10

(アプリケーションに関連する回答について、スーパーユーザーに同様の質問があります。質問は、同じプログラム可能なソリューションを収集するためにここに投稿されます)

私の職場では、パスポートサイズの写真を一緒にスキャンしてから、個々の写真に切り分けて、一意のファイル番号で保存しています。現在、Paint.netを使用して、画像を手動で選択、切り取り、保存しています。

スキャンしたドキュメントのサンプルPicasaスクリーンショット:( 差出人:Google画像検索の複数のソース、フェアユース)

picasaのスクリーンショット

たとえば。Picasa 3.8では、[表示]> [人物]をクリックすると、すべての顔が表示され、名前を付けるように求められます。これらの個々の画像を別の画像として名前とともに自動的に保存できますか?

更新しました

私がやりたいのは、上の写真を個々の写真に変換することだけです。

上の画像では、Picasa 3.8が画像を検出し、名前を付けるように求めるメッセージを示しています。顔認識は必要ありません。顔検出が必要です。Picasaは個々の画像を検出し、RHSに表示します。これらの個々の画像は私が必要としているものです。Picasaは、個々の面の座標を含む16進値を保存する.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

rect64(534a06d429ae627),dff6163dfd9d4e41* iniファイルは、各タグの顔タグの座標を保存しているようです。PicasaヘルプサイトのユーザーTechnonathからの引用

@oediousは次のように書いています:-これはやや技術的なことになるので、しばらくお待ちください。* rect64()に含まれる数値は、64ビットの16進数です。*それを4つの16ビット数に分割します。*それぞれを最大の符号なし16ビット数(65535)で割ると、0から1までの4つの数になります。*残りの4つの数は、面の長方形の相対座標を示します:(左、上、右、下)。※絶対座標にしたい場合は、左右に画像幅、上下に画像高さを掛けてください。

上記の引用は、rect64()で囲まれた数値について説明していますが、コンマの後の括弧の外側の数値についてはどうでしょうか。

関連する質問をしました。その答えもあなたを助けるかもしれません。 64ビットの16進値から4つの16ビット数値を取得します

注:iniの詳細は、picasaが特定の画像に対して生成したものと同じです。

さらに、質問は複数回更新されており、十分に明確ではない可能性があります。

Picasaヘルプサイトにいくつかの回答があります。同じ質問をしました。そのスレッドからの回答の1つは、iniファイルの16進値に基づいて座標を取得することです。次のコードは、ヘルプサイトの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);
} 

64ビットを1から0までの数値に変換しようとするPHPコード

<?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.94633483887剰余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はそれらをトリミングする方法を示しました。次のステップは、16進コードとファイル名についてpicasa.iniを解析し、コードを統合することです。Picasaは現在、APIを介して16進コードを提供していません(またはそれらはありますか?)。もしそうなら、物事はもっと良かったでしょう。

ですから、私たちは解決に近づいています。みなさん、ありがとうございました。みんなに賞金を授与できたらいいのにと思います(できませんが、恐れることはなく、担当者の急増に注意してください!)

4

7 に答える 7

5

OpenCVを見てください-ディストリビューションに付属している例の1つは、顔検出用です。

于 2010-10-06T12:18:43.290 に答える
5

問題に対するあなたの解決策はやり過ぎです。顔を無視します。あなたが持っているのは、無地の白い背景とその上にたくさんの長方形の画像です。あなたがする必要があるのは、各画像を囲む長方形を見つけてトリミングすることです。

すべての非背景ピクセルをマークする元の画像に対してフィルターを実行することから始めます。背景に少し色合いがある場合(汚れ)や、写真に背景のように見えるピクセル(実際には白い歯)がある場合があるため、これにはある程度の調整が必要です。

ここで、背景色のない広い領域を探します。それらを長方形に切り取ります。

あなたがスキャンをしているので、背景を緑にしてみませんか?特にパスポート写真は白い背景で撮影されているため、緑の方がフィルタリングしやすい色になる可能性があります。

于 2010-10-13T10:25:47.010 に答える
3

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つの数になります。*残りの4つの数は、面の長方形の相対座標を示します:(左、上、右、下)。※絶対座標にしたい場合は、左右に画像幅、上下に画像高さを掛けてください。

于 2010-10-08T15:21:29.757 に答える
2

問題をさらに単純化することができます:-)スキャンされた画像が常に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
  }
}
于 2010-10-06T12:04:16.763 に答える
1

トリミング部分については、テストせずにコードを入力していますが、これは機能するはずです。

<?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形式であり、座標が完全な長方形または正方形になることを前提としています。

お役に立てば幸いです。

于 2010-10-14T10:24:22.537 に答える
1

これにより、フィニッシュラインを越えることができます。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/>";
    }
}
于 2010-10-18T09:49:53.227 に答える
1

私はあなたが言ったことを正確に実行する.NETで小さなアプリを開発しました。それは顔のファイルを生成します。ここでそれをチェックしてください: http: //ceottaki.com/devprojects/getpicasafaces

ソースコードも利用できます。

16進コードから連絡先の名前を取得することは実装していませんが、GoogleコンタクトAPIを使用して可能です:http ://code.google.com/apis/contacts/

このAPIを使用すると、IDで連絡先を取得できます。連絡先がPicasaとGoogleの連絡先の間で同期されている場合、16進数のIDは同じです。

完全な連絡先リンクの最後の部分は、Picasaで使用される16進数です。

これがお役に立てば幸いです。

乾杯、フェリペ。

于 2011-03-08T16:42:06.790 に答える