Sortieren Sie die Bilder nach Seitenverhältnis

13

Ich versuche ein paar Kunstbilder auszuwählen, um sie an einige neue Rahmen anzupassen. Ich möchte in der Lage sein, diese Bilder nach Nähe zu einem bestimmten Seitenverhältnis zu sortieren und sie dann in abnehmender Reihenfolge der Nähe durch so etwas wie Feh zu betrachten.

Gibt es einen herrlichen einzeiligen Unix-Ausdruck? Andernfalls sollten ein paar Dutzend Python-Zeilen dies aufklären.

Jeff
quelle
3
Sie können das Seitenverhältnis über ImageMagick ziehen, z identify -format "%[fx:w/h]:%M\n" *.jpg. Ich weiß nicht, wie ich leicht nach der Nähe zu einem beliebigen Wert sortieren kann. sortscheint eine solche Sortierung nicht zu unterstützen.
NN
Im Grunde genommen möchten Sie diese Zahlen in eine ganzzahlige Distanzmetrik konvertieren und sie dann an die Sortierung -n übergeben. Anscheinend können Sie mit ImageMagick tatsächlich alle Berechnungen durchführen.
Derobert

Antworten:

8

Wenn Sie den ImageMagick-Kommentar von NN als Hinweis verwenden, können Sie im Rahmen der -formatAusgabe beliebige Berechnungen durchführen . Also ein möglicher Weg:

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

sollte tun, was du willst. Beachten Sie, dass 4/3 darin eine Konstante ist, das gewünschte Seitenverhältnis. Sie könnten das natürlich als Ausgabe einer vorherigen finden identify(entspricht "diesem Bild am nächsten").

Zur Erklärung nehmen wir den einfachen Unterschied zwischen dem gewünschten und dem tatsächlichen Seitenverhältnis. Dann mit einer großen Zahl multiplizieren und runden. Das Multiplizieren und Runden ist, weil sort nur Ganzzahlen behandelt, keine Rationalen.

bearbeiten

Es hat sich herausgestellt sort, dass dies nicht nur Ganzzahlen, sondern auch Rationalitäten sind. Es ist sogar in der Single Unix Specification (v4) spezifiziert. So können Sie diese Problemumgehung loswerden:

identify -format "%[fx:abs((4/3)-(w/h))]:%M\n" *.jpg | \
    sort -n -k1 -t:
derobert
quelle
Wo haben Sie die Dokumentation zur Option -format von identify gefunden? Ich habe nichts auf der Manpage gesehen und einige Zeit damit verbracht, das verdammte Ding herauszufinden :).
terdon
Oh, und auf meinem System scheint Ihr Befehl nicht zu funktionieren. Ich bekomme 33333:cover.jpgwo cover.jpg 500x500 ist.
Terdon
2
@terdon naja, das liegt daran, dass es ein Verhältnis von 1/1 nicht 4/3 hat. 4 / 3-1 = 1/3 = .333…. Ändern Sie einfach das 4/3 auf das gewünschte Verhältnis (was wie 1/1 klingt). Die Dokumente befinden sich auf typisch verwirrende Weise unter imagemagick.org/script/fx.php . Ich habe auch eine Weile gebraucht, um sie zu finden.
Derobert
Danke für den Link. Im übrigen war ich ein Idiot. Ich hatte nur ein JPG in meinem Testordner (der Rest sind PNGs). Da ich also nur eine Ausgabezeile sah, ging ich davon aus, dass dies das gewünschte Ergebnis war und das Bild ein Seitenverhältnis von 4/3 hatte. Das ist es, was ich bekomme, wenn ich versuche, am Montagabend ... +1 für eine elegante Lösung zu denken.
Terdon
Gute Antwort! Gibt es eine Möglichkeit, eine Art Etikett an die Dateinamen aller Bilder anzuhängen, die nicht dem gewünschten Verhältnis entsprechen?
Mentalist
3

Am einfachsten geht das mit ImageMagick . Es sollte sich in den Repositories Ihrer Linux-Distribution befinden und für Debian-basierte Systeme ausgeführt werden:

sudo apt-get install imagemagick

