Détection automatique des visages en utilisant l'API Picasa pour extraire des images individuelles

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

Question

(Une question similaire a été posée sur des réponses liées superuser aux applications. La question est affichée ici pour recueillir des solutions programmables pour les mêmes)

A mon lieu de travail, des photographies de format passeport sont scannés ensemble, puis découpé en images individuelles et enregistré avec des numéros de fichiers uniques. Actuellement, nous utilisons Paint.net pour sélectionner manuellement, couper et enregistrer les images.

Exemple Scanned document Picasa Capture d'écran: (À partir de: image google recherche de sources multiples, FairUse)

picasa capture d'écran

Pour exemple. Dans Picasa 3.8, En cliquant sur Affichage> Les gens, tous les visages sont représentés et on me demande de les nommer, puis-je sauvegarder ces images individuelles automatiquement avec les noms que différentes images?

Mise à jour

Tout ce que je veux faire est de convertir l'image ci-dessus pour des images individuelles.

Dans l'image ci-dessus, je l'ai montré comment Picasa 3.8 détecte les images et les invites me les nommer. Je ne ai pas besoin la reconnaissance faciale, j'ai simplement besoin d'une détection de visage. Picasa détecte les images individuelles et les spectacles du RHS. Ces images individuelles sont ce que je dois. Picasa crée un fichier .ini qui enregistre les valeurs hexagonales qui contient les coordonnées des faces individuelles.

Ces visages individuels sont ce que je suis intéressé par Si je peux avoir les coordonnées, je peux recadrer les images nécessaires à partir de l'image.

sample.jpg

sample.jpg

contenu 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

* Le fichier ini semble enregistrer les coordonnées des balises face comme rect64(534a06d429ae627),dff6163dfd9d4e41 pour chaque balise. Je cite l'utilisateur de Picasa aide du site Technonath dit

  

écrit @oedious: - Cela va être   un peu technique, accrocher ainsi de suite.   * Le nombre enfermé dans rect64 () est un nombre hexadécimal 64 bits.   * BREAK qui en quatre numéros 16 bits.   * Diviser chaque par le non signé Nombre maximal de 16 bits (65535) et vous aurez   quatre nombres compris entre 0 et 1.   * Les quatre chiffres que vous donnent les coordonnées restantes relatives pour le visage   rectangle: (gauche, en haut, à droite, en bas).   * Si vous voulez retrouver avec des coordonnées absolues, multiples et de gauche   juste à côté de la largeur de l'image et la partie supérieure   et en bas par la hauteur de l'image.

Les pourparlers de citation ci-dessus sur le nombre enfermé dans rect64 () ce que le nombre en dehors des parenthèses après la virgule?

J'ai posé une question connexe. Les réponses de ce qui peut vous aider. obtenir quatre numéros de 16bit d'une valeur hexadécimale 64bit

  

Note:   les détails ini sont les mêmes qui picasa   généré pour l'image particulière.

     

De plus la question a été mis à jour plusieurs fois et peuvent ne pas être assez clair.

Il y a quelques réponses au le site Centre d'aide Picasa , où j'ai posé la même question L'une des réponses de ce fil pour obtenir les coordonnées sur la base des valeurs hexagonales à partir du fichier ini. Le code suivant est en C # de ESAC à partir du site d'aide. Puis-je faire la même chose en 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);
} 

Code PHP essayant de convertir 64 bits à un nombre entre 1 et 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/>";
}
?>

La sortie

  

Remainder 1: 49.551; Résultat 1:   0.75608825683594 COORDONNEES: 371,99542236328 396,94633483887 résiduaire de 1: 19598; Résultat 1:   0.29904174804688 COORDONNEES: 147,12854003906 156,99691772461 résiduaire de 1: 62471; Résultat 1:   0.95323181152344 COORDONNEES: 468,99005126953 500,4467010498 résiduaire de 1: 34078; Résultat 1:   0.51998901367188 COORDONNEES: 255,83459472656 272,99423217773

J'ai donc les coordonnées trop et @Nirmal a montré comment les recadrer . Maintenant, les prochaines étapes seraient pour analyser picasa.ini pour les codes hexagonaux et les noms de fichiers et d'intégrer le code. Picasa ne fournit pas les codes hexagonaux via un api (ou Ont-ils? ). Si tel était le cas, les choses auraient pu être mieux.

