Php 使用Picasa API提取单个图像的自动人脸检测
(superuser上也有类似的问题,需要与应用程序相关的答案。发布此问题的目的是收集相同应用程序的可编程解决方案) 在我的工作场所,护照大小的照片被扫描在一起,然后切割成单独的照片,并用唯一的文件号保存。目前,我们使用Paint.net手动选择、剪切和保存图片 样本扫描文档Picasa屏幕截图: (来源:谷歌图片搜索多源,fairuse) 例如,在Picasa 3.8中,单击“查看”>“人物”,将显示所有人脸,并要求我为其命名,我是否可以将这些单独的图片自动保存为不同的图片 已更新 我想做的就是将上面的图片转换为单独的图片。 在上图中,我展示了Picasa 3.8如何检测图像并提示我命名它们。我不需要人脸识别,我只需要人脸检测。Picasa检测单个图像并将其显示在RHS上。这些单独的图像是我需要的。Picasa创建一个.ini文件,保存包含各个面坐标的十六进制值 这些单独的面孔是我感兴趣的,如果我有坐标,我可以从图片中裁剪出所需的图像 SAMPLE.jpg ini内容Php 使用Picasa API提取单个图像的自动人脸检测,php,api,picasa,face-recognition,Php,Api,Picasa,Face Recognition,(superuser上也有类似的问题,需要与应用程序相关的答案。发布此问题的目的是收集相同应用程序的可编程解决方案) 在我的工作场所,护照大小的照片被扫描在一起,然后切割成单独的照片,并用唯一的文件号保存。目前,我们使用Paint.net手动选择、剪切和保存图片 样本扫描文档Picasa屏幕截图: (来源:谷歌图片搜索多源,fairuse) 例如,在Picasa 3.8中,单击“查看”>“人物”,将显示所有人脸,并要求我为其命名,我是否可以将这些单独的图片自动保存为不同的图片 已更新 我想做的
[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
。
引用用户的话
@oedious写道:这将是
有点技术性,所以等一下。
*包含在rect64()中的数字是64位十六进制数。
*将其分解为四个16位数字。
*将每个值除以最大无符号16位数字(65535),得到
四个介于0和1之间的数字。
*剩下的四个数字为您提供了面的相对坐标
矩形:(左、上、右、下)。
*如果希望以绝对坐标结束,请将左、右坐标乘以
右边是图像宽度和顶部
和底部的图像高度
上面的引文谈到了包含在rect64()中的数字逗号后括号外的数字呢
我问了一个相关的问题。这些问题的答案也可能对你有所帮助。
注:该
ini细节与picasa相同
为特定图像生成
此外,该问题已被更新多次,可能不够清楚
在会议上有一些回答,我问了同样的问题
来自该线程的一个答案,用于根据ini文件中的十六进制值获取坐标。下面的代码是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之间的数字
<?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.7560882568359594坐标:371.99542236328396.94633483887剩余1:19598;结果1:
0.29904174804688坐标:147.12854003906156.99691772461剩余1:62471;结果1:
0.95323181152344坐标:468.99005126953500.4467010498剩余1:34078;结果1:
0.51998901367188坐标:255.83459472656272.99423217773
所以我也有坐标,@Nirmal也有。接下来的步骤是解析picasa.ini中的十六进制代码和文件名,并集成代码。Picasa目前没有通过api(或)提供十六进制代码。如果是这样,情况会更好
因此,我们正在接近解决办法。谢谢大家,我希望我能将奖金奖励给每个人(我不能,但我不担心,并注意你的代表中是否有尖峰!)你可以进一步简化这个问题:-)如果扫描的图像总是在5x4网格中。。。然后,您可以轻松地只需用几乎任何提供位图操作的编程语言打开图像,然后保存每个方块。下面是一个如何使用C#执行此操作的示例: 您需要做的就是计算每个矩形,然后调用此方法,该方法只返回矩形定义的图像区域。类似(可能是伪代码,尚未编译下面的代码):
//假设较大图像中的每个子图像为45x65
int cellwidth=45,cellheight=65;
对于(int row=0;row查看-发行版附带的一个示例是人脸检测。要回答picasa问题,请参阅picasa论坛上的以下回复:
@oedious写道:这将是
有点技术性,所以等一下。
*包含在rect64()中的数字是64位十六进制数。
*将其分解为四个16位数字。
*将每个值除以最大无符号16位数字(65535),得到
四个介于0和1之间的数字。
*剩下的四个数字为您提供了面的相对坐标
矩形:(左、上、右、下)。
*如果希望以绝对坐标结束,请将左、右坐标乘以
右边是图像宽度和顶部
和底部的图像高度
你解决这个问题的方法太过分了。忽略这些面。你拥有的是一个纯白的背景和一堆矩形图像。你所需要做的就是找到包围每个图像的矩形并进行裁剪
首先,在标记所有非背景像素的原始图像上运行一个过滤器。这需要一些调整,因为有时背景中会有一点色调(污垢),或者照片中会有一些看起来像背景的像素(真正的白色牙齿)
现在你要寻找没有背景色的大区域,把它们裁剪成矩形
既然是你在做扫描,为什么不把背景变成绿色呢?绿色可能更容易过滤,尤其是在通过扫描之后
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);
?>
<?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/>";
}
}