Domanda

(Una domanda simile è stata posta al superutente per le risposte relative alle applicazioni.La domanda è pubblicata qui per raccogliere soluzioni programmabili per lo stesso)

Sul posto di lavoro, le fotografie formato tessera vengono scansionate insieme, quindi suddivise in singole immagini e salvate con numeri di file univoci.Attualmente utilizziamo Paint.net per selezionare, tagliare e salvare manualmente le immagini.

Schermata di esempio di Picasa del documento scansionato:(da:ricerca immagini su Google da più fonti, fair use)

picasa screenshot

Per es.In Picasa 3.8, facendo clic su Visualizza > Persone, vengono visualizzati tutti i volti e mi viene chiesto di nominarli. Posso salvare automaticamente queste singole immagini con i nomi come immagini diverse?

Aggiornato

Tutto quello che voglio fare è convertire l'immagine sopra in singole immagini.

Nell'immagine sopra ho mostrato come Picasa 3.8 rileva le immagini e mi chiede di nominarle.Non ho bisogno del riconoscimento facciale, ho semplicemente bisogno del rilevamento facciale.Picasa rileva le singole immagini e le mostra sulla destra.Queste singole immagini sono ciò di cui ho bisogno.Picasa crea un file .ini che salva i valori esadecimali che contengono le coordinate dei singoli volti.

Questi singoli volti sono ciò che mi interessa. Se riesco ad avere le coordinate, posso ritagliare le immagini richieste dall'immagine.

CAMPIONE.jpg

sample.jpg

contenuto iniziale

 [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

*Sembra che il file ini salvi le coordinate dei tag dei volti come rect64(534a06d429ae627),dff6163dfd9d4e41 per ogni etichetta.Citando da Sito di assistenza di Picasa utente Technonath dice

@oedious ha scritto:- Questo sarà Un po' tecnico, quindi aspetta.* Il numero racchiuso in rect64() è un numero esadecimale a 64 bit.* Suddividilo in quattro numeri a 16 bit.* Dividi ciascuno per il numero massimo senza segno a 16 bit (65535) e avrai quattro numeri compresi tra 0 e 1.* I quattro numeri rimanenti forniscono le coordinate relative per il viso rettangolo:(sinistra, alto, destra, basso).* Se vuoi ottenere coordinate assolute, moltiplica il tasto sinistro e proprio accanto alla larghezza dell'immagine e alla parte superiore e in basso dall'altezza dell'immagine.

La citazione sopra parla del numero racchiuso in rect64() e del numero fuori dalle parentesi dopo la virgola?

Ho posto una domanda correlata.Le cui risposte potrebbero aiutare anche te.Ottieni quattro numeri a 16 bit da un valore esadecimale a 64 bit

Nota:I dettagli INI sono gli stessi che Picasa ha generato per l'immagine particolare.

Inoltre la domanda è stata aggiornata più volte e potrebbe non essere abbastanza chiara.

Ci sono alcune risposte al Sito della Guida di Picasa, dove ho posto la stessa domanda Una delle risposte da quel thread per ottenere le coordinate in base ai valori esadecimali dal file ini.Il codice seguente è in C# da esac dal sito di aiuto.Posso fare lo stesso in 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);
} 

Codice PHP provando a convertire 64 bit in numeri compresi tra 1 e 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/>";
}
?>

Il risultato

Resto 1:49551 ;Risultato 1:0.75608825683594 COORDINATE :371.99542236328 396.94633483887 Resto 1 :19598;Risultato 1:0.29904174804688 COORDINATE :147.12854003906 156.99691772461 Resto 1 :62471 ;Risultato 1:0.95323181152344 COORDINATE :468.99005126953 500.4467010498 Resto 1 :34078 ;Risultato 1:0.51998901367188 COORDINATE :255.83459472656 272.99423217773

Quindi anch'io ho le coordinate e @Nirmal le ha mostrato come ritagliarli.Ora il passo successivo sarebbe quello di analizzare picasa.ini per i codici esadecimali e i nomi dei file e integrare il codice.Picasa attualmente non fornisce i codici esadecimali tramite un file api(or Fanno?).Se così fosse le cose sarebbero andate meglio.