Eines der Programme der ImageMagick-Suite ist identify, dass hiermit die Eigenschaften einer Liste von Eingabebilddateien gedruckt werden. Wenn Sie es mit sortkombinieren, erhalten Sie eine Liste der Bilder, sortiert nach Größe (Sie können png für jede Erweiterung ändern, die Sie haben:

identify *png | sort -gk 3

Wenn Sie tatsächlich das Seitenverhältnis und nicht nur die Größe benötigen , versuchen Sie Folgendes:

  1. Einfache Option, vorausgesetzt Ihre Bildnamen haben keine Leerzeichen :

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

    Der Befehl gawk teilt das 3. Feld (die Bildgröße im Format LxH) in das Array "Größen" auf und druckt dann das 1. Feld (den Bildnamen) und das Ergebnis der Division der Länge des Bildes durch seine Höhe. Der sedBefehl verschönert lediglich die Ausgabe und sortsortiert das Ergebnis nach dem Bildgrößenverhältnis.

  2. Komplexer kann dieser mit Leerzeichen in Dateinamen umgehen:

    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
    

    Hier findidentifizieren wir die Dateien, an denen wir interessiert sind, führen den identifyBefehl aus und leiten seine Ausgabe über ein kleines PERL-Skript weiter. Der reguläre Ausdruck sucht nach drei Großbuchstaben ( [A-Z]{3}), die das Bildformat haben sollen. Sobald wir das gefunden haben, ist es einfach, den Bildnamen und die Abmessungen zu identifizieren.

    Ich benutze gawk hier nicht, weil das Vorhandensein von Leerzeichen in den Eingabedateinamen die Feldnummern verwirren wird. Schließlich druckt das Skript den Namen des Bildes und das Ergebnis der von uns sortnumerisch ermittelten Längen- / Höhenunterteilung aus .

Wenn das einfache Durchsuchen der verfügbaren Seitenverhältnisse nicht ausreicht und Sie mindestens ein Bild mit dem gewünschten Seitenverhältnis haben, extrahieren Sie mit grep die Bilder, deren Verhältnis am nächsten liegt:

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
terdon
quelle
2

Sie können die Differenz jedes Seitenverhältnisses mit der Referenz berechnen. Sieht aus wie die Antwort von derobert, ist aber einfacher:

ref=4/3
identify -format "%[fx:abs(w/h - $ref)] %M\n" *.jpg | sort -n -k1
Pedro Lacerda
quelle
Hmm, anscheinend macht sort rationals. Ich hatte den Eindruck, dass es nicht ...
Derobert
2

Ein Seitenverhältnis ist nur eine Zahl, so dass Sie die Bilder nach ihren Namen durchsuchen können, wenn dem Namen das Seitenverhältnis vorangestellt wird. Wenn Sie symbolische Verknüpfungen mit dem vorher festgelegten Seitenverhältnis erstellen, können Sie die Bilder nach Seitenverhältnis sortieren.

Die folgenden Viewer funktionieren wie erwartet. ( feh nicht vorwärts / rückwärts, auch für echte Bilder - auf meinem System)

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

Gehen Sie in das ar-sortVerzeichnis und navigieren Sie von einem beliebigen Ausgangspunkt (Seitenverhältnis) aus, an dem Sie interessiert sind.

Die symbolischen Linknamen sehen folgendermaßen aus:

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
Peter.O
quelle
Hinweis: Wenn Ihre Gebietsschemaeinstellungen ein anderes Dezimalzeichen als einen Punkt verwenden, funktioniert dies nicht. Einfach zu beheben: stackoverflow.com/questions/12845997/…
Jobjörn Folkesson
1

Meine übliche Argumentationsweise ist die Verwendung der Quadratfehlerdistanz-Metrik, wo immer ich Wörter "Grad der Nähe" höre. Man kann sicherlich absolute Werte verwenden, und es wäre schneller. Das Skript verwendet als Argument das ideale Seitenverhältnis, verarbeitet alle * .jpg-Dateien im aktuellen Verzeichnis und gibt sie sortiert in der aufsteigenden Reihenfolge der Abweichung vom idealen Verhältnis aus.

head Entfernt das von ImageMagick eingefügte hintere Zeilenendezeichen.

Das Skript enthält einen Befehl gawk, der das Ausgabefeldtrennzeichen auf ein unwahrscheinliches Zeichen setzt, die quadratische Differenz berechnet und den Paardifferenzdateinamen zurückgibt. Die Sortierung wird durchgeführt und unnötige Informationen (quadratische Seitenverhältnisdifferenz) werden von entfernt 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"|"
Hirschjäger
quelle
Bitte beachten Sie, dass es quadratischen Abstand und Berechnungen innerhalb gawk / awk :) (Danke an @NN für die erste Verknüpfung) verwendet
Deer Hunter
Könnten Sie Ihrer Antwort bitte eine Erklärung des Skripts hinzufügen? Es würde es besser machen.
NN