Ликбез: методы ресайза изображений

    Почему изображение, масштабированное с бикубической интерполяцией, выглядит не как в Фотошопе. Почему одна программа ресайзит быстро, а другая — нет, хотя результат одинаковый. Какой метод ресайза лучше для увеличения, а какой для уменьшения. Что делают фильтры и чем они отличаются.

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


    Этот человек сидит среди ромашек, чтобы привлечь ваше внимание к статье.

    Для наглядного сравнения я буду использовать изображения одинакового разрешения 1920×1280 (одно, второе), которые буду приводить к размерам 330×220, 1067×667 и 4800×3200. Под иллюстрациями будет написано, сколько миллисекунд занял ресайз в то или иное разрешение. Цифры приведены лишь для понимания сложности алгоритма, поэтому конкретное железо или ПО, на котором они получены, не так важно.


    Ближайший сосед (Nearest neighbor)


    Это самый примитивный и быстрый метод. Для каждого пикселя конечного изображения выбирается один пиксель исходного, наиболее близкий к его положению с учетом масштабирования. Такой метод дает пикселизированное изображение при увеличении и сильно зернистое изображение при уменьшении.



    Вообще, качество и производительность любого метода уменьшения можно оценить по отношению количества пикселей, участвовавших в формировании конечного изображения, к числу пикселей в исходном изображении. Чем больше это отношение, тем скорее всего алгоритм качественнее и медленнее. Отношение, равное одному, означает что как минимум каждый пиксель исходного изображения сделал свой вклад в конечное. Но для продвинутых методов оно может быть и больше одного. Дак вот, если например мы уменьшаем изображение методом ближайшего соседа в 3 раза по каждой стороне, то это соотношение равно 1/9. Т.е. большая часть исходных пикселей никак не учитывается.




    1920×1280 → 330×220 = 0,12 ms
    1920×1280 → 1067×667 = 1,86 ms
    1920×1280 → 4800×3200 = 22,5 ms

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

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


    Аффинные преобразования (Affine transformations)


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

    Принцип действия заключается в том, что для каждой точки конечного изображения берется фиксированный набор точек исходного и интерполируется в соответствии с их взаимным положением и выбранным фильтром. Количество точек тоже зависит от фильтра. Для билинейной интерполяции берется 2x2 исходных пикселя, для бикубической 4x4. Такой метод дает гладкое изображение при увеличении, но при уменьшении результат очень похож на ближайшего соседа. Смотрите сами: теоретически, при бикубическом фильтре и уменьшении в 3 раза отношение обработанных пикселей к исходным равно 4² / 3² = 1,78. На практике результат значительно хуже т.к. в существующих реализациях окно фильтра и функция интерполяции не масштабируются в соответствии с масштабом изображения, и пиксели ближе к краю окна берутся с отрицательными коэффициентами (в соответствии с функцией), т.е. не вносят полезный вклад в конечное изображение. В результате изображение, уменьшенное с бикубическим фильтром, отличается от изображения, уменьшенного с билинейным, только тем, что оно еще более четкое. Ну а для билинейного фильтра и уменьшения в три раза отношение обработанных пикселей к исходным равно 2² / 3² = 0.44, что принципиально не отличается от ближайшего соседа. Фактически, аффинные преобразования нельзя использовать для уменьшения более чем в 2 раза. И даже при уменьшении до двух раз они дают заметные эффекты лесенки для линий.

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




    1920×1280 → 330×220 = 6.13 ms
    1920×1280 → 1067×667 = 17.7 ms
    1920×1280 → 4800×3200 = 869 ms

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

    Мое скромное мнение, что использование этого способа для произвольного уменьшения изображений попросту является багом, потому что результат получается очень плохой и похож на ближайшего соседа, а ресурсов на этот метод нужно значительно больше. Тем не менее, этот метод нашел широкое применение в программах и библиотеках. Самое удивительное, что этот способ используется во всех браузерах для метода канвы drawImage() (наглядный пример), хотя для простого отображения картинок в элементе используются более аккуратные методы (кроме IE, в нем для обоих случаев используются аффинные преобразования). Помимо этого, такой метод используется в OpenCV, текущей версии питоновской библиотеки Pillow (об этом я надеюсь написать отдельно), в Paint.NET.

    Кроме того, именно этот метод используется видеокартами для отрисовки трехмерных сцен. Но разница в том, что видеокарты для каждой текстуры заранее подготавливают набор уменьшенных версий (mip-уровней), и для окончательной отрисовки выбирается уровень с таким разрешением, чтобы уменьшение текстуры было не более двух раз. Кроме этого, для устранения резкого скачка при смене mip-уровня (когда текстурированный объект приближается или отдаляется), используется линейная интерполяция между соседними mip-уровнями (это уже трилинейная фильтрация). Таким образом для отрисовки каждого пикселя трехмерного объекта нужно интерполировать между 2³ пикселями. Это дает приемлемый для быстро движущейся картинки результат за время, линейное относительно конечного разрешения.


    Суперсемплинг (Supersampling)


    С помощью этого метода создаются те самые mip-уровни, с помощью него (если сильно упростить) работает полноэкранное сглаживание в играх. Его суть в разбиении исходного изображения по сетке пикселей конечного и складывании всех исходных пикселей, приходящихся на каждый пиксель конечного в соответствии с площадью, попавшей под конечный пиксель. При использовании этого метода для увеличения, на каждый пиксель конечного изображения приходится ровно один пиксель исходного. Поэтому результат для увеличения равен ближайшему соседу.



    Можно выделить два подвида этого метода: с округлением границ пикселей до ближайшего целого числа пикселей и без. В первом случае алгоритм становится малопригодным для масштабирования меньше чем в 3 раза, потому что на какой-нибудь один конечный пиксель может приходиться один исходный, а на соседний — четыре (2x2), что приводит к диспропорции на локальном уровне. В то же время алгоритм с округлением очевидно можно использовать в случаях, когда размер исходного изображения кратен размеру конечного, или масштаб уменьшения достаточно мал (версии разрешением 330×220 почти не отличаются). Отношение обработанных пикселей к исходным при округлении границ всегда равно единице.




    1920×1280 → 330×220 = 7 ms
    1920×1280 → 1067×667 = 15 ms
    1920×1280 → 4800×3200 = 22,5 ms

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




    1920×1280 → 330×220 = 19 ms
    1920×1280 → 1067×667 = 45 ms
    1920×1280 → 4800×3200 = 112 ms

    Производительность этого метода для уменьшения ниже, чем у аффинных преобразований, потому что в расчете конечного изображения участвуют все пиксели исходного. Версия с округлением до ближайших границ обычно быстрее в несколько раз. Также возможно создать отдельные версии для масштабирования в фиксированное количество раз (например, уменьшение в 2 раза), которые будут еще быстрее.

    Данный метод используется в функции gdImageCopyResampled() библиотеки GD, входящей в состав PHP, есть в OpenCV (флаг INTER_AREA), Intel IPP, AMD Framewave. Примерно по такому же принципу работает libjpeg, когда открывает изображения в уменьшенном в несколько раз виде. Последнее позволяет многим приложениям открывать изображения JPEG заранее уменьшенными в несколько раз без особых накладных расходов (на практике libjpeg открывает уменьшенные изображения даже немного быстрее полноразмерных), а затем применять другие методы для ресайза до точных размеров. Например, если нужно отресайзить JPEG разрешением 1920×1280 в разрешение 330×220, можно открыть оригинальное изображение в разрешении 480×320, а затем уменьшить его до нужных 330×220.


    Свертки (Convolution)


    Этот метод похож на аффинные преобразования тем, что используются фильтры, но имеет не фиксированное окно, а окно, пропорциональное масштабу. Например, если размер окна фильтра равен 6, а размер изображения уменьшается в 2,5 раза, то в формировании каждого пикселя конечного изображения принимает участие (2,5 * 6)² = 225 пикселей, что гораздо больше, чем в случае суперсемплинга (от 9 до 16). К счастью, свертки можно считать в 2 прохода, сначала в одну сторону, потом в другую, поэтому алгоритмическая сложность расчета каждого пикселя равна не 225, а всего (2,5 * 6) * 2 = 30. Вклад каждого исходного пикселя в конечный как раз определяется фильтром. Отношение обработанных пикселей к исходным целиком определяется размером окна фильтра и равно его квадрату. Т.е. для билинейного фильтра это отношение будет 4, для бикубического 16, для Ланцоша 36. Алгоритм прекрасно работает как для уменьшения, так и для увеличения.




    1920×1280 → 330×220 = 76 ms
    1920×1280 → 1067×667 = 160 ms
    1920×1280 → 4800×3200 = 1540 ms

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

    Именно этот метод реализован в ImageMagick, GIMP, в текущей версии Pillow с флагом ANTIALIAS.

    Одно из преимуществ этого метода в том, что фильтры могут задаваться отдельной функцией, никак не привязанной к реализации метода. При этом функция самого фильтра может быть достаточно сложной без особой потери производительности, потому что коэффициенты для всех пикселей в одном столбце и для всех пикселей в одной строке считаются только один раз. Т.е. сама функция фильтра вызывается только (m + n) * w раз, где m и n — размеры конечного изображения, а w — размер окна фильтра. И наклепать этих функций можно множество, было бы математическое обоснование. В ImageMagick, например, их 15. Вот как выглядят самые популярные:

    Билинейный фильтр (bilinear или triangle в ImageMagick)

    Бикубический фильтр (bicubic, catrom в ImageMagick)

    Фильтр Ланцоша (Lanczos)


    Примечательно, что некоторые фильтры имеют зоны отрицательных коэффициентов (как например бикубический фильтр или фильтр Ланцоша). Это нужно для придания переходам на конечном изображении резкости, которая была на исходном.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну, и что?
    Реклама
    Комментарии 72
    • +4
      Все эти методы оперируют обычным растром, где каждый пиксель имеет три составляющих цвета. Но вот у 99.9% камер на матрице каждый пиксель имеет всего один светофильтр и собирает только одну составлящую цвета. Это так называемый фильтр Байера. И сначала информацию с баейра интерполируют в растр, а потом растр масштабируют. Имхо гораздо более высокого качества (цвета и деталей) можно было бы добиться, если считать конечную картинку в один проход без промежуточных преобразований. Есть ли какие-то существующие RAW-конверторы, умеющие применять тот же бикубический фильтр напрямую к байеровкому изображению (учитывая цвет фильтров пикселей и расстояние до них от центра результирующего пикселя)?
      • 0
        Для начала объясните зачем ресемплировать RAW?
        • 0
          Вопрос скорее. «что же эти изобретатели фотоаппаратов не додумались до такой простой вещи».
          • 0
            Но зачем? Ведь потом с полученным ресемлированным изображением придется как-то взаимодействовать алгоритму де-байеризаци. Да и сам практический смысл абсолютно не понятен.
            • +2
              Вы не поняли. На выходе я ожидаю получить нормальный растровый tiff или jpeg, а не ресемплированный байер.
              • +3
                Просто мылить байер в растр, потом его ресемплировать, потом шарпить, это как рыбу несколько раз замораживать-размораживать а потом удивляться чего она невкусная. Хочется сразу с байера получать выходной растр нужного размера без промежуточных преобразований. То что это сложно, медленно, требует сбора данных с нескольких рядов ради получения одного цвета — это понятно.
                • –1
                  Если вы будите ресайзить картинку до дебайеризации, то потом вам Amaze это таким узорами разрисует — засмотришься.
                  • +2
                    Мне кажется вы не понимаете сути де-байеризации.
                    • +1
                      А если вы понимаете — не скажете, где можно посмотреть основные алгоритмы? Есть ли что-нибудь, кроме нескольких функций из dcraw, например, теория, которая за ними стоит, или хотя бы основные идеи?
                        • 0
                          По ссылкам я вижу только примеры использования. Нет ли каких-нибудь алгоритмов, для которых есть описание работы? Понимаю, что большинство из них — know-how, но ведь хоть что-то, более качественное, чем независимая билинейная интерполяция цветов, могло бы быть открыто?
                          • +1
                            Посмотрите в этой статье: http://www.int-arch-photogramm-remote-sens-spatial-inf-sci.net/XXXIX-B5/387/2012/isprsarchives-XXXIX-B5-387-2012.pdf. Там есть ссылки на статьи с описанием многих алгоритмов, правда как миниму некоторые из них доступны только по подписке.
                            • 0
                              Спасибо. Буду разбираться.
                            • 0
                              Я связан с этими вещами только практической необходимостью: много снимаю и обрабатываю.
                              • 0
                                И для этого действительно нужно «понимать суть де-байеризации»?
                                Для меня совершенно неочевидно, что нельзя получить выигрыша, если переход от растра к масштабированному или повёрнутому изображению выполнять за один шаг, более сложным алгоритмом. И чтобы это понять, надо разобраться не только в том, какие алгоритмы есть и как они работают, но и почему они именно такие, какие особенности физики и физиологии в них используются. Тогда можно более или менее приблизиться к сути, и начать искать ответ на поставленный вопрос.
                                • –2
                                  Да. Потому что RAW это не просто картинка. Это сигнал с датчиков матрицы камеры. Каждый пиксель не имеет цвета. Это просто массив цифр. Если его отресайзить все значения тупо перемешаются и алгоритм де-байеризации выдаст не цвет, а подобие кислотного трипа.

                                  Почему я знаю это, а товарищи программисты нет? Вот это интереснее.
                                  • 0
                                    Естественно никто не собирается тупо ресайзить RAW а потом вызывать дебайеризацию. Идея другая, и в общем разумная — совместить дебайеризацию с ресайзом.

                                    Потому что при дебайеризации мы пытается повысить разрешение цветовых раналов картинки — восстановить значиние цвета там, где его в RAW не было. Но если затем мы все равно собираемся уменьшить картинку (для публикачии в интернете например), то получается что мы делаем лишнюю работу. Возможно, можно сразу при дебайеризации получить картинку нужного разрешения. Примерно так, как работает метод half в dcraw, только лучше.

                                    Вот возможность такого и хочет изучить Mrrl
                                    • 0
                                      Примерно так. При преобразовании мы хотим получить цвет не в исходных точках растра, а в интерполированных точках, или усреднённых, или свёрнутых с чем-то… Когда мы выполняем преобразование восстановленной картинки, то мы используем компоненты цвета, которые в некоторых точках исходные, а в других — восстановленные (в действительности, это неправда: поскольку при дебайеризации нам пришлось умножать вектор сигналов на матрицу преобразования в линейное цветовое пространство, цвета будут восстановлены всегда). Так может быть, если наша область свёртки захватывает больше 4 датчиков каждого цвета, то можно поменять действия местами — сначала найти значения каждого цвета в пространстве сигналов матрицы, а потом перейти в RGB?
                                      Одна из идей: что если вместо восстановления цвета в каждом пикселе, считать значение в углах пикселей (точках, где сходятся датчики всех трёх цветов)? Раз так не делают, значит, будет плохо, но почему?
                                      • 0
                                        Ну вообще-то так и делают. Это самый простой, очевидный и в принципе вполне пригодный алгоритм. Практически любое описание процесса дебайризации начинается с него.
                                        • 0
                                          И как после его работы будет выглядеть слегка наклонная граница чёрного и белого? На первый взгляд, там должны чередоваться жёлтый и голубой цвета (точнее, FF8000 и 0080FF). Если это так, то вряд ли хоть кто-нибудь назовёт его «вполне пригодным».
              • +2
                Ну почему же не додумались? Кэноны, например, могут писать равы меньшего размера.
              • +1
                > Для начала объясните зачем ресемплировать RAW?
                Имея в распоряжении исходные данные, для получения более качественного результата логично оперировать ими, а не суррогатом, полученным на их основе.
                А зачем ресемплировать вообще — для получения растрового изображения требуемого размера в пикселях.
                • 0
                  Меня наверно опять заминусуют, но я таки отвечу:
                  Проблема в байеровском муаре.
                  Вот это мишень:
                  www.libraw.su/sites/libraw.su/files/images/porcupine.png
                  её сфотографировали и вот что вышло:
                  www.libraw.su/sites/libraw.su/files/images/porcupine-q0.png
                  Красота? Это как раз и есть главная проблема демозаика. Как только в кадре появляется ритмично повторяющийся рисунок, шаг которого близок к шагу байровской сетки матрицы вы получаете вот такого рода артефакты.
                  Вы предлагаете отресеплить RAW и получить шаг сетки гораздо больший. Фактически у вас будет два шага в кадре — оригинальный и шаг который вам подарит ресемплер бесплатно без регистрации и смс. Таким образом вы только увеличите количество объектов которые покроются байеровским муаром.
              • +1
                Тогда надо учитывать порядок расположения сенсоров разных цветов, их размеры(сенсор разного цвета может быть разного размера) и узор расположения на матрице. фото- и видео-матрицы имеют разный узор расположения пикселей и субпикселей.
              • 0
                Спасибо. Познавательно.
                К сожалению прочитав статью не могу сказать что с одного раза сформировал в голове четкий алгоритм в каком случае какой способ лучше.
                Я бы рекомендовал в конце статьи составить простой список типа: входные условия — рекомендуемый фильтр. По такому списку можно быстро пробежать глазами и выбрать подходящий способ. Если захочется понять почему можно углубиться снова в статью и освежить информацию. Человек так устроен, что прочитав более менее обширную информацию через неделю забудет её (если интенсивно ей не пользуется конечно).
                Ещё была бы интересна обзорная таблица где представлены ведущие радакторы и библиотеки для обработки изображений и поддерживаемые ими фильтры.
                Спасибо
                • +7
                  Бикубический или Lanczos плюс шарп по желанию в тренде кучу лет.
                  Nearest neighbor если нужно показать крайне резкие детали… там листики… как в этой статье у меня:
                  habrahabr.ru/post/158381/
                  image
                  С бикубическим такого не получится и то… на любителя.
                  Остальные методы малоактуальные.
                  • +4
                    Если мы говорим о своем приложении, то в большинстве случаев вы скованы имеющимися у вас библиотеками. Если ваша библиотека умеет только аффинные преобразования, то какой фильтр не используй, получится практически ближайший сосед. Если она умеет свертки, но не умеет суперсемплинг, то научить её можно только суперсемлпингу с округлением границ, используя box фильтр (т.е. фильтр, который дает единицу от -0.5 до 0.5, и ноль на остальном протяжении), но смысла в этом никакого, потому что такая эмуляция суперсемплинга все равно будет работать со скоростью сверток.

                    Если же у вас действительно есть выбор, то вот список от лучшего и медленного до неплохого, но очень быстрого:
                    Свертки с фильтром Ланцоша
                    Свертки с бикубическим фильтром (в ImageMagick он называется catrom)
                    Суперсемплинг без округления
                    Суперсемплинг с округлением

                    При этом нужно учитывать, что если вам нужно не только уменьшение, но и увеличение, то суперсемплинг не годится.
                    • 0
                      Бесит, когда мелкие картинки (типа иконок) отображаются сильно увеличенными (×10, ×100 и больше) в виде размазанного облака не пойми чего в программах-смотрелках. Я так понимаю, алгоритмы увеличения в разы должны бы сильно отличаться от алгоритмов увеличения на проценты. Бороться с пикселизацией в лоб имеет смысл только при небольших масштабированиях. На больших масштабах придумывали особые методы депикселизации, как то раз я видел статью про сглаживание пиксель-арта, там чуть ли не очень хитрая промежуточная векторизация проводилась.
                    • 0
                      Свертки с бикубическим фильтром (в ImageMagick он называется catrom)

                      Это просто один из вариантов коэффициентов Catmull–Rom сплайн
                    • 0
                      тут такой простой таблицей не обойтись. Скорей всего надо разложить по полочкам такие параметры фильтров как сложность, качество, направление и диапазон масштабирования, время работы. Так чтобы можно было подобрать нужный алгоритм прямо по месту по необходимым параметрам. Ведь ясное дело чем качественней картинка тем дольше работать алгоритм будет, но не всегда нужно качество иногда на первом месте стоит скорость работы(превьюшки создать для предпросмотра).
                      • 0
                        Это же всё можно на спектрах, теореме отсчётов и фильтрах нижних частот объяснить. Изменение частоты дискретизации, наложение спектров и так далее. Всё было бы наглядно.
                        Та же билиненая и треугольная функции (на первое место забыли вставить прямоугольную) являются последовательными свёртками: из двух одинаковых прямоугольников получается треугольник, из двух треугольников — кубический сплайн и так далее по посинения. Причём в области спектра это соответствует всё более узкому фильтру нижних частот: пресловутый синус Котельникова умножается на себя N-раз (N=1 — ближайший сосед, N=2 — билинейное, N=3 — кубическое).
                      • +6
                        Есть довольно примечательная работа по увеличению изображений под авторством А. Сухинова.

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

                        Программа дает довольно хорошие результаты:
                        Оригинал
                        image
                        Увеличение в два раза:
                        image

                        Статья с частичным описанием алгоритма.
                        • 0
                          В вашем комменте изображения идентичны по масштабу. Возможно резкость чуть отличается.
                          • +1
                            Это результат отображения их движком сайта, который их таки немножко масштабирует. Нужно открывать ссылки и смотреть в отдельных окнах/вкладках:
                            Исходное
                            Увеличенное
                          • 0
                            Продайте Эпплу для ретины.
                            • 0
                              Как сказал когда-то современник, уже успевший стать классиком: "Мопед Конвертер не мой, я просто разместил ссылку!"
                              • 0
                                Вы сначала скорость замерьте. Там далеко не реалтайм.)
                              • 0
                                Видимо там нечто похожее на полный перебор результирующих пикселей, у меня давно была такая идея и они это всё же сделали.
                              • +3
                                Можно ещё добавить, что для операции свёртки с большим ядром (больше 8 пикселей, емнип), можно применять преобразование Фурье, тогда сложность зависит только от размеров изображения и не зависит от размера ядра.

                                Ещё можно рассказать, для чего нужны разные фильтры в последнем случае и что они делают. Недавно как раз читал небольшую заметку на эту тему (на англ.): hirntier.blogspot.ru/2008/12/downscaling-algorithms.html
                                • 0
                                  А так действительно ресайз картинок делается? Тот же Lanczos, насколько я понимаю, зависит от точки. Т.е. свёртка там не с постоянным ядром, а с зависящим от текущей позиции.

                                  А ещё, кажется, полноценная свёртка нам не нужна, т.к. не для каждого пикселя исходного изображения нужно её считать.
                                • +3
                                  Ещё важная деталь: ресайз следует проводить в линейном цветовом пространстве. Иначе будут артефакты и искажения.
                                  • 0
                                    Вы вот это www.4p8.com/eric.brasseur/gamma.html имеете в виду?

                                    Уменьшение изображения
                                    image

                                    в два раза большинством программ дает результат
                                    image

                                    хотя корректно было бы так:
                                    image
                                • 0
                                  Как-то раз сравнивал алгоритмы, которые есть в ImageMagick, Irfanview, ImageJ (штатные и в виде плагинов). Сортировал их по резкости получаемого результата.
                                  Получилось вот такое:
                                  Осторожно, картинка шириной 2600 px
                                  сравнение резкости

                                  Также делал по ним объективное измерение и строил график:
                                  Тоже весьма немаленькая каритнка
                                  график резкости и место измерения
                                  • 0
                                    Least squares cubic на мой взгляд даёт самую приятную картинку. Максимально резкую из пластичных.
                                    Где доступен данный алогритм?
                                • 0
                                  Кстати, было бы неплохо всем этим методам выборки указать их названия. Вот XnView, например, предлагает, помимо бикубической, билинейной, интерполяции по соседним и упомянутого тут Lanczos, ещё следующие варианты:

                                  Hermite
                                  Gaussian (тут вроде всё понятно)
                                  Bell
                                  Bspline
                                  Mitchell
                                  Hanning

                                  Было бы круто иметь под рукой список, как посоветовали выше, что есть что и в каком случае удобно применять. Ибо я тут даже затрудняюсь сказать что конкретно каждый из них делает вообще.
                                  • +2
                                    В документации ImageMagick есть обширнейшая статья по этому поводу.
                                    Все приведенные вами фильтры — свёрточные.
                                    В частности, Hermite, B-spline и Mitchell относятся к кубическим — то есть их весовая функция это кубический полином. Там приводится такая картинка для кубических фильтров:
                                    image
                                    Gaussian приводит обычно к заметному размытию, и поэтому редко используется.
                                    Bell означает использование колоколообразной функции, но что именно авторы XnView под этим понимают, я затрудняюь сказать.

                                    Другой большой класс функций — это sinc, умноженный на разные "окна".
                                    Hanning использует функцию sinc умноженную на окно Хана.
                                    Lanzos это sinc * растянутый sinc в качестве окна.

                                    В качестве рекомендации там сказано следующее:
                                    The Best Filter?
                                    That is something you will need to work out yourself. Often however it depends on what type of image and resizing you are doing.

                                    For enlarging images 'Mitchell' is probably about the best filter you can use, while basically any of the Windowed Filters (default is 'Lanczos') are good for shrinking images, especially when some type of low level pattern is involved. However if you have no patterns, but lots of straight edges (such as GIF transparency), you may be better off using sharpened Gaussian Filter or again a 'Mitchell', so as to avoid strong ringing effects.

                                    The 'Lagrange' filter is also quite good, especially with a larger Filter Support Setting, for shrinking images.

                                    For those interested I recommend you look at the IM User Discussion topic a way to compare image quality after a resize? which basically shows that their is no way of quantitatively determining «The Best Filter», only a qualitative or subjective «Best Filter».

                                    The choice is yours, and choice is a key feature of ImageMagick.
                                    Для увеличения изображений рекомендуют Mitchell, для уменьшения подойдет любой их оконных (по умолчанию Lanzos), если есть много мелких «узоров». Если же «узоров» нет, зато есть прямы границы, то лучше Гаусс с повышением резкости либо Mitchell, чтобы избежать сильного звона.

                                    В самом ImageMagick в по умолчанию для повышения разрешения используется Mithell, а во всех остальных случаях — Lanzos.
                                    • 0
                                      Круто, спасибо! Я знал, что хабр не подведёт =)
                                  • +1
                                    Есть еще полином- преобразование — дающее алгебраическую точность (сотни лет применяется в картографии). На основе точек исходного изображения Можно составить полином который будет алгебраически приближатся к общей энтропийной функции изображения. Зависит только от количества выделенного времени на вычисление коофициентов полинома.

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

                                    P.S. И вообще почему бы изображение не хранить как набор коофициентов полинома. Можно формировать изображение нужного размера уже при открытии файла.
                                    • +2
                                      И вообще почему бы изображение не хранить как набор коофициентов полинома. Можно формировать изображение нужного размера уже при открытии файла

                                      А разве в jpeg не так? Только вместо полинома там косинусы.
                                      • +2
                                        Тут важно понимать, что для изображений, как для звука, не имеет значения математическая точность приближения. Имеет значение только насколько хорошо это воспринимается человеком. Аппроксимация полиномами высокой степени даст ужасный «звон», к сожалению, и несмотря на высокий алгебраический порядок приближения, будет выглядеть плохо. Sinc используют не случайно, он максимально сохраняет полосу частот, но тоже подвержен звону.

                                        Собственно, все методы ресайза изображений, это компромисс между резкостью, «звоном» на резких границах и алиасингом на мелких узорах.
                                        • 0
                                          Собственно, у математиков полиномы степени выше 5 также вызывают отвращение по тем же причинам — портят устойчивость, давая неприятные осцилляции: про это явление даже статья на вики есть.
                                      • 0
                                        Для апсэмплинга есть ещё фрактальные алгоритмы. Ну и специальные алгоритмы для пиксельной графики.
                                        • 0
                                          Спасибо, статья интересная, но всё же слишком «начального» уровня.

                                          Наверное, сравнивать алгоритмы имеет смысл при изменении размера изображения не только в 2 раза, но и на несколько процентов. Во втором случае артефакты вылезут в явном виде и станет очевидной непригодность алгоритмов типа ближайшего соседа. Также интересно было бы сравнить ресайз в 2 раза с помощью Ланцоша с результатом вейвлета 9/7, но я такого сравнения пока нигде не видел.

                                          Представление об алгоритмах на базе свёртки как о медленных, уже не совсем верно. Ресайз на GPU может быть быстрее во много раз по сравнению с CPU. Пример очень быстрого ресайза можно взять тут: CUDA Resize. Интересно посмотреть на время выполнения, но только только для карточек NVIDIA. Ядро Ланцоша там полифазное, т. е. коэффициенты ядра зависят от смещения нового пиксела по отношению к старой сетке.

                                          Вот ещё одно интересное сравнение разных алгоритмов ресайза с картинками.
                                          • 0
                                            Наверное, сравнивать алгоритмы имеет смысл при изменении размера изображения не только в 2 раза, но и на несколько процентов.

                                            Среди примеров и нет изменения размеров в 2 раза. В начале есть все исходные и конечные разрешения.

                                            Представление об алгоритмах на базе свёртки как о медленных, уже не совсем верно. Ресайз на GPU может быть быстрее во много раз

                                            Дак сложность алгоритмов не меняется от того, что появляются более быстрые процессоры или видеокарты. Если можно быстрее сделать свертки, все остальное тоже можно ускорить. Впрочем, я и не говорил, что свертки какие-то медленные. Просто популярные реализации не слишком оптимизированные. Я например использую реализацию, которая ресайзит 5120×2880 в 2048×1152 с фильтром Ланцоша за 150 ms на одном ядре процессора, т.е. делает это со скоростью 98 мегапикселей в секунду, и хорошо параллелится на все ядра сервера. Скорость GraphicMagick — 12 мегапикселей в секунду. А скорость CUDA Resize — 0 мегапикселей в секунду, потому что из трех ноутбуков у меня дома видеокарта от Nvidia только на одном, но и та ниже минимальной требуемой. И на сервере её либо нет, либо есть, но одна, в отличии от ядер процессора.

                                            Ядро Ланцоша там полифазное, т. е. коэффициенты ядра зависят от смещения нового пиксела по отношению к старой сетке.
                                            А бывает по другому? Честно, не встречал.
                                            • 0
                                              У меня картинка 5120×2880 преобразуется в 2048×1152 с фильтром Ланцоша за 17 мс на карточке GeForce GTX 570. Причём половину этого времени уходит на передачу данных через PCI-Express в видеокарту и обратно. А смысл не только в ресайзе — так ведь можно делать всю обработку в GPU.
                                              • 0
                                                Сервер видимо упомянут был не зря, ресайз нужен часто чтобы изображение отдать клиенту по сети а не вывести на экран.
                                                • 0
                                                  Тот подход, о котором я писал, как раз и используется для серверных приложений. На сервер ставят карточки с CUDA не для вывода на экран, а для вычислений. Например, для массового ресайза изображений в формате JPEG. Схема примерно такая: декодирование-ресайз-шарп-кодирование. Одна карточка Tesla K1 на сервере может сделать за сутки 15 миллионов ресайзов для изображений формата JPEG с разрешением 3 мегапиксела.
                                                • 0
                                                  Я написал вам в личку, что вы что-то не отвечаете :)

                                                  Можете прислать вот эту картинку, отресайженую за 17мс на видеокарте Ланцошем: www.apple.com/imac-with-retina/5k.html? Хочу внимательно сравнить. Только присылайте не через хабрасторадж, и в png (без потерь). Можно через этот демо-проект.
                                                • 0
                                                  Помоему, для CUDA есть специальные математические карты расширения, которые вполне можно вставить в сервер и даже не одну при необходимости. Они в любом случае будут выполнять работы подобного рода быстрее чем на процессоре.
                                                  Стоимость, правда, может стать камнем преткновения…
                                                  И да… одна видеокарта это сотня отдельных ядер, так что это не должно стать принципиальной проблемой разделения её ресурсов между приложениями.
                                                  • 0
                                                    Я например использую реализацию, которая ресайзит 5120×2880 в 2048×1152 с фильтром Ланцоша за 150 ms на одном ядре процессора, т.е. делает это со скоростью 98 мегапикселей в секунду, и хорошо параллелится на все ядра сервера.

                                                    Поделитесь?
                                                    • +1
                                                      Поделюсь. Я не зря везде писал «в текущей версии Pillow», потому что в следующей весь ресайз будет на свертах и в 2+ раза быстрее чем в текущей версии или ImageMagick. Остальное ускорение за счет SSE4, поэтому его не так просто влить в основной репозиторй и скорее всего будет в виде форка.
                                                      • 0
                                                        Как и обещал — первая часть больших изменений в Pillow вышла вчера.
                                                  • 0
                                                    А как же 2xSAI? Я помню, в эмуляторах старых игр он творил чудеса и восстанавливал картинку в апскейле до почти хайрезной.
                                                    • +1
                                                      Это алгоритмы апскейла пиксельарта, их очень много и все они специфичные.
                                                    • 0
                                                      FastStone Image Viewer предлагает следующие варианты:

                                                      image

                                                      Чем лучше всего пользоваться? Тем что стоит по дефолту?
                                                      • 0
                                                        да. но вам что так уж сложно сравнить самому?) вариантов то не много.
                                                      • 0
                                                        А есть ли специальные методы ресайза изображений в формате JPEG без декодирования?
                                                        • 0
                                                          Кроп есть lossless и поворот. Остальное не представляю себе как. Для алгоритма доступ к пикселям нужен. Их не получить без декодирования.

                                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                        Самое читаемое