使用picasa api提取单个图像的自动面部检测
-
28-09-2019 - |
题
(在Superuser上提出了类似的问题以寻求与应用程序有关的答案。此处发布的问题是为了收集相同的可编程解决方案)
在我的工作场所,护照尺寸的照片被一起扫描,然后将其切成单独的图片并用独特的文件编号保存。目前,我们使用Paint.net手动选择,剪切和保存图片。
样品扫描文档Picasa屏幕截图:(来自:Google Image搜索多个来源,Fairuse)
例如。在Picasa 3.8中,单击视图>人们,所有的面孔都显示出来,我被要求将它们命名,我可以用名称作为不同的图片自动保存这些单独的图片吗?
更新
我要做的就是将上图转换为单个图片。
在上图中,我显示了Picasa 3.8如何检测图像并提示我命名它们。我不需要面部识别,我只需要面部检测即可。 Picasa检测到各个图像并在RHS上显示它们。这些单独的图像是我需要的。 Picasa创建了一个.ini文件,该文件保存了包含单个面部坐标的十六进制值。
这些个人面孔是我感兴趣的,如果我可以拥有坐标,我可以从图片中裁剪所需的图像。
样本
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帮助网站 用户 技术 说
@Oedious写道: - 这将是有些技术性的,所以请坚持下去。 *包含在Rect64()中的数字是64位十六进制数。 *将其分解为四个16位数字。 *将每个分配除以最大未签名的16位数字(65535),您将有四个数字在0和1之间。 *如果要以绝对的坐标结束,则通过图像宽度以及图像高度的顶部和底部多倍左右。
上面的报价谈论了rect64()中包含的数字,逗号后括号之外的数字呢?
我问了一个相关的问题。答案也可能对您有所帮助。从64位十六进制中获取四个16位数字
注意:INI详细信息与Picasa为特定图像生成的详细信息相同。
加上问题已多次更新,可能还不够清楚。
有一些回应 Picasa帮助网站, ,我问了同样的问题,该线程中的一个答案之一是根据INI文件中的十六进制值获得坐标。以下代码在C#中 ESAC 来自帮助网站。我可以在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之间的数字
<?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/>";
}
?>
输出
其余1:49551;结果1:0.75608825683594坐标:371.99542236328 396.94633348387剩余1:19598;结果1:0.29904174804688坐标:147.12854003906 156.99691772461剩余1:62471;结果1:0.95323181152344坐标:468.99005126953 500.4467010498剩余1:34078;结果1:0.51998901367188坐标:255.83459472656 272.99423217773
所以我也有坐标, @nirmal有 显示如何裁剪它们. 。现在,下一步将是对十六进制代码和文件名来解析picasa.ini并集成代码。 Picasa当前未通过API提供十六进制代码(或 他们吗?)。如果是这样,情况会更好。
因此,我们正在接近解决方案。谢谢大家,我希望我能将赏金授予每个人(我不能,但不要害怕,并在您的代表中寻找尖峰!)
解决方案
要回答Picasa问题,请在Picasa论坛上查看此回答:
http://www.google.com/support/forum/p/picasa/thread?tid=36ae553a7b49088e&hl = en
@Oedious写道: - 这将是有些技术性的,所以请坚持下去。 *包含在Rect64()中的数字是64位十六进制数。 *将其分解为四个16位数字。 *将每个分配除以最大未签名的16位数字(65535),您将有四个数字在0和1之间。 *如果要以绝对的坐标结束,则通过图像宽度以及图像高度的顶部和底部多倍左右。
其他提示
看着 OPENCV - 分布随附的示例之一是用于面部检测。
您对问题的解决方案是过度杀伤。忽略面孔。您拥有的是白色背景和一堆矩形图像。您需要做的就是找到包含每个图像和作物的矩形。
首先通过标记所有非背景像素的原始图像运行过滤器。这将需要一些调整,因为有时背景会带有淡淡的色彩(污垢),否则照片将带有一些像背景的像素,看起来像背景(真的是洁白的牙齿)。
现在,您在其中寻找没有背景颜色的大区域。将它们裁剪成矩形。
既然您是进行扫描的人,为什么不使背景绿色呢?绿色可能是更容易过滤的颜色,尤其是因为护照照片是在白色背景上拍摄的。
您可以进一步简化问题:-)如果扫描的图像始终在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
}
}
对于裁剪部分,我在不进行测试的情况下输入代码,但这应该有效:
<?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
源代码也可用。
虽然我尚未实施从其十六进制代码中获取联系人的名称,但可以使用Google Contacts API: http://code.google.com/apis/contacts/
使用该API,可以通过ID获得联系人,如果您的联系人在Picasa和Google联系人之间同步,则十六进制ID是相同的。
完整触点链接的最后一部分是Picasa使用的十六进制。
我希望这有帮助。
欢呼,费利佩。