Сортировка изображений по соотношению сторон


13

Я пытаюсь выбрать несколько художественных изображений для новых кадров. Я хотел бы иметь возможность сортировать эти изображения по близости к определенному соотношению сторон, а затем просматривать их в порядке убывания близости через что-то вроде feh.

Есть ли какое-нибудь великолепное однострочное выражение Unix? В противном случае несколько десятков строк Python должны прояснить это.


3
Вы можете получить соотношение сторон через ImageMagick, например identify -format "%[fx:w/h]:%M\n" *.jpg. Я не знаю, как легко отсортировать по близости к произвольному значению. sortпохоже не поддерживает такую ​​сортировку.
NN

Ну, в общем, вы хотели бы преобразовать эти числа в целочисленную метрику расстояния, а затем вы могли бы передать ее для сортировки -n. Похоже, что вы можете сделать всю математику с ImageMagick.
Дероберт

Ответы:


8

Используя комментарий NM ImageMagick в качестве ведущей, получается, что вы можете сделать произвольные вычисления как часть его -formatвывода. Итак, один из возможных способов:

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

должен делать то, что вы хотите. Обратите внимание, что 4/3 есть постоянное, желаемое соотношение сторон. Конечно, вы можете найти это как вывод предыдущего identify(для соответствия «ближе всего к этому изображению»).

Чтобы объяснить, мы берем явную разницу между желаемым и фактическим соотношением сторон. Затем умножаем на большое число и округляем. Умножение и округление происходит потому, что сортировка обрабатывает только целые числа, а не рациональные.

редактировать

Оказывается, sortэто действительно рациональные, а не целые числа. Это даже указано в спецификации Single Unix (v4). Итак, вы можете избавиться от этого обходного пути:

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

Где вы нашли документацию по опции -format для идентификации? Я ничего не видел на странице справочника и потратил довольно много времени, пытаясь выяснить эту чертову вещь :).
Terdon

Да, и в моей системе ваша команда не работает. Я получаю, 33333:cover.jpgгде cover.jpg 500x500.
Terdon

2
@terdon хорошо, это потому, что он имеет соотношение 1/1, а не 4/3. 4 / 3-1 = 1/3 = .333…. Просто измените это 4/3 на желаемое соотношение (которое звучит как 1/1). Документы находятся по адресу imagemagick.org/script/fx.php в типичной путанице. Мне тоже понадобилось время, чтобы найти их.
Дероберт

Спасибо за ссылку. В остальном я был идиотом. У меня был только один jpg в моей тестовой папке (остальные - pngs), поэтому, поскольку я видел только одну выходную строку, я предположил, что это был желаемый результат, и эта идентификация утверждала, что изображение имеет соотношение сторон 4/3. Вот что я получаю за попытку думать по вечерам в понедельник ... +1 за элегантное решение.
Terdon

Хороший ответ! Есть ли способ добавить какую-то метку к именам файлов всех изображений, не придерживаясь желаемого соотношения?
Менталист

3

Ну, самый простой способ сделать это - использовать ImageMagick . Он должен быть в репозиториях вашего дистрибутива Linux, для систем на основе Debian:

sudo apt-get install imagemagick

Одной из программ пакета ImageMagick является identifyпечать характеристик списка файлов входных изображений. В сочетании с ним sortвы получите список изображений, отсортированных по размеру (вы можете изменить png для любого расширения:)

identify *png | sort -gk 3

Если вам действительно нужно соотношение сторон, а не только размер, попробуйте что-то вроде этого:

  1. Простой вариант, предполагает, что имена ваших изображений не имеют пробелов :

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

    Команда gawk разделяет 3-е поле (размер изображения в формате LxH) на массив «размеры», а затем печатает 1-е поле (имя изображения) и результат деления длины изображения на его высоту. Команда sedпросто украшает вывод, и sortкоманда сортирует результат в соответствии с размером изображения.

  2. Более сложный, этот может иметь дело с пробелами в именах файлов:

    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
    

    Здесь мы используем findдля идентификации интересующих нас файлов и запускаем identifyкоманду, а затем передаем ее вывод с помощью небольшого сценария PERL. Регулярное выражение ищет три заглавные буквы ( [A-Z]{3}), которые должны быть форматом изображения. Как только мы нашли это, легко определить имя и размеры изображения.

    Я не использую gawk здесь, потому что наличие пробелов в именах входных файлов будет путать номера полей. Наконец, скрипт распечатает имя изображения и результат деления длины / высоты, которое мы sortчисленно выполнили.

Если простого просмотра доступных соотношений сторон недостаточно, если у вас есть хотя бы одно изображение с желаемым соотношением сторон, просто используйте grep, чтобы извлечь те изображения, соотношение которых является ближайшим:

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

Вы можете вычислить разницу каждого соотношения сторон с помощью ссылки. Выглядит как ответ Дероберта, но проще:

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

Хм, видимо, сортировка делает рациональные решения. У меня сложилось впечатление, что это не так ...
Дероберт

2

Соотношение сторон - это просто число, поэтому вы можете просматривать изображения в соответствии с их именами, если к имени добавлен префикс отношения сторон. Создание символических ссылок с предварительно установленным соотношением сторон позволяет просматривать изображения, отсортированные по соотношению сторон.

Следующие зрители работают как положено. ( feh не пересылает / назад, даже для реальных изображений - в моей системе)

  • Comix
  • eog (Глаз Гнома / Просмотрщик изображений)
  • 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 

Зайдите в ar-sortкаталог и просто просмотрите любую начальную точку (соотношение сторон), которая вас интересует.

Имена символических ссылок выглядят так:

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

Примечание. Если в настройках вашего языка используется другой десятичный знак, кроме точки, это не сработает. Хотя это легко исправить: stackoverflow.com/questions/12845997/…
Jobjörn Folkesson

1

Моя обычная аргументация заключается в использовании квадрата метрики расстояния ошибки везде, где я слышу слова «степень близости». Можно, конечно, использовать абсолютные значения, и это будет быстрее. Сценарий принимает в качестве аргумента идеальное соотношение сторон, обрабатывает все файлы * .jpg в текущем каталоге и выводит их, отсортированные в порядке возрастания отклонения от идеального соотношения.

head удаляет завершающий символ конца строки, вставленный ImageMagick.

Сценарий содержит команду gawk, которая устанавливает разделитель выходного поля на маловероятный символ, вычисляет квадратную разницу и выводит обратно разность пар | имя файла. Выполняется сортировка и отбирается ненужная информация (квадратная разница пропорций) 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"|"

Обратите внимание, что он использует квадратичное расстояние и вычисления в gawk / awk :) (Спасибо @NN за начальный ярлык)
Охотник на оленей

Не могли бы вы добавить объяснение сценария к вашему ответу? Это сделало бы это лучше.
NN
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.