Programaticamente determinar “uniformidade” da imagem

5

Estou tentando escrever um script que miniaturas nossos muitos milhares de ativos. Os ativos usam o Flash na maioria das vezes, e eu os estou capturando via chromium-browser na linha de comando. Eu praticamente preciso superar isso para fazê-lo funcionar no momento e é um PITA. O que ajudaria seria uma maneira do meu script saber quando ele fez uma miniatura falhada, o que parece acontecer muito.

Os "fracassos" tendem a ser de uma cor uniforme, cinza escuro ou branco, e eu pensei que poderia usar esse "grau de uniformidade" como forma de avaliar programaticamente o sucesso da miniatura. Veja alguns exemplos:

link link link link

O que faz isso (eu diria) mais difícil é que o cinza escuro não é uma cor uniforme, mas sim um padrão repetido de pixels, que se parece com isso em close:

Portanto, é uniforme, mas é um padrão repetido uniforme.

Alguém pode pensar em uma maneira de fazer isso na linha de comando?

    
por Max Williams 11.03.2016 / 16:34

4 respostas

1

Escrevendo minha própria resposta, desde que descobri. Bem, parece funcionar com as minhas imagens de teste. É explicado nos comentários.

#!/bin/sh

#Tests whether an image is uniform (ie a simple repeated pattern or a single colour.)  

#The logic is as follows:
# - convert the image to an 8x8 px temp BMP image.  
#(we need to use bitmaps because we need exact pixel values 
#with no random compression artifacts)
# - convert THAT to a 1x1 px BMP image
# - convert the 1 px image back to an 8x8 px BMP image.

#If the first 8x8 image is the same (according to 'diff')   
#as the scaled-to-1px-and-back-again image, 
#then we can conclude that the first 8x8 image was totally uniform,
#(ie every pixel exactly the same) 
#and from this we can conclude that the original full size image 
#was also uniform:  not necessarily the same colour in every pixel,  
#but not varied enough for our requirements.

source=$1
small1=/tmp/small_image.bmp
small2=/tmp/small_image2.bmp
tiny=/tmp/tiny_image.bmp

#the \! after 8x8 tells it to ignore the aspect ratio and just squash it to those dimensions
convert "$source" -resize 8x8\! "$small1"
convert "$small1" -resize 1x1 "$tiny"
convert "$tiny" -resize 8x8 "$small2"
diff "$small1" "$small2" > /dev/null
result=$?
if [ $result -eq 0 ]; then
  #diff gives an empty return, so the files are the same, which means there wasn't variation
  echo "Image is uniform" >&1
else
  #we found a difference between the pre-squashed and resized versions which means there WAS variation
  echo "Image is not uniform" >&1
fi
    
por 21.03.2016 / 16:06
2

Eu não sei como você pode programaticamente fazer isso e não é uma coisa 100% precisa, mas, como você está fazendo algo próximo ao screen scraping, eu sugiro que você realmente lance a imagem na tela e use xdtool , você pode amostrar muitos pontos aleatórios na imagem e detectar a cor do pixel. Se todos ou mais de 95% deles estiverem com a mesma cor, é seguro dizer que a imagem é de cor lisa.

Outra maneira é armazenar imagens errôneas comumente encontradas e comparar o tamanho da imagem com o tamanho de imagens erradas. Estou extraindo fotos de vídeos usando o VLC para minha biblioteca de vídeos e, ao fazer isso, percebi, quanto maior o contraste em uma imagem, maior o tamanho de um arquivo png que eu capturei. Então, veja se os tamanhos das imagens são muito pequenos. Afinal, a compactação de imagens tem tudo a ver com a minimização da quantidade de armazenamento de um padrão repetitivo. Você pode usar este fato a seu favor.

    
por 11.03.2016 / 16:51
2

Você poderia tentar um método que Neal Krawetz, de < Fama, faz:

FotoForensics , faz:

  1. Reduza o tamanho. Krawetz "esmaga" a imagem em um quadrado de 8x8.
  2. Reduza a cor da imagem 8x8 para tons de cinza.
  3. Calcule o valor médio das 64 cores resultantes.
  4. Calcule um número de 64 bits (8 * 8 = 64) - "Cada bit é simplesmente definido com base em se o valor da cor está acima ou abaixo da média.
  5. Construa um hash. Parece que o Krawetz usa apenas os 64 bits como um valor hash.

Esse tipo de coisa criaria suas imagens em escala de cinza e as imagens em preto-e-branco cairiam como valores hash muito distintos. Você provavelmente teria que escrever ou encontrar algum código de script que não fosse shell para isso.

Outro que vem à mente é encontrar cores dominantes em uma imagem. Esse cara usa o Imagemagick e o awk , mas não sei como você testaria a igualdade ou similaridade no seu caso.

UPDATE

Acabei de encontrar libpuzzle , "Uma biblioteca para encontrar imagens semelhantes" por acaso. Seria necessário um pouco de código para fazer o que você quer com isso.

Há também o pHash , uma biblioteca de hashing de código aberto. Provavelmente, a mesma quantidade de codificação seria necessária para este.

Nenhuma dessas opções atende exatamente às suas necessidades, pois a libpuzzle tem uma interface PHP e o pHash parece exigir que você escreva um programa em C.

    
por 11.03.2016 / 20:07
1

Você pode usar o imagemagick para calcular uma FFT e compará-la a uma imagem inválida conhecida:

http://www.fmwconcepts.com/imagemagick/fourier_transforms/fourier.html#im_fft

    
por 23.03.2016 / 02:22