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



Но машины все еще не люди, и далеко не всегда будет вырезана нужная область. Старые способы типа вырезать миниатюру 100х100 из левого верхнего угла или из центра отходят на второй план, и на арену выходит смарт-кроп.

Традиционный смарт-кроп


Большинство библиотек для избежания искажения и растягивания фоток используют смарт-кроп. Суть в том, что сначала код ресайзит картинку так, чтобы один из параметров — длина или ширина — соответствовали заданному. Затем проверяет, соответствует ли второй параметр заданному. Если нет, выполняется кроп лишних областей начиная от центра.

Создание миниатюры, допустим, 400х400 будет происходить так:



Загвоздка в том, что далеко не всегда (а точнее почти никогда) самое главное оказывается в самом центре. Чаще всего — какая-то часть главного, но объекты чаще всего так или иначе смещены.

Смарт-кроп на основе энтропии


Общая идея — найти фрагмент картинки, несущий наибольшее количество информации и сохранить его в кропнутой версии.

Как это работает


Сначала картинка ресайзится.

Затем запускается фильтр для определения границ. Картинка становится черно-белой и на ней остаются только контуры обьектов.

Максимально снижается насыщенность и картинка несколько “замыливается”.

Определяется фрагмент с наивысшей энтропией — то есть с наибольшим количеством контуров. Возвращаются координаты этого фрагмента, то есть той части картинки, которую обрезать нельзя ни в коем случае.


Самый сложный этап — поиск фрагмента с наивысшей энтропией. Поиск выполняется фрагментарно — картинка “разрезается” на 25 полосок, подсчитывается энтропия для каждой из них и сравнивается. Затем определяется группа с максимальной энтропией.

Применение


Для применения удобно использовать вот эту библиотеку.
Требования: PHP 5.3 с расширением Imagick. Применяется в три этапа.

Инициализация:

$center = new CropEntropy($imagePath);

Ресайз и кроп:

$croppedImage = $center->resizeAndCrop($width, $height);

Cохранение нового изображения:

$croppedImage->writeimage($newImagePath);


Попробовать кроп на основе энтропии можно тут, задав требуемый размер миниатюры.
Иногда алгоритм безошибочно определяет самую важную область. Но иногда и ошибается, особенно при нестандартных — неквадратных параметрах кропа (300х100). Но вот очень хороший результат с теми же параметрами, но другой фоткой. Идеального результата алгоритм не гарантирует, но тем не менее является одним из лучших способов автокропа.

Конспект


  1. Один из лучших способов автоматизации кропа — кроп на основе энтропии.
  2. Алгоритм определяет фрагмент с наибольшим количеством информации и сохраняет его в кропнутой версии.
  3. Преимущества и недостатки способа можно проверить этим инструментом.

Комментарии (17)


  1. lleo_aha
    12.06.2015 11:55
    +14

    Рискну конечно погореть, но где тут PHP то? Тут больше похоже на рекламу онлайн-сервиса вроде бы :)


  1. shoomyst
    12.06.2015 12:28

    Что за класс CropEntropy? Где брать?


    1. Capuchin Автор
      12.06.2015 12:45

      Вот в этой библиотеке.


  1. Chris_Griffin
    12.06.2015 12:34
    +3

    Полагаю, что если не реализация, то идея алгоритма взята здесь codegeekz.com/cropping-images-entrop.

    Были идеи сделать перевод на хабре, но так руки и не дошли.


  1. johniek_comp
    12.06.2015 12:38
    +2

    Почему у Вас на сайте нет валидации, sendmail?mail= можно что угодно написать, все равно выдаст «ok»? Зачем писать ок в любом случае, если «error» скорее всего не предусмотрен?


  1. lostpassword
    12.06.2015 13:02
    -12

    Можете назвать меня ханжой, но жопа в ленте хабра мне совершенно не нравится.
    Даже если это рисованная жопа Барта Симпсона.


    1. datacompboy
      12.06.2015 13:11
      +42

      Здравствуйте, Ханжой!


    1. Klaster
      12.06.2015 15:35
      +27

      У меня серьезнее проблема, я почему то вместо умный кроп, Читаю укроп и сразу вижу жопу. Долбанная политика.


  1. david_mz
    12.06.2015 13:04
    +7

    Это ваш сервис, да?

    Я бы посоветовал помимо плотности деталей использовать нахождение лиц на фото (opencv это вполне неплохо умеет). Лицо для человеческого восприятия гораздо важнее любых других деталей. Если на фото есть лица, то их расположению должен отдаваться приоритет. Как-то так делает Твиттер при обрезке фотографий в твитах.


    1. Agent_Smith
      12.06.2015 14:54

      В одном iOS приложении использовал FaceImageView для аватарок. Она использует CoreImage для определиня лиц, и автоматически выравнивает по этим областям картинку.


  1. saggid
    12.06.2015 13:13
    +3

    По-моему, всё-таки лучше человеку дать возможность самому указать нужную область, как это нынче делается на всех популярных онлайн-сервисах. Для этого есть хорошая JS-библиотека под названием Jcrop. Показываем с помощью неё клиенту изображение, он выделяет нужную область, и потом её мы и вырезаем и делаем аватаркой. Я на нескольких сайтах использовал такой подход, получается очень удобно и качественно.


  1. relgames
    12.06.2015 13:57
    +15

    Действительно — самое важное осталось :) i.onthe.io/crop?r=6cd1d969906ea893c49fd4feebdf3053


    1. david_mz
      12.06.2015 15:01
      +4

      А вот как ту же картинку кропнул Твиттер: yadi.sk/i/M4HEjmZchDjJt


    1. alexeygrigorev
      12.06.2015 20:26

      Картинка уже умерла? Ничего не отображает


      1. alexeygrigorev
        12.06.2015 20:31

        Отбой, т.к. картинка раздается через 88-й порт, мой фаейрвол ее обрезал. Через VPN все ок


  1. dom1n1k
    12.06.2015 14:35
    +2

    Позднее стоит написать, что все эти статьи дали вашем сервисам в смысле популярности :) Краткосрочной и долгосрочной. Это отдельная и очень интересная тема.


  1. sergehog
    09.07.2015 14:10
    -1

    Почему люди еще не используют Сим-Карвинг ??