Sortir gambar berdasarkan rasio aspek

13

Saya mencoba memilih beberapa gambar seni agar sesuai dengan beberapa bingkai baru. Saya ingin dapat mengurutkan gambar-gambar ini berdasarkan kedekatan dengan rasio aspek tertentu dan kemudian melihatnya dalam urutan kedekatan yang menurun melalui sesuatu seperti feh.

Apakah ada ekspresi Unix satu baris yang mulia? Kalau tidak, beberapa lusin baris Python akan menghapus ini.

Jeff
sumber
3
Anda dapat menarik rasio aspek melalui ImageMagick, misalnya identify -format "%[fx:w/h]:%M\n" *.jpg. Saya tidak tahu bagaimana cara mudah menyortir berdasarkan kedekatan dengan nilai arbitrer. sorttampaknya tidak mendukung penyortiran semacam itu.
NN
Nah, pada dasarnya, Anda ingin mengonversi angka-angka itu ke metrik jarak integer, dan kemudian Anda bisa meneruskannya ke sort -n. Tampaknya Anda benar-benar dapat melakukan semua matematika dengan ImageMagick.
derobert

Jawaban:

8

Menggunakan komentar ImageMagick NN sebagai petunjuk, ternyata Anda dapat meminta Ned melakukan perhitungan sewenang-wenang sebagai bagian dari -formathasilnya. Jadi, satu cara yang mungkin:

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

harus melakukan apa yang Anda inginkan. Perhatikan bahwa 4/3 ada rasio aspek yang diinginkan konstan. Anda tentu saja dapat menemukan itu sebagai output dari sebelumnya identify(untuk mencocokkan "paling dekat dengan gambar ini").

Untuk menjelaskan, kami mengambil perbedaan nyata antara rasio aspek yang diinginkan dan aktual. Kemudian mengalikan dengan jumlah besar, dan pembulatan. Multiply dan round adalah karena sort hanya menangani bilangan bulat, bukan rasional.

sunting

Ternyata sortmemang tampak melakukan rasional, bukan hanya bilangan bulat. Bahkan ditentukan dalam Spesifikasi Unix Tunggal (v4). Jadi, Anda dapat menyingkirkan solusi itu:

identify -format "%[fx:abs((4/3)-(w/h))]:%M\n" *.jpg | \
    sort -n -k1 -t:
derobert
sumber
Di mana Anda menemukan dokumentasi pada opsi -format identifikasi? Saya tidak melihat apa-apa di halaman manual dan menghabiskan cukup banyak waktu untuk mencoba mencari tahu masalah :)
terdon
Oh, dan pada sistem saya perintah Anda sepertinya tidak berfungsi. Saya mengetahui 33333:cover.jpgcover.jpg adalah 500x500.
terdon
2
@terdon yah, itu karena ia memiliki rasio 1/1 bukan 4/3. 4 / 3-1 = 1/3 = .333…. Ubah saja 4/3 ke rasio yang Anda inginkan (yang terdengar seperti 1/1). Dokumen ada di imagemagick.org/script/fx.php dengan cara yang biasanya membingungkan. Butuh waktu beberapa saat untuk menemukan mereka juga.
derobert
Terima kasih untuk tautannya. Sedangkan sisanya, saya menjadi idiot. Saya hanya memiliki satu jpg di folder pengujian saya (sisanya adalah pngs) jadi karena saya hanya melihat satu garis keluaran saya berasumsi bahwa itu adalah hasil yang diinginkan dan identifikasi itu mengklaim bahwa gambar memiliki rasio aspek 4/3. Itulah yang saya dapatkan ketika mencoba berpikir pada Senin malam ... +1 untuk solusi yang elegan.
terdon
Jawaban bagus! Apakah ada cara untuk menambahkan semacam label pada nama file semua gambar yang tidak sesuai dengan rasio yang diinginkan?
Mentalis
3

Nah, cara termudah untuk melakukan ini adalah menggunakan ImageMagick . Itu harus di repositori distribusi Linux Anda, untuk sistem berbasis debian, jalankan:

sudo apt-get install imagemagick

Salah satu program suite ImageMagick adalah identify, ini akan mencetak karakteristik daftar file gambar input. Menggabungkannya dengan sortakan memberi Anda daftar gambar yang diurutkan berdasarkan ukuran (Anda dapat mengubah png untuk ekstensi apa pun yang Anda miliki:

identify *png | sort -gk 3

Jika Anda benar-benar membutuhkan rasio aspek dan bukan hanya ukurannya, cobalah sesuatu seperti ini:

  1. Opsi sederhana, anggap nama gambar Anda tidak memiliki spasi :

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

    Perintah gawk membagi bidang ke-3 (ukuran gambar yang memiliki format LxH) ke dalam array "ukuran" dan kemudian mencetak bidang ke-1 (nama gambar) dan hasil membagi panjang gambar dengan tingginya. The sedperintah hanya mempercantik output dan sortperintah macam hasil sesuai dengan rasio ukuran gambar.

  2. Lebih kompleks, ini dapat menangani spasi dalam nama 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
    

    Di sini kita gunakan finduntuk mengidentifikasi file-file yang kita minati dan menjalankan identifyperintah, dan kemudian menyalurkan hasilnya melalui skrip PERL kecil. Ekspresi reguler mencari tiga huruf besar ( [A-Z]{3}) yang harus berupa format gambar. Setelah kami menemukan itu, mudah untuk mengidentifikasi nama dan dimensi gambar.

    Saya tidak menggunakan gawk di sini karena keberadaan spasi di nama file input akan membingungkan nomor bidang. Akhirnya, skrip akan mencetak nama gambar dan hasil pembagian panjang / tinggi yang kita sortnumerik.

Jika hanya menjelajah rasio aspek yang tersedia tidak cukup, jika Anda memiliki setidaknya satu gambar dengan rasio aspek yang diinginkan, cukup gunakan grep untuk mengekstrak gambar-gambar yang rasio terdekatnya:

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
sumber
2

Anda dapat menghitung perbedaan masing-masing rasio aspek dengan referensi. Sepertinya jawaban derobert, tetapi lebih sederhana:

ref=4/3
identify -format "%[fx:abs(w/h - $ref)] %M\n" *.jpg | sort -n -k1
Pedro Lacerda
sumber
Hmm, rupanya semacam memang rasional. Saya mendapat kesan itu tidak ...
derobert
2

Rasio aspek hanyalah angka, sehingga Anda dapat menelusuri gambar sesuai dengan namanya, jika nama diawali dengan rasio aspek. Membuat tautan simbolis dengan rasio aspek pra-pended memungkinkan Anda untuk menelusuri gambar yang diurutkan berdasarkan rasio aspek.

Pemirsa berikut berfungsi seperti yang diharapkan. ( feh tidak maju / mundur, bahkan untuk gambar nyata - di sistem saya)

  • comix
  • eog (Eye of Gnome / Penampil Gambar)
  • lihatlah

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 

Pergilah ke ar-sort direktori dan cukup telusuri dari titik awal apa pun (rasio aspek) yang Anda minati.

Nama tautan simbolis terlihat seperti ini:

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
sumber
Catatan: jika pengaturan lokal Anda menggunakan tanda desimal lain selain titik, ini tidak akan berfungsi. Mudah diperbaiki: stackoverflow.com/questions/12845997/…
Jobjörn Folkesson
1

Garis penalaran saya yang biasa adalah menggunakan metrik jarak kesalahan kuadrat di mana pun saya mendengar kata "derajat kedekatan". Seseorang pasti dapat menggunakan nilai absolut, dan itu akan lebih cepat. Script mengambil sebagai argumen rasio aspek ideal , memproses semua file * .jpg di direktori saat ini dan output mereka diurutkan dalam urutan peningkatan divergensi dari rasio ideal.

head menghapus karakter end-of-line trailing yang dimasukkan oleh ImageMagick.

Skrip berisi perintah gawk yang mengatur pemisah bidang keluaran ke karakter yang tidak mungkin, menghitung perbedaan kuadrat dan mencetak kembali perbedaan pasangan | nama file. Sortir dilakukan dan informasi yang tidak perlu (perbedaan rasio aspek kuadrat) diambil oleh 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"|"
Pemburu rusa
sumber
Harap dicatat bahwa ia menggunakan jarak kuadratik dan perhitungan dalam gawk / awk :) (Terima kasih kepada @NN untuk pintasan awal)
Deer Hunter
Bisakah Anda menambahkan penjelasan skrip ke jawaban Anda? Itu akan membuatnya lebih baik.
NN