Quindi siamo vicini ad una soluzione.Grazie a tutti, vorrei poter assegnare la taglia a tutti (non posso, ma non temere e fai attenzione a un picco nella tua reputazione!)

È stato utile?

Soluzione

Per rispondere alla domanda su Picasa, consulta questa risposta sui forum di Picasa:
http://www.google.com/support/forum/p/Picasa/thread?tid=36ae553a7b49088e&hl=it

@oedious ha scritto:- Questo sarà Un po' tecnico, quindi aspetta.* Il numero racchiuso in rect64() è un numero esadecimale a 64 bit.* Suddividilo in quattro numeri a 16 bit.* Dividi ciascuno per il numero massimo senza segno a 16 bit (65535) e avrai quattro numeri compresi tra 0 e 1.* I quattro numeri rimanenti forniscono le coordinate relative per il viso rettangolo:(sinistra, alto, destra, basso).* Se vuoi ottenere coordinate assolute, moltiplica il tasto sinistro e proprio accanto alla larghezza dell'immagine e alla parte superiore e in basso dall'altezza dell'immagine.

Altri suggerimenti

Guarda a OpenCV - uno degli esempi forniti con la distribuzione riguarda il rilevamento dei volti.

La tua soluzione al problema è eccessiva.Ignora i volti.Quello che hai è uno sfondo bianco solido e un mucchio di immagini rettangolari su di esso.Tutto quello che devi fare è trovare il rettangolo che racchiude ogni immagine e ritagliare.

Inizia eseguendo un filtro sull'immagine originale che contrassegna tutti i pixel non di sfondo.Ciò richiederà un po' di messa a punto perché a volte lo sfondo avrà un tocco di tinta (sporco) o la foto avrà alcuni pixel che assomigliano allo sfondo (denti veramente bianchi).

Ora cerchi aree estese senza colore di sfondo.Ritagliali in rettangoli.

Dato che sei tu a eseguire la scansione, perché non rendere lo sfondo verde?Il verde potrebbe essere un colore più facile da filtrare, soprattutto perché le foto tessera sono scattate su uno sfondo bianco.

Puoi semplificare ulteriormente il problema :-) se le immagini scansionate saranno sempre in una griglia 5x4 ...allora puoi facilmente basta aprire l'immagine praticamente in qualsiasi linguaggio di programmazione che offra la manipolazione bitmap e salvare ogni quadrato.Ecco un esempio di come eseguire questa operazione con C#:

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

Tutto quello che devi fare è calcolare ciascun rettangolo e quindi chiamare questo metodo che restituisce solo l'area dell'immagine definita dal rettangolo.Qualcosa del tipo (possibilmente pseudo codice, non ho compilato il codice seguente):

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

Per la parte di ritaglio, sto digitando il codice senza testarlo, ma dovrebbe funzionare:

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

Il codice precedente presuppone che l'immagine sorgente sia in formato JPEG e che le coordinate formino un rettangolo o un quadrato perfetto.

Spero che aiuti.

Questo dovrebbe portarti a tagliare il traguardo.Ecco del codice per analizzare 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/>";
    }
}

Ho sviluppato una piccola app in .NET che fa esattamente quello che hai detto, produce i file per i volti.Controllalo qui: http://ceottaki.com/devprojects/getpicasafaces

È disponibile anche il codice sorgente.

Anche se non ho implementato il recupero del nome dei contatti dal loro codice esadecimale, è possibile utilizzare l'API dei contatti di Google: http://code.google.com/apis/contacts/

Con tale API è possibile ottenere contatti tramite ID e, se i tuoi contatti sono sincronizzati tra Picasa e Contatti Google, l'ID esadecimale è lo stesso.

L'ultima parte di un collegamento di contatto completo è l'esadecimale utilizzato da Picasa.

Spero che aiuti.

Cin cin Felipe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top