自动人脸检测

问题描述:

(A类似的问题已经被问对超级用户与应用程序相关的答案。问题是张贴在这里收集了相同的可编程解决方案)自动人脸检测

在我的工作将护照尺寸的照片一起扫描,然后剪切成单独的照片并用唯一的文件编号保存。目前我们使用Paint.net手动选择,剪切和保存图片。

样品扫描的文档的Picasa截图: (来自:谷歌图像搜索多个数据源,fairuse)

picasa screenshot

对于例如。在Picasa 3.8中,单击视图>人员时,会显示所有人脸,并要求我为他们命名,我是否可以将这些个人图片自动保存为不同图片的名称?

更新

所有我想要做的就是上面的转换对单张照片的画面。

在上面的图片中,我已经展示了Picasa 3.8如何检测图像并提示我命名它们。我不需要脸部识别,我只需要脸部识别。 Picasa会检测单个图像并在RHS上显示它们。这些个人图像是我需要的。 Picasa创建一个.ini文件,该文件保存包含各个面的坐标的十六进制值。

这些个人面孔是我感兴趣的如果我可以有坐标,我可以从图片中裁剪所需的图像。

SAMPLE.jpg

sample.jpg

INI内容

[SAMPLE.jpg] 
faces=rect64(c18f4c8ef407851e),d4ff0a020be5c3c0;rect64(534a06d429ae627),dff6163dfd9d4e41;rect64(b9c100fae46b3046),e1059dcf6672a2b3;rect64(7b5105daac3a3cf4),4fc7332c107ffafc;rect64(42a036a27062a6c),ef86c3326c143248;rect64(31f4efe3bd68fd8),90158b3d3b65dc9b;rect64(327904e0614d390d),43cbda6e92fcb63e;rect64(4215507584ae9b8c),15b6a967e857f334;rect64(895d4efeb8b68425),5c4ff70ac70b27d3 
backuphash=3660 

* ini文件似乎是保存面子标签的坐标为rect64(534a06d429ae627),dff6163dfd9d4e41每个标签。 从Picasa Help Site用户Technonath引述说

@oedious写道: - 这将是 有些技术性的,所以坚持下去。 *包含在rect64()中的数字是一个64位的十六进制数。 *将其分成四个16位数字。 *将每个数除以最大无符号16位数(65535),并且您将有 四个数字,介于0和1之间。 *剩余的四个数字将为您提供相对坐标 矩形:(左,上,右,底部)。 *如果您想要以绝对坐标结束,请将图像宽度和顶部 的左侧和右侧多余,然后按图像高度底部。

上面的引用谈到了rect64()中包含的数字,逗号后的圆括号之外的数字是什么?

我已经问了一个相关的问题。其中的答案也可以帮助你。 Get four 16bit numbers from a 64bit hex value

注: INI细节其PICASA用于特定图像生成 相同。

此问题已更新多次,可能不够清楚。

有在Picasa Help site,在那里我问同样的问题 一位来自该线程的答案,我们将根据从ini文件中的十六进制值坐标的一些回应。以下代码位于帮助站点的esac的C#中。我可以在PHP中执行相同的操作吗?

public static RectangleF GetRectangle(string hashstr) 
{ 
    UInt64 hash = UInt64.Parse(hashstr, System.Globalization.NumberStyles.HexNumber); 
    byte[] bytes = BitConverter.GetBytes(hash); 

    UInt16 l16 = BitConverter.ToUInt16(bytes, 6); 
    UInt16 t16 = BitConverter.ToUInt16(bytes, 4); 
    UInt16 r16 = BitConverter.ToUInt16(bytes, 2); 
    UInt16 b16 = BitConverter.ToUInt16(bytes, 0); 

    float left = l16/65535.0F; 
    float top = t16/65535.0F; 
    float right = r16/65535.0F; 
    float bottom = b16/65535.0F; 

    return new RectangleF(left, top, right - left, bottom - top); 
} 

PHP代码试图转换到64位的数字1和0剩余1之间

<?php 
$dim = getimagesize("img.jpg");  
$hex64=array(); 
$b0="c18f4c8ef407851e"; 
$hex64[]=substr($b0,0,4); 
$hex64[]=substr($b0,4,4); 
$hex64[]=substr($b0,8,4); 
$hex64[]=substr($b0,12,4); 
$width=$dim[0]; 
$height=$dim[1]; 
foreach($hex64 as $hex16){ 
$dec=hexdec($hex16); 
$divide=65536; 
$mod=$dec%$divide; 
$result=$dec/$divide; 
$cordinate1=$result*$width; 
$cordinate2=$result*$height; 
echo "Remainder 1 : ".$mod." ; Result 1 : ".$result."<br/>CO-ORDINATES : <B>".$cordinate1." ".$cordinate2."</B><br/>"; 
} 
?> 

输出

