Classificar imagens por proporção

13

Estou tentando selecionar algumas imagens de arte para se adequar a alguns novos quadros. Gostaria de poder classificar essas imagens por proximidade a uma proporção específica e, em seguida, visualizá-las em ordem decrescente de proximidade por meio de algo como feh.

Existe alguma expressão Unix gloriosa de uma linha? Caso contrário, algumas dezenas de linhas de Python devem esclarecer isso.

    
por Jeff 08.10.2012 / 18:06

5 respostas

8

Usando o comentário do N.M. ImageMagick como um lead, você pode fazer cálculos arbitrários como parte de sua saída -format . Então, uma maneira possível:

identify -format "%[fx:round(100000*abs((4/3)-(w/h)))]:%M\n" *.jpg | \
    sort -n -k1 -t:

deve fazer o que quiser. Note que 4/3 lá é uma constante, a relação de aspecto desejada. É claro que você pode achar isso como a saída de um identify anterior (para corresponder a "mais próximo dessa imagem").

Para explicar, estamos tomando a clara diferença entre a proporção desejada e real. Em seguida, multiplicando por um grande número e arredondando. A multiplicação e a volta são porque o tipo só lida com inteiros, não com racionais.

editar

Acontece que sort parece fazer racionais, não apenas inteiros. É até especificado na Especificação Unix Única (v4). Então, você pode se livrar dessa solução alternativa:

identify -format "%[fx:abs((4/3)-(w/h))]:%M\n" *.jpg | \
    sort -n -k1 -t:
    
por 08.10.2012 / 19:37
3

Bem, a maneira mais fácil de fazer isso seria usar o ImageMagick . Deve estar nos repositórios da sua distribuição Linux, para sistemas baseados no debian, execute:

sudo apt-get install imagemagick

