個々の画像を抽出するためにPicasa APIを使用した自動フェイス検出
-
28-09-2019 - |
質問
(アプリケーションに関連する回答について、スーパーユーザーに同様の質問が尋ねられました。質問は、プログラム可能なソリューションを収集するためにここに投稿されています)
私の職場では、パスポートサイズの写真が一緒にスキャンされ、個々の写真に切り分けられ、一意のファイル番号で保存されます。現在、paint.netを使用して、写真を手動で選択、カット、保存しています。
サンプルスキャンドキュメントPicasaスクリーンショット:(From:Google Image Search複数のソース、Firuse)
例えば。 Picasa 3.8では、ビュー>人々をクリックして、すべての顔が表示され、名前を付けてもらうように頼まれます。これらの個々の写真を別の写真として自動的に保存できますか?
更新しました
私がやりたいのは、上の写真を個々の写真に変換することだけです。
上の画像では、Picasa 3.8が画像をどのように検出し、それらに名前を付けるように促す方法を示しました。顔の認識は必要ありません。単に顔の検出が必要です。 Picasaは個々の画像を検出し、RHSに表示します。これらの個々の画像は私が必要とするものです。 Picasaは、個々の顔の座標を含む16進値を保存する.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
各タグに対して。から引用 ピカサヘルプサイト ユーザー Technonath 言う
@oediousは次のように書いています。 * rect64()に囲まれた数値は、64ビットの16進数です。 *それを4つの16ビット番号に分割します。 *それぞれを最大符号なしの16ビット数(65535)で割ると、0から1の間に4つの数値があります。 *絶対座標になってしまう場合は、画像幅で左右に複数と画像の高さで上部と下部になります。
上記の引用では、rect64()に包まれた数について説明しています。
関連する質問をしました。その答えもあなたを助けるかもしれません。64ビットヘックス値から4つの16ビット番号を取得します
注:INIの詳細は、Picasaが特定の画像に対して生成したものと同じです。
さらに、質問は複数回更新されており、十分に明確ではない場合があります。
にいくつかの応答があります ピカサヘルプサイト, 、そこで、INIファイルの16進値に基づいて、そのスレッドからの回答の1つを尋ねました。次のコードは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.9463348383887 REPEANDER 1:19598;結果1:0.29904174804688 Co-ordinates:147.12854003906 156.99691772461 LESTER 1:62471;結果1:0.95323181152344座標:468.99005126953 500.4467010498残り1:34078;結果1:0.51998901367188座標:255.83459472656 272.99423217773
だから私には座標もあり、@nirmalにあります それらを収穫する方法を示しました. 。次のステップは、hexコードとファイル名をpicasa.iniに解析し、コードを統合することです。 Picasaは現在、APIを介して16進コードを提供していません(または 彼らは?)。もしそうなら、物事はもっと良かったでしょう。
だから私たちは解決策に近づいています。どうもありがとうございました、私は皆に賞金を授与することができたらいいのにと思います(私はできませんが、恐れず、あなたの担当者のスパイクを探してください!)
解決
Picasaの質問に答えるには、Picasaフォーラムでこの回答を参照してください。
http://www.google.com/support/forum/p/picasa/thread?tid=36ae553a7b49088e&hl=en
@oediousは次のように書いています。 * rect64()に囲まれた数値は、64ビットの16進数です。 *それを4つの16ビット番号に分割します。 *それぞれを最大符号なしの16ビット数(65535)で割ると、0から1の間に4つの数値があります。 *絶対座標になってしまう場合は、画像幅で左右に複数と画像の高さで上部と下部になります。
他のヒント
見る opencv - 分布に伴う例の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
}
}
トリミング部分については、テストせずにコードを入力していますが、これは機能するはずです。
<?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
ソースコードも利用できます。
私は彼らの16進コードから連絡先の名前を取得することを実装していませんが、Google連絡先APIを使用して可能です: http://code.google.com/apis/contacts/
そのAPIを使用すると、IDで連絡先を取得することができ、PicasaとGoogleの連絡先の間で連絡先が同期されている場合、16進IDは同じです。
完全な連絡先リンクの最後の部分は、Picasaが使用する16進数です。
これが役立つことを願っています。
乾杯、フェリペ。