Ordina le immagini in base alle proporzioni


13

Sto cercando di selezionare alcune immagini artistiche per adattarle ad alcune nuove cornici. Vorrei essere in grado di ordinare queste immagini per vicinanza a un particolare formato e quindi visualizzarle in ordine decrescente di prossimità attraverso qualcosa come feh.

Esiste una gloriosa espressione Unix a una riga? Altrimenti alcune decine di righe di Python dovrebbero chiarire questo punto.


3
È possibile estrarre le proporzioni tramite ImageMagick, ad es identify -format "%[fx:w/h]:%M\n" *.jpg. Non so come ordinare facilmente per vicinanza a un valore arbitrario. sortnon sembra supportare tale ordinamento.
NN,

Bene, fondamentalmente, vorresti convertire quei numeri in una metrica di distanza intera, e quindi potresti passarlo per ordinare -n. Sembra che tu possa effettivamente fare tutta la matematica con ImageMagick.
derobert l'

Risposte:


8

Usando il commento di ImageMagick di NN come lead, si scopre che puoi fare calcoli arbitrari come parte del suo -formatoutput. Quindi, un modo possibile:

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

dovrebbe fare quello che vuoi. Si noti che 4/3 in è una costante, le proporzioni desiderate. Ovviamente potresti trovarlo come output di un precedente identify(per corrispondere a "più vicino a questa immagine").

Per spiegare, stiamo prendendo la semplice differenza tra l'aspetto desiderato e quello reale. Quindi moltiplicando per un numero elevato e arrotondando. La moltiplicazione e il round sono perché l'ordinamento gestisce solo numeri interi, non razionali.

modificare

Si scopre sortche sembra fare razionali, non solo numeri interi. È anche specificato nella specifica Unix singola (v4). Quindi, puoi sbarazzarti di quella soluzione alternativa:

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

Dove hai trovato la documentazione sull'opzione -format di identify? Non ho visto nulla nella pagina di manuale e ho trascorso un bel po 'di tempo a cercare di capire cosa diavolo :).
terdon

Oh, e sul mio sistema il tuo comando non sembra funzionare. Capisco 33333:cover.jpgdove cover.jpg è 500x500.
terdon

2
@terdon bene, è perché ha un rapporto di 1/1 e non di 4/3. 4 / 3-1 = 1/3 = .333…. Basta cambiare quel 4/3 con il rapporto desiderato (che suona come 1/1). I documenti sono su imagemagick.org/script/fx.php in un modo tipicamente confuso. Mi ci è voluto un po 'anche per trovarli.
derobert,

Grazie per il link Per il resto, ero un idiota. Avevo solo un jpg nella mia cartella di test (il resto sono png) quindi da quando ho visto solo una linea di output ho pensato che fosse il risultato desiderato e che identificava affermando che l'immagine aveva un formato 4/3. Questo è quello che ottengo provando a pensare il lunedì sera ... +1 per una soluzione elegante.
terdon

Bella risposta! C'è un modo per aggiungere una sorta di etichetta ai nomi dei file di tutte le immagini che non aderiscono al rapporto desiderato?
Mentalista,

3

Bene, il modo più semplice per farlo sarebbe usare ImageMagick . Dovrebbe essere nei repository della tua distribuzione Linux, per i sistemi basati su Debian, eseguire:

sudo apt-get install imagemagick

Uno dei programmi della suite ImageMagick è identifyche stampa le caratteristiche di un elenco di file immagine di input. La combinazione con sortti darà un elenco di immagini ordinate per dimensione (puoi cambiare png per qualsiasi estensione che hai:

identify *png | sort -gk 3

Se in realtà hai bisogno delle proporzioni e non solo delle dimensioni, prova qualcosa del genere:

  1. Opzione semplice, presuppone che i nomi delle tue immagini non abbiano spazi :

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

    Il comando gawk divide il 3 ° campo (la dimensione dell'immagine che ha il formato LxH) nella matrice "dimensioni" e quindi stampa il 1 ° campo (il nome dell'immagine) e il risultato della divisione della lunghezza dell'immagine per la sua altezza. Il sedcomando sta semplicemente abbellendo l'output e il sortcomando ordina il risultato in base al rapporto delle dimensioni dell'immagine.

  2. Più complesso, questo può occuparsi di spazi nei nomi dei file:

    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
    

    Qui stiamo usando findper identificare i file a cui siamo interessati ed eseguiamo il identifycomando, quindi eseguiamo il piping del suo output attraverso un piccolo script PERL. L'espressione regolare cerca tre lettere maiuscole ( [A-Z]{3}) che dovrebbero essere il formato dell'immagine. Una volta trovato ciò, è facile identificare il nome e le dimensioni dell'immagine.

    Non sto usando gawk qui perché la presenza di spazi nei nomi dei file di input confonderà i numeri dei campi. Infine, lo script stamperà il nome dell'immagine e il risultato della divisione lunghezza / altezza che abbiamo sortnumericamente.

Se sfogliare semplicemente le proporzioni disponibili non è sufficiente, se hai almeno un'immagine con le proporzioni desiderate, usa grep per estrarre quelle immagini il cui rapporto è più vicino:

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

2

È possibile calcolare la differenza di ciascuna proporzione con il riferimento. Sembra la risposta di Derobert, ma più semplice:

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

Hmm, apparentemente una specie fa razionali. Avevo l'impressione che non ...
Derobert l'

2

Un rapporto d'aspetto è solo un numero, quindi puoi sfogliare le immagini in base al loro nome, se il nome è preceduto dal rapporto d'aspetto. La creazione di collegamenti simbolici con le proporzioni precedenti consente di sfogliare le immagini ordinate per proporzioni.

I seguenti visualizzatori funzionano come previsto. ( feh non va avanti / indietro, anche per immagini reali - sul mio sistema)

  • comix
  • eog (Eye of Gnome / Image Viewer)
  • 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' -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 

Vai nella ar-sortdirectory e naviga da qualsiasi punto di partenza (rapporto d'aspetto) a cui sei interessato.

I nomi dei collegamenti simbolici si presentano così:

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

Nota: se le impostazioni locali utilizzano un altro segno decimale rispetto a un punto, questo non funzionerà. Facile da risolvere però: stackoverflow.com/questions/12845997/...
Jobjörn Folkesson

1

La mia solita linea di ragionamento è quella di utilizzare la metrica della distanza dell'errore quadrata ogni volta che sento parole "grado di prossimità". Si possono sicuramente usare valori assoluti e sarebbe più veloce. Lo script prende come argomento le proporzioni ideali , elabora tutti i file * .jpg nella directory corrente e li genera ordinati in ordine crescente di divergenza rispetto alla proporzione ideale.

head rimuove il carattere finale di fine riga inserito da ImageMagick.

Lo script contiene un comando gawk che imposta il separatore del campo di output su un carattere improbabile, calcola la differenza quadrata e stampa la differenza di coppia | nome file. L'ordinamento viene eseguito e le informazioni non necessarie (differenza di proporzioni quadrate) vengono eliminate cut.

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

Nota che utilizza distanza quadratica e calcoli in gawk / awk :) (Grazie a @NN per la scorciatoia iniziale)
Deer Hunter

Potresti per favore aggiungere una spiegazione dello script alla tua risposta? Lo renderebbe migliore.
NN,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.