Um dos programas do conjunto ImageMagick é identify , isso imprimirá as características de uma lista de arquivos de imagem de entrada. Combinando-o com sort , você terá uma lista de imagens ordenadas por tamanho (você pode alterar png para qualquer extensão que tenha:

identify *png | sort -gk 3

Se você realmente precisar da proporção e não apenas do tamanho, tente algo assim:

  1. Opção simples, assume que os nomes das suas imagens não têm espaços :

    identify *png *jpg *gif | \
    gawk '{split($3,sizes,"x"); print $1,sizes[1]/sizes[2]}' | \
    sed 's/\[.\]//' | sort -gk 3
    

    O comando gawk divide o terceiro campo (o tamanho da imagem que tem o formato LxH) na matriz "tamanhos" e imprime o primeiro campo (o nome da imagem) e o resultado da divisão do comprimento da imagem pela sua altura. O comando sed está apenas embelezando a saída e o comando sort classifica o resultado de acordo com a proporção do tamanho da imagem.

  2. Mais complexo, este pode lidar com espaços em nomes de arquivos:

    find . \( -iname  "*png" -o -iname "*jpg" -o -iname "*gif" \) -exec identify {} \; |\
    perl -ne '/(.+?)\s+[A-Z]{3}\s+(\d+)x(\d+)/; print "$1 ", $2/$3, "\n"' | \
    sort -gk 2
    

    Aqui estamos usando find para identificar os arquivos nos quais estamos interessados e executar o comando identify e, em seguida, direcionando sua saída através de um pequeno script PERL. A expressão regular procura três letras maiúsculas ( [A-Z]{3} ) que devem ser o formato da imagem. Depois de descobrirmos isso, é fácil identificar o nome e as dimensões da imagem.

    Eu não estou usando o gawk aqui porque a presença de espaços nos nomes dos arquivos de entrada irá confundir os números dos campos. Finalmente, o script irá imprimir o nome da imagem e o resultado da divisão comprimento / altura que nós sort numericamente.

Se simplesmente pesquisar as proporções disponíveis não for suficiente, se você tiver pelo menos uma imagem com a proporção desejada, use grep para extrair aquelas imagens cuja proporção esteja mais próxima:

identify *png *jpg *gif | \
gawk '{split($3,sizes,"x"); print $1,sizes[1]/sizes[2]}' |\
sed 's/\[.\]//' | sort -gk 3 | grep -C 10 GOOD_IMAGE.jpg
    
por 08.10.2012 / 19:55
2

Você pode calcular a diferença de cada proporção com a referência. Parece a resposta de Derobert, mas mais simples:

ref=4/3
identify -format "%[fx:abs(w/h - $ref)] %M\n" *.jpg | sort -n -k1
    
por 08.10.2012 / 20:17
2

Uma proporção é apenas um número, portanto, você pode navegar pelas imagens de acordo com seus nomes, se o nome tiver o prefixo com a proporção. A criação de links simbólicos com a proporção pré-definida permite que você navegue pelas imagens classificadas por proporção.

Os seguintes visualizadores funcionam como esperado. ( feh não avança / retrocede, mesmo para imagens reais - no meu sistema)

  • comix
  • eog (Olho do Gnomo / Visualizador de Imagens)
  • gwenview
picd='/media/dat_ext4/pictures/jpg/misc'
srtd="$picd/ar-sort"   # directory to hold "sorted" symbolic links
mkdir -p "$srtd"              

find "$picd" -maxdepth 1 -type f -name "*" -print0 | 
  while IFS= read -d $'
0.6732 Gold Bars.jpg
0.7242 Light Bulb.jpg
0.8022 Escher - Waterfall.jpg
1.3696 Old Typewriter.jpg
1.6000 King Tut.jpg
' -r file ; do [[ $(file -ib "$file") != image* ]] && continue # skip non-image files ar="$(identify -format "%[fx:w/h]" "$file")" slink="$(printf '%s/%06.4f %s' "$srtd" "$ar" "$(basename "$file")")" # make symbolic link in 'ar-sort' directory ln -s "$file" "$slink" echo "$slink" done

Entre no diretório ar-sort e navegue a partir de qualquer ponto inicial (aspect-ratio) em que esteja interessado.

Os nomes dos links simbólicos são assim:

picd='/media/dat_ext4/pictures/jpg/misc'
srtd="$picd/ar-sort"   # directory to hold "sorted" symbolic links
mkdir -p "$srtd"              

find "$picd" -maxdepth 1 -type f -name "*" -print0 | 
  while IFS= read -d $'
0.6732 Gold Bars.jpg
0.7242 Light Bulb.jpg
0.8022 Escher - Waterfall.jpg
1.3696 Old Typewriter.jpg
1.6000 King Tut.jpg
' -r file ; do [[ $(file -ib "$file") != image* ]] && continue # skip non-image files ar="$(identify -format "%[fx:w/h]" "$file")" slink="$(printf '%s/%06.4f %s' "$srtd" "$ar" "$(basename "$file")")" # make symbolic link in 'ar-sort' directory ln -s "$file" "$slink" echo "$slink" done
    
por 08.10.2012 / 20:36
1

Minha linha usual de raciocínio é usar a métrica de distância de erro quadrada sempre que eu ouvir as palavras "grau de proximidade". Certamente, é possível usar valores absolutos e seria mais rápido. O script toma como argumento a relação de aspecto ideal , processa todos os arquivos * .jpg no diretório atual e os envia classificados na ordem crescente de divergência da relação ideal.

head remove caracteres de final de linha à direita inseridos pelo ImageMagick.

O script contém um comando gawk que define o separador do campo de saída como um caractere improvável, calcula a diferença quadrada e imprime o nome do arquivo de diferenças do par. A classificação é executada e informações desnecessárias (diferença de proporção de aspecto quadrada) são selecionadas por cut .

#!/bin/sh
if [ x"$1" = "x" ] ; then
  echo "Usage: $0 TargetAspectRatio" >&2
  exit 2
fi
ASPECT_CMD="BEGIN{OFS=\"|\";}\
{\
print (\-$1)^2, \;\
}"
identify -format "%[fx:w/h]:%M\n" *.jpg | head -n-1 | gawk -F":" "$ASPECT_CMD" | sort -k1 -t"|" | cut -f2 -d"|"
    
por 08.10.2012 / 20:18

Tags