Pergunta

(Uma pergunta semelhante foi feita ao superusuário para obter respostas relacionadas a aplicativos.A questão é postada aqui para reunir soluções programáveis ​​para a mesma)

No meu local de trabalho, as fotografias tamanho passaporte são digitalizadas juntas, depois cortadas em imagens individuais e salvas com números de arquivo exclusivos.Atualmente usamos o Paint.net para selecionar, cortar e salvar manualmente as imagens.

Exemplo de captura de tela do Picasa de documento digitalizado:(de:pesquisa de imagens do Google em várias fontes, uso justo)

picasa screenshot

Por exemplo.No Picasa 3.8, ao clicar em Visualizar > Pessoas, todos os rostos são mostrados e sou solicitado a nomeá-los. Posso salvar essas imagens individuais automaticamente com os nomes como imagens diferentes?

Atualizada

Tudo o que quero fazer é converter a imagem acima em imagens individuais.

Na imagem acima, mostrei como o Picasa 3.8 detecta as imagens e me pede para nomeá-las.Não preciso de reconhecimento facial, simplesmente preciso de detecção facial.O Picasa detecta as imagens individuais e as mostra no RHS.Essas imagens individuais são o que eu preciso.O Picasa cria um arquivo .ini que salva os valores hexadecimais que contêm as coordenadas das faces individuais.

Esses rostos individuais são o que me interessa. Se eu puder ter as coordenadas, posso cortar as imagens necessárias da imagem.

AMOSTRA.jpg

sample.jpg

conteúdo inicial

 [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

*O arquivo ini parece estar salvando as coordenadas das tags faciais como rect64(534a06d429ae627),dff6163dfd9d4e41 para cada etiqueta.Citando de Site de ajuda do Picasa do utilizador Technonath diz

@oedious escreveu:- Isso vai ser um pouco técnico, então espere.* O número contido em rect64() é um número hexadecimal de 64 bits.* Divida isso em quatro números de 16 bits.* Divida cada um pelo número máximo de 16 bits não assinados (65535) e você terá quatro números entre 0 e 1.* Os quatro números restantes dão-lhe coordenadas relativas para o rosto retângulo:(esquerda, superior, direita, inferior).* Se você quiser acabar com coordenadas absolutas, vários à esquerda e À direita pela largura da imagem e pela parte superior e inferior pela altura da imagem.

A citação acima fala sobre o número entre rect64() e o número fora dos parênteses após a vírgula?

Eu fiz uma pergunta relacionada.As respostas também podem ajudá-lo.Obtenha quatro números de 16 bits a partir de um valor hexadecimal de 64 bits

Observação:O Os detalhes do INI são os mesmos que o Picasa gerado para a imagem em particular.

Além disso, a pergunta foi atualizada várias vezes e pode não ser clara o suficiente.

Existem algumas respostas no Site de ajuda do Picasa, onde fiz a mesma pergunta Uma das respostas desse thread para obter coordenadas com base nos valores hexadecimais do arquivo ini.O código a seguir está em C# de esac do site de ajuda.Posso fazer o mesmo em 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);
} 

Código PHP tentando converter 64 bits em números entre 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/>";
}
?>

A saída

Restante 1:49551;Resultado 1:0,75608825683594 COORDENADAS:371.99542236328 396.94633483887 Restante 1:19598;Resultado 1:0,29904174804688 COORDENADAS:147.12854003906 156.99691772461 Restante 1:62471;Resultado 1:0.95323181152344 COORDENADAS:468.99005126953 500.4467010498 Restante 1:34078;Resultado 1:0,51998901367188 COORDENADAS:255.83459472656 272.99423217773

Então eu também tenho as coordenadas e @Nirmal tem mostrado como cortá-los.Agora, as próximas etapas seriam analisar o picasa.ini em busca de códigos hexadecimais e nomes de arquivos e integrar o código.No momento, o Picasa não fornece códigos hexadecimais por meio de uma API(ou Eles?).Se fosse esse o caso, as coisas teriam sido melhores.

Portanto, estamos nos aproximando de uma solução.Obrigado a todos, gostaria de poder conceder a recompensa a todos (não posso, mas não tema e fique atento para um aumento em sua reputação!)

Foi útil?

Solução

Para responder à pergunta do picasa, veja esta resposta nos fóruns do picasa:
http://www.google.com/support/forum/p/Picasa/thread?tid=36ae553a7b49088e&hl=en

@oedious escreveu:- Isso vai ser um pouco técnico, então espere.* O número contido em rect64() é um número hexadecimal de 64 bits.* Divida isso em quatro números de 16 bits.* Divida cada um pelo número máximo de 16 bits não assinados (65535) e você terá quatro números entre 0 e 1.* Os quatro números restantes dão-lhe coordenadas relativas para o rosto retângulo:(esquerda, superior, direita, inferior).* Se você quiser acabar com coordenadas absolutas, vários à esquerda e À direita pela largura da imagem e pela parte superior e inferior pela altura da imagem.

Outras dicas

Olhe para OpenCV - um dos exemplos que acompanha a distribuição é para detecção de rosto.

Sua solução para o problema é um exagero.Ignore os rostos.O que você tem é um fundo branco sólido e um monte de imagens retangulares nele.Tudo que você precisa fazer é encontrar o retângulo que envolve cada imagem e recortar.

Comece executando um filtro sobre a imagem original que marca todos os pixels que não são de fundo.Isso exigirá alguns ajustes porque às vezes o fundo terá um toque de tonalidade (sujeira) ou a foto terá alguns pixels que se parecem com o fundo (dentes bem brancos).

Agora você procura grandes áreas sem cor de fundo.Corte-os em retângulos.

Já que é você quem está fazendo a digitalização, por que não deixar o fundo verde?Verde pode ser uma cor mais fácil de filtrar, especialmente porque as fotos do passaporte são tiradas em fundo branco.

Você pode simplificar ainda mais o problema :-) se as imagens digitalizadas estiverem sempre em uma grade 5x4...então você pode facilmente basta abrir a imagem em praticamente qualquer linguagem de programação que ofereça manipulação de bitmap e salvar cada quadrado.Aqui está um exemplo de como fazer isso com C#:

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

Tudo o que você precisa fazer é calcular cada retângulo e depois chamar esse método que retorna apenas a área da imagem definida pelo retângulo.Algo como (possivelmente pseudocódigo, não compilei o código abaixo):

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

Para a parte de corte, estou digitando o código sem testar, mas deve funcionar:

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

O código acima assume que sua imagem de origem está no formato JPEG e as coordenadas formam um retângulo ou quadrado perfeito.

Espero que ajude.

Isso deve levá-lo até a linha de chegada.Aqui está um código para analisar o 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/>";
    }
}

Desenvolvi um pequeno aplicativo em .NET que faz exatamente o que você falou, produz os arquivos para os rostos.Confira aqui: http://ceottaki.com/devprojects/getpicasafaces

O código-fonte também está disponível.

Embora eu não tenha implementado a obtenção do nome dos contatos a partir do código hexadecimal, é possível usar a API de Contatos do Google: http://code.google.com/apis/contacts/

Com essa API é possível obter contatos por ID, e se seus contatos estiverem sincronizados entre o Picasa e os Contatos do Google, o ID hexadecimal é o mesmo.

A última parte de um link de contato completo é o hexadecimal usado pelo Picasa.

Eu espero que isso ajude.

Obrigada Felipe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top