Nous sommes donc presque une solution. Merci à tous, je voudrais pouvoir attribuer la prime à tout le monde (je ne peux pas, mais ne crains pas et regarder dehors pour un pic de votre représentant!)

Était-ce utile?

La solution

Pour répondre à la question de picasa, voir cette réponse sur les forums de picasa:
http://www.google.com/support/forum / p / Picasa / fil? tid = 36ae553a7b49088e & hl = fr

  

écrit @oedious: - Cela va être   un peu technique, accrocher ainsi de suite.   * Le nombre enfermé dans rect64 () est un nombre hexadécimal 64 bits.   * BREAK qui en quatre numéros 16 bits.   * Diviser chaque par le non signé Nombre maximal de 16 bits (65535) et vous aurez   quatre nombres compris entre 0 et 1.   * Les quatre chiffres que vous donnent les coordonnées restantes relatives pour le visage   rectangle: (gauche, en haut, à droite, en bas).   * Si vous voulez retrouver avec des coordonnées absolues, multiples et de gauche   juste à côté de la largeur de l'image et la partie supérieure   et en bas par la hauteur de l'image.

Autres conseils

Regardez OpenCV - l'un des exemples qui vient avec la distribution est pour la détection des visages <. / p>

Votre solution au problème est surpuissant. Ignorer les visages. Ce que vous avez est un fond blanc solide et un tas d'images rectangulaires sur elle. Tout ce que vous devez faire est de trouver le rectangle qui entoure chaque image et la culture.

Débuter en exécutant un filtre sur l'image originale qui marque tous les pixels de non-fond. Cela prendra quelques ajustements parce que parfois l'arrière-plan aura une touche de teinte en elle (la saleté) ou la photo aura des pixels qui ressemblent à l'arrière-plan (vraiment des dents blanches).

Maintenant, vous regardez pour les grandes surfaces sans couleur de fond en eux. Recadrer les en rectangles.

Puisque vous êtes celui qui fait le balayage, pourquoi ne pas faire le vert de fond? Vert pourrait être une couleur plus facile à filtrer, d'autant plus que les photos de passeport sont prises sur un fond blanc.

Vous pouvez simplifier le problème encore plus loin :-) si les images numérisées seront toujours dans une grille 5x4 ... alors vous pouvez facilement il suffit d'ouvrir l'image dans à peu près tout langage de programmation qui offre manipulation de bitmap, et enregistrer chaque carré. Voici un exemple de la façon de le faire avec C #:

private Image Crop(Image pics, Rectangle area)
{
   var bitmap = new Bitmap(pics);
   return (Image)bitmap.Clone(area, bitmap.PixelFormat);
}

Tout ce que vous aurez besoin de faire est de calculer chaque rectangle, puis appeler cette méthode qui retourne juste la zone de l'image définie par le rectangle. Quelque chose comme (peut-être un code pseudo, n'a pas compilé le code ci-dessous):

// 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
  }
}

Pour la partie culture, je suis en tapant le code sans tester, mais cela devrait fonctionner:

<?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);
?>

Le code ci-dessus suppose que votre image source est au format JPEG et les coordonnées font un rectangle parfait ou carré.

L'espoir qui aide.

Cela devrait vous faire passer la ligne d'arrivée. Voici un code pour analyser l'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/>";
    }
}

J'ai développé une petite application .NET qui fait exactement ce que vous avez dit, il produit les fichiers pour les visages. Check it out ici: http://ceottaki.com/devprojects/getpicasafaces

Le code source est disponible.

Alors que je ne l'ai pas mis en œuvre obtenir le nom des contacts à partir de leur code hexadécimal, il est possible en utilisant l'API Google Contacts: http://code.google.com/apis/contacts/

Avec cette API, il est possible d'obtenir des contacts par ID, et si vos contacts sont synchronisés entre les contacts Picasa et Google, l'ID hexadécimal est le même.

La dernière partie d'un lien de contact complet est hexadécimal utilisé par Picasa.

J'espère que cette aide.

Cordialement, Felipe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top