اكتشاف الوجه التلقائي باستخدام Picasa API لاستخراج الصور الفردية

StackOverflow https://stackoverflow.com/questions/3872112

سؤال

(تم طرح سؤال مماثل على Superuser للحصول على إجابات تتعلق بالتطبيقات. يتم نشر السؤال هنا لجمع حلول قابلة للبرمجة لنفسه)

في مكان عملي ، يتم مسح الصور الفوتوغرافية بحجم جواز السفر معًا ، ثم تقطعها إلى صور فردية وحفظها بأرقام ملفات فريدة. حاليًا نستخدم Paint.net لتحديد الصور وقطعها يدويًا.

عينة وثيقة ممسوحة ضوئيا لقطة شاشة بيكاسا:(من: Google Image Search Mustraces ، Fairuse)

picasa screenshot

على سبيل المثال. في Picasa 3.8 ، عند النقر فوق "عرض> الأشخاص ، يتم عرض جميع الوجوه ويُطلب مني تسميتها ، هل يمكنني حفظ هذه الصور الفردية تلقائيًا بالأسماء كصور مختلفة؟

محدث

كل ما أريد فعله هو تحويل الصورة أعلاه إلى صور فردية.

في الصورة أعلاه ، أظهرت كيف يكتشف Picasa 3.8 الصور ويطالبني بتسميةها. لست بحاجة إلى التعرف على الوجه ، أنا ببساطة بحاجة إلى اكتشاف الوجه. يكتشف بيكاسا الصور الفردية ويظهرها على RHS. هذه الصور الفردية هي ما أحتاجه. تقوم Picasa بإنشاء ملف .ini الذي يحفظ قيم Hex التي تحتوي على إحداثيات الوجوه الفردية.

هذه الوجوه الفردية هي ما أهتم به إذا كان بإمكاني الحصول على إحداثيات ، يمكنني قصف الصور المطلوبة من الصورة.

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

*يبدو أن ملف INI يحفظ إحداثيات علامات الوجه مثل rect64(534a06d429ae627),dff6163dfd9d4e41 لكل علامة. نقلا عن موقع مساعدة بيكاسا المستعمل Technonath يقول

كتب Oedious:- سيكون هذا تقنيًا إلى حد ما ، لذا تمسك. * الرقم المغطى في rect64 () هو رقم سداسي عشري 64 بت. * كسر ذلك إلى أربعة أرقام 16 بت. * قسّم كل منها على الحد الأقصى لعدد 16 بت غير موقّع (65535) وسيكون لديك أربعة أرقام بين 0 و 1. * تمنحك الأرقام الأربعة المتبقية إحداثيات نسبية لمستطيل الوجه: (يسار ، أعلى ، يمين ، أسفل). * إذا كنت تريد أن ينتهي الأمر بإحداثيات مطلقة ، فالأمر الأيسر واليمين بعرض الصورة والأعلى والسفلي بواسطة ارتفاع الصورة.

يتحدث الاقتباس أعلاه عن الرقم المغطى في rect64 () ماذا عن الرقم خارج الأقواس بعد الفاصلة؟

لقد طرحت سؤالاً ذا صلة. قد تساعدك الإجابات التي تساعدك أيضًا.احصل على أربعة أرقام 16bit من قيمة سداسية سداسية 64 بت

ملاحظة: تفاصيل INI هي نفسها التي أنشأها بيكاسا للصورة المعينة.

بالإضافة إلى أن السؤال قد تم تحديثه عدة مرات وقد لا يكون واضحًا بما فيه الكفاية.

هناك بعض الردود في موقع مساعدة بيكاسا, ، حيث طرحت نفس السؤال أحد الإجابات من هذا الموضوع للحصول على إحداثيات بناءً على قيم Hex من ملف 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.9463348387 الباقي 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 حاليًا رموز Hex عبر واجهة برمجة التطبيقات (أو هل هم؟). لو كان الأمر كذلك ، لكانت الأمور أفضل.

لذلك نحن نقترب من الحل. شكرًا لكم جميعًا ، أتمنى أن أتمكن من منح المكافأة للجميع (لا أستطيع ، لكن لا أخاف وأبحث عن ارتفاع في مندوبك!)

هل كانت مفيدة؟

المحلول

للإجابة على سؤال بيكاسا ، راجع هذا الرد على منتديات بيكاسا:
http://www.google.com/support/forum/p/picasa/thread؟tid=36ae553a7b49088e&hl=en

كتب Oedious:- سيكون هذا تقنيًا إلى حد ما ، لذا تمسك. * الرقم المغطى في rect64 () هو رقم سداسي عشري 64 بت. * كسر ذلك إلى أربعة أرقام 16 بت. * قسّم كل منها على الحد الأقصى لعدد 16 بت غير موقّع (65535) وسيكون لديك أربعة أرقام بين 0 و 1. * تمنحك الأرقام الأربعة المتبقية إحداثيات نسبية لمستطيل الوجه: (يسار ، أعلى ، يمين ، أسفل). * إذا كنت تريد أن ينتهي الأمر بإحداثيات مطلقة ، فالأمر الأيسر واليمين بعرض الصورة والأعلى والسفلي بواسطة ارتفاع الصورة.

نصائح أخرى

ينظر الى OpenCV - أحد الأمثلة التي تأتي مع التوزيع هو للكشف عن الوجه.

الحل الخاص بك للمشكلة هو المبالغة. تجاهل الوجوه. ما لديك هو خلفية بيضاء صلبة ومجموعة من الصور المستطيلة عليها. كل ما عليك فعله هو العثور على المستطيل الذي يحيط كل صورة ومحصول.

ابدأ بتشغيل مرشح على الصورة الأصلية التي تمثل جميع وحدات البكسل غير الخلفية. سيستغرق هذا بعض الضبط لأنه في بعض الأحيان سيكون للخلفية لمسة من الصبغة (الأوساخ) أو أن الصورة ستحتوي على بعض وحدات البكسل التي تبدو مثل الخلفية (الأسنان البيضاء حقًا).

الآن تبحث عن مساحات واسعة بدون لون خلفية فيها. اقتصاص هذه المستطيلات.

بما أنك الشخص الذي يقوم بالمسح ، فلماذا لا تجعل الخلفية خضراء؟ قد يكون اللون الأخضر لونًا أسهل للتصفية ، خاصة وأن صور جواز السفر يتم التقاطها على خلفية بيضاء.

يمكنك تبسيط المشكلة إلى أبعد من ذلك :-) إذا كانت الصور الممسوحة ضوئيًا ستكون دائمًا في شبكة 5 × 4 ... يمكنك ذلك بسهولة ما عليك سوى فتح الصورة في أي لغة برمجة تقدم معالجة نقطية ، وحفظ كل مربع. إليك مثال على كيفية القيام بذلك باستخدام 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://ceotki.com/devprojects/getpicasafaces

رمز المصدر متاح أيضًا.

على الرغم من أنني لم أكن قد قمت بتطبيق الحصول على اسم جهات الاتصال من رمزها السداسي عشري ، إلا أنه من الممكن استخدام واجهة برمجة تطبيقات جهات اتصال Google: http://code.google.com/apis/contacts/

مع API هذا ، من الممكن الحصول على جهات اتصال حسب المعرف ، وإذا تم مزامنة جهات الاتصال الخاصة بك بين جهات اتصال Picasa و Google ، فإن معرف السداسية هو نفسه.

الجزء الأخير من رابط الاتصال الكامل هو سداسي عشري تستخدمه بيكاسا.

آمل أن يساعد هذا.

هتاف ، فيليبي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top