:49551;结果1: 0.75608825683594副标题:371.99542236328 396.94633483887剩余1:19598;结果1: 0.29904174804688副标题:147.12854003906 156.99691772461剩余1:62471;结果1: 0.95323181152344 CO-ORDINATES:468.99005126953 500.4467010498剩余1:34078;结果1: 0.51998901367188坐标:255.83459472656 272.99423217773

所以我有坐标也和@Nirmal有shown how to crop them。现在接下来的步骤是解析picasa.ini中的十六进制代码和文件名并整合代码。 Picasa目前不通过api提供十六进制代码(或Do they?)。如果是这样,事情会更好。

所以我们正在接近一个解决方案。谢谢大家,我希望我能把赏金奖励给大家(我不能,但不要害怕,并且不要在你的代表中出现尖峰!)

+0

你可以给所有四个角的'(x,y)'格式的最终​​坐标吗? – Nirmal 2010-10-14 07:56:52

+0

@Nirmal(371,156),(468,156),(468,272),(371,272) – abel 2010-10-14 08:25:35

要回答这个问题的Picasa,看到Picasa的论坛上这样回应:
http://www.google.com/support/forum/p/Picasa/thread?tid=36ae553a7b49088e&hl=en

@oedious写道: - 这将是 有些技术性的,所以坚持下去。 *包含在rect64()中的数字是一个64位的十六进制数。 *将其分成四个16位数字。 *将每个数除以最大无符号16位数(65535),并且您将有 四个数字,介于0和1之间。 *剩余的四个数字将为您提供相对坐标 矩形:(左,上,右,底部)。 *如果您想要以绝对坐标结束,请将图像宽度和顶部 的左侧和右侧多余,然后按图像高度底部。

+0

这是一个宝贵的链接。谢谢。如果你已经理解了我的问题,我试图将扫描后的img分解为单个imgs。如果我有坐标,我可以为Paint.net编写一个插件,它可以做到这一点(我没有任何桌面编程经验,所以这可能需要几个月的时间,当它完成后会发布一个链接:)。) – abel 2010-10-08 15:29:27

+0

我如何从64位的一个16位数字? – abel 2010-10-08 15:35:13

你可以进一步简化问题:-)如果扫描的图像将总是在一个5x4的网格...然后你可以很容易只是在任何提供位图操作的编程语言中打开图像,并保存每个正方形。这里有一个如何用C#做这样一个例子:

private Image Crop(Image pics, Rectangle area) 
{ 
    var bitmap = new Bitmap(pics); 
    return (Image)bitmap.Clone(area, bitmap.PixelFormat); 
} 

所有你需要做的是计算每个矩形,然后调用该方法返回由矩形定义的图像的只是区域。喜欢的东西(可能是伪代码,没有编译下面的代码):

// assuming that each sub image in the larger is 45x65 
int cellwidth=45, cellheight=65; 

for(int row=0;row<5;row++) 
{ 
    for(int col=0;col<4;col++) 
    { 
    var rect = new Rectangle(
     row * cellwidth, 
     col * cellheight, 
     cellwidth, 
     cellheight); 
    var picture = Crop(bigPicture, rect); 
    // then save the sub image with whatever naming convention you need 
    } 
} 
+0

但护照照片大小各不相同。一些是5厘米乘4厘米,一些4乘3厘米,4x4等,并将它们放置在扫描仪中通常会造成随意安排。如果我可以检测图像的标记部分,然后裁剪出来...我可以做一些PHP。 – abel 2010-10-06 12:12:06

+0

我已经更新了原来的问题,如果我可以有坐标,你的解决方案看起来似乎是合理的。但坐标是在十六进制,我不明白十六进制, – abel 2010-10-12 17:12:51

OpenCV - 中附带的分布是人脸检测的例子之一。

+0

谢谢我会考虑它 – abel 2010-10-06 12:21:04

+1

我正在寻找这样一个图书馆很长一段时间,看起来像这会帮助。感谢分享。 – Nirmal 2010-10-18 06:41:58

你对这个问题的解决方法是矫枉过正。忽略脸部。你有什么是坚实的白色背景和一堆矩形图像。所有你需要做的是找到包围每个图像和裁剪的矩形。

首先在标记所有非背景像素的原始图像上运行过滤器。这将需要一些调整,因为有时背景会有一点色调(污垢)或照片将有一些看起来像背景像素(真的是白色的牙齿)。

现在,您可以查看其中没有背景色的大面积区域。将它们裁剪成矩形。

既然你是一个正在做扫描的人,为什么不让背景变成绿色?绿色可能是一种更容易过滤的颜色,特别是因为护照照片是在白色背景上拍摄的。

+0

+1让我以不同的角度看待问题。制作绿色背景将非常简单,我期待开发一个php webapp,它将在本地服务器上运行,该服务器将扫描的img作为上传文件,然后将各个照片保存在服务器上,并将其作为一个zip下载。有没有PHP libs(gd?)这将允许我检测颜色和选择rects? – abel 2010-10-13 11:45:09

+0

我不知道是否有库。但是,必须有库才能加载图像并处理其中的颜色。从背景开始,如绿色> 90%,红色和蓝色 Eyal 2010-10-13 13:41:36

+0

我已经更新了这个问题。用一个php脚本获取(?)图像坐标。我可以使用这些从图像中裁剪单个图像吗? – abel 2010-10-13 17:52:38

对于裁剪的部分,我打字未经测试的代码,但这应该工作:

<?php 
//source image 
$srcImg = "full/path/of/source/image.jpg"; 
//output image 
$outImg = "full/path/to/result/image.jpg"; 

//coordinates obtained from your calculation 
$p1 = array('X'=>371, 'Y'=>156); 
$p2 = array('X'=>468, 'Y'=>156); 
$p3 = array('X'=>468, 'Y'=>272); 
$p4 = array('X'=>371, 'Y'=>272); 

//let's calculate the parametres 
$srcX = $p1['X']; 
$srcY = $p1['Y']; 
$width = $p2['X'] - $p1['X']; 
$height = $p4['Y'] - $p1['Y']; 

//image processing 
$srcImg = imagecreatefromjpeg($srcImg); 
$dstImg = imagecreatetruecolor($width, $height); 
imagecopy($dstImg, $srcImg, 0, 0, $srcX, $srcY, $width, $height); 
imagejpeg($dstImg, $outImg, 100); // 100 for highest quality, 0 for lowest quality 
imagedestroy($dstImg); 
?> 

上面的代码假定您的源图像是JPEG格式和坐标做一个完美的矩形或正方形。

希望有所帮助。

+0

谢谢你nirmal。我正在探索PHP的图像处理库。竖起大拇指! – abel 2010-10-14 11:39:23

+0

不客气。很高兴有帮助。 – Nirmal 2010-10-18 06:21:09

这应该让你越过终点线。这里有一些解析INI的代码。

<?php 
$vals = parseIni('picasa.ini'); 
foreach($vals as $filename => $values) { 
    $rects = getRects($values['faces']); 
    foreach($rects as $rect) { 
     printImageInfo($filename, $rect); 
    } 
} 

/** 
* PHP's own parse_ini_file doesn't like the Picasa format. 
*/ 
function parseIni($file) 
{ 
    $index = 0; 
    $vals = array(); 
    $f = fopen($file, 'r'); 
    while(!feof($f)) { 
     $line = trim(fgets($f)); 
     if (preg_match('/^\[(.*?)\]$/', $line, $matches)) { 
      $index = $matches[1]; 
      continue; 
     } 

     $parts = explode('=', $line, 2); 
     if (count($parts) < 2) continue; 
     $vals[$index][$parts[0]] = $parts[1]; 
    } 

    fclose($f); 
    return $vals; 
} 

function getRects($values) 
{ 
    $values = explode(';', $values); 
    $rects = array(); 
    foreach($values as $rect) { 
     if (preg_match('/^rect64\(([^)]+)\)/', $rect, $matches)) { 
      $rects[] = $matches[1]; 
     } 
    } 

    return $rects; 
} 

function printImageInfo($filename, $rect) 
{ 
    $dim = getimagesize($filename);  
    $hex64=array(); 
    $hex64[]=substr($rect,0,4); 
    $hex64[]=substr($rect,4,4); 
    $hex64[]=substr($rect,8,4); 
    $hex64[]=substr($rect,12,4); 
    $width=$dim[0]; 
    $height=$dim[1]; 
    foreach($hex64 as $hex16){ 
     $dec=hexdec($hex16); 
     $divide=65536; 
     $mod=$dec%$divide; 
     $result=$dec/$divide; 
     $cordinate1=$result*$width; 
     $cordinate2=$result*$height; 
     echo "Remainder 1 : ".$mod." ; Result 1 : ".$result."<br/>CO-ORDINATES : <B>".$cordinate1." ".$cordinate2."</B><br/>"; 
    } 
} 

我在.NET中开发了一个小应用程序,它完全按照您的说法生成脸部文件。看看这里:http://ceottaki.com/devprojects/getpicasafaces

源代码也可用。

虽然我还没有实现正从他们的十六进制代码的联系人的姓名,也可以使用谷歌联系人API:http://code.google.com/apis/contacts/

随着该API就可以得到由ID接触,如果你的联系人在Picasa和Google通讯录之间同步,十六进制ID是相同的。

完整联系人链接的最后一部分是Picasa使用的十六进制。

我希望这会有所帮助。

干杯, Felipe。

+1

好的工作!没有想到联系人整合;这是一个附加。尽管取决于Picasa获得rect格式是痛苦的。希望有一个API! – abel 2011-03-09 13:42:28