Görüntüleri en boy oranına göre sırala


13

Bazı yeni karelere uyacak birkaç sanat resmi seçmeye çalışıyorum. Bu görüntüleri belirli bir en boy oranına yakınlığa göre sıralayabilmek ve daha sonra feh gibi bir şeyle azalan yakınlık düzeninde görüntülemek istiyorum.

Muhteşem bir tek satırlık Unix ifadesi var mı? Aksi takdirde birkaç düzine Python hattı bunu temizlemelidir.


3
En boy oranını ImageMagick aracılığıyla çekebilirsiniz, örn identify -format "%[fx:w/h]:%M\n" *.jpg. Nasıl keyfi bir değere yakınlık göre sıralamak bilmiyorum. sortböyle bir sıralamayı desteklemiyor gibi görünüyor.
NN

Temel olarak, bu sayıları bir tamsayı mesafe metriğine dönüştürmek istersiniz ve sonra bunu -n'ye geçirebilirsiniz. ImageMagick ile tüm matematiği yapabileceğiniz anlaşılıyor.
derobert

Yanıtlar:


8

NN'nin ImageMagick yorumunu olası satış olarak kullanarak, -formatçıktının bir parçası olarak rastgele hesaplamalar yapabileceğiniz ortaya çıkıyor . Yani, olası bir yol:

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

ne istersen yapmalısın. İçeride 4/3 sabit, istenen en boy oranına dikkat edin. Elbette bir önceki çıktı olarak identify("bu görüntüye en yakın" eşleşir) bulabilirsiniz.

Açıklamak için, istenen ve gerçek en boy oranı arasındaki açık farkı ele alıyoruz. Sonra çok sayıda ve yuvarlayarak çarpın. Çarpma ve yuvarlama, sıralamanın rasyonel değerleri değil, yalnızca tamsayıları işlemesidir.

Düzenle

Görünüşe göre sortsadece tamsayılar değil, gerekçeler var gibi görünüyor. Tek Unix Spesifikasyonunda (v4) bile belirtilir. Böylece, bu geçici çözümden kurtulabilirsiniz:

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

İdentify'ın -format seçeneği ile ilgili belgeleri nerede buldunuz? Adam sayfasında hiçbir şey görmedim ve lanet şeyi anlamaya çalışırken epey zaman geçirdim :).
terdon

Oh, ve benim sistemimde emriniz çalışmıyor gibi görünüyor. Ben olsun 33333:cover.jpgcover.jpg 500x500 olduğu.
terdon

2
@terdon iyi, çünkü 1/1 değil 1/1 oranına sahip. 4 / 3-1 = 1/3 = .333…. Sadece 4 / 3'ü istediğiniz orana değiştirin (1/1 gibi görünüyor). Dokümanlar tipik olarak kafa karıştırıcı bir şekilde imagemagick.org/script/fx.php adresindedir . Onları da bulmak için bana biraz zaman ayırdı.
derobert

Bağlantı için teşekkürler. Geri kalanlara gelince, ben aptal oluyordum. Test klasörümde sadece bir jpg vardı (geri kalanı png'dir), bu yüzden sadece bir çıktı satırı gördüğümden beri istenen sonuç olduğunu ve bu tanımlamanın görüntünün 4/3 en boy oranına sahip olduğunu iddia ettiğini varsaydım. Pazartesi akşamları düşünmeye çalıştığım şey budur ... Zarif bir çözüm için +1.
terdon

Güzel cevap! İstenilen orana uymayan tüm görüntülerin dosya adlarına bir tür etiket eklemenin bir yolu var mı?
Mentalist

3

Bunu yapmanın en kolay yolu ImageMagick kullanmaktır . Debian tabanlı sistemler için Linux dağıtımınızın depolarında olmalıdır:

sudo apt-get install imagemagick

ImageMagick paketinin programlarından biri, identifygiriş görüntü dosyaları listesinin özelliklerini basacaktır. Bunu ile birleştirmek sortsize boyuta göre sıralanmış görüntülerin bir listesini verir (sahip olduğunuz uzantılar için png'yi değiştirebilirsiniz:

identify *png | sort -gk 3

Sadece boyuta değil , en boy oranına gerçekten ihtiyacınız varsa , şöyle bir şey deneyin:

  1. Basit seçenek, resim adlarınızın boşluk içermediğini varsayar :

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

    Gawk komutu, 3. alanı (LxH biçimindeki görüntü boyutu) "boyutlar" dizisine böler ve ardından 1. alanı (görüntü adı) ve görüntünün uzunluğunu yüksekliğine bölmenin sonucunu yazdırır. sedKomut sadece çıkış güzelleştirici ve sortkomut görüntü boyutu oranına göre sonuca sıralar.

  2. Daha karmaşık, bu dosya adlarındaki boşluklarla başa çıkabilir:

    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
    

    Burada find, ilgilendiğimiz dosyaları tanımlamak ve identifykomutu çalıştırmak için kullanıyoruz ve daha sonra çıktısını küçük bir PERL komut dosyası aracılığıyla pipetliyoruz. Normal ifade [A-Z]{3}, resim biçimi olması gereken üç büyük harf ( ) arar . Bunu bulduktan sonra, görüntü adını ve boyutlarını tanımlamak kolaydır.

    Giriş dosyası adlarında boşluk bulunması alan numaralarını karıştıracağından burada gawk kullanmıyorum. Son olarak, komut dosyası görüntünün adını ve sortsayısal olarak uzunluk / yükseklik bölümünün sonucunu yazdıracaktır .

Mevcut en boy oranlarına göz atmak yeterli değilse, istenen en boy oranına sahip en az bir görüntünüz varsa, oranı en yakın olan görüntüleri çıkarmak için grep komutunu kullanın:

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

Her bir en boy oranının farkını referansla hesaplayabilirsiniz. Derobert'in cevabı gibi görünüyor, ancak daha basit:

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

Hmm, görünüşe göre sıralama rasyonel yapıyor. Ben izlenim altında değildi ...
derobert

2

En boy oranı yalnızca bir sayıdır, bu nedenle ad en boy oranıyla önekse görüntülerine adlarına göre göz atabilirsiniz. Önceden askıya alınmış en boy oranıyla sembolik bağlantılar oluşturmak, en boy oranına göre sıralanmış görüntülere göz atmanıza olanak tanır.

Aşağıdaki izleyiciler beklendiği gibi çalışır. ( feh , sistemimde gerçek görüntüler için bile ileri / geri gitmez )

  • comix
  • eog (Gnome'un Gözü / Resim Görüntüleyici)
  • 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 

Gidin ar-sortdizin ve sadece ilgilendiğiniz noktası (boy-oranı) başlayarak her ne göz atarlar.

Sembolik bağlantı adları şöyle görünür:

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

Not: Yerel ayarlarınız noktadan başka bir ondalık işareti kullanıyorsa, bu çalışmaz. Gerçi düzeltmesi kolay: stackoverflow.com/questions/12845997/…
Jobjörn Folkesson

1

Her zamanki akıl yürütme çizgim, "yakınlık derecesi" kelimelerini duyduğum her yerde kare hata mesafesi metriğini kullanmaktır. Kesinlikle mutlak değerler kullanılabilir ve bu daha hızlı olacaktır. Komut dosyası, ideal en boy oranını bağımsız değişken olarak alır , geçerli dizindeki tüm * .jpg dosyalarını işler ve ideal orandan artan ayrışma sırasına göre sıralanmış olarak çıktılar.

head ImageMagick tarafından eklenen son satır sonu karakterini kaldırır.

Komut dosyası, çıktı alanı ayırıcısını beklenmedik bir karaktere ayarlayan, kare farkını hesaplayan ve çift farkı | dosya adını geri yazdıran bir gawk komutu içeriyor. Sıralama yapılır ve gereksiz bilgiler (kare en boy oranı farkı) tarafından kaldırılır 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"|"

Lütfen gawk / awk içinde kuadratik mesafe ve hesaplamalar kullandığını unutmayın :) (İlk kısayol için @NN'ye teşekkürler)
Deer Hunter

Cevabınıza bir betik açıklaması ekleyebilir misiniz? Daha iyi olur.
NN
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.