自动人脸检测
(A类似的问题已经被问对超级用户与应用程序相关的答案。问题是张贴在这里收集了相同的可编程解决方案)自动人脸检测
在我的工作将护照尺寸的照片一起扫描,然后剪切成单独的照片并用唯一的文件编号保存。目前我们使用Paint.net手动选择,剪切和保存图片。
样品扫描的文档的Picasa截图: (来自:谷歌图像搜索多个数据源,fairuse)
对于例如。在Picasa 3.8中,单击视图>人员时,会显示所有人脸,并要求我为他们命名,我是否可以将这些个人图片自动保存为不同图片的名称?
更新
所有我想要做的就是上面的转换对单张照片的画面。
在上面的图片中,我已经展示了Picasa 3.8如何检测图像并提示我命名它们。我不需要脸部识别,我只需要脸部识别。 Picasa会检测单个图像并在RHS上显示它们。这些个人图像是我需要的。 Picasa创建一个.ini文件,该文件保存包含各个面的坐标的十六进制值。
这些个人面孔是我感兴趣的如果我可以有坐标,我可以从图片中裁剪所需的图像。
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?)。如果是这样,事情会更好。
所以我们正在接近一个解决方案。谢谢大家,我希望我能把赏金奖励给大家(我不能,但不要害怕,并且不要在你的代表中出现尖峰!)
要回答这个问题的Picasa,看到Picasa的论坛上这样回应:
http://www.google.com/support/forum/p/Picasa/thread?tid=36ae553a7b49088e&hl=en
@oedious写道: - 这将是 有些技术性的,所以坚持下去。 *包含在rect64()中的数字是一个64位的十六进制数。 *将其分成四个16位数字。 *将每个数除以最大无符号16位数(65535),并且您将有 四个数字,介于0和1之间。 *剩余的四个数字将为您提供相对坐标 矩形:(左,上,右,底部)。 *如果您想要以绝对坐标结束,请将图像宽度和顶部 的左侧和右侧多余,然后按图像高度底部。
你可以进一步简化问题:-)如果扫描的图像将总是在一个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
}
}
你对这个问题的解决方法是矫枉过正。忽略脸部。你有什么是坚实的白色背景和一堆矩形图像。所有你需要做的是找到包围每个图像和裁剪的矩形。
首先在标记所有非背景像素的原始图像上运行过滤器。这将需要一些调整,因为有时背景会有一点色调(污垢)或照片将有一些看起来像背景像素(真的是白色的牙齿)。
现在,您可以查看其中没有背景色的大面积区域。将它们裁剪成矩形。
既然你是一个正在做扫描的人,为什么不让背景变成绿色?绿色可能是一种更容易过滤的颜色,特别是因为护照照片是在白色背景上拍摄的。
+1让我以不同的角度看待问题。制作绿色背景将非常简单,我期待开发一个php webapp,它将在本地服务器上运行,该服务器将扫描的img作为上传文件,然后将各个照片保存在服务器上,并将其作为一个zip下载。有没有PHP libs(gd?)这将允许我检测颜色和选择rects? – abel 2010-10-13 11:45:09
我不知道是否有库。但是,必须有库才能加载图像并处理其中的颜色。从背景开始,如绿色> 90%,红色和蓝色 Eyal 2010-10-13 13:41:36
我已经更新了这个问题。用一个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格式和坐标做一个完美的矩形或正方形。
希望有所帮助。
这应该让你越过终点线。这里有一些解析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。
好的工作!没有想到联系人整合;这是一个附加。尽管取决于Picasa获得rect格式是痛苦的。希望有一个API! – abel 2011-03-09 13:42:28
你可以给所有四个角的'(x,y)'格式的最终坐标吗? – Nirmal 2010-10-14 07:56:52
@Nirmal(371,156),(468,156),(468,272),(371,272) – abel 2010-10-14 08:25:35