Понимание перспективных искажений проекции ImageMagick

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

convert \
  -verbose mw2.png \
  -alpha set \
  -virtual-pixel transparent \
  -distort Perspective-Projection '0,0 0,0   0,0 0,0' \
   box.png

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

Здесь вы найдете простое изображение того, чего я пытаюсь достичь (с помощью инструментов CLI):

input example image

Обновление:

   convert \
        -virtual-pixel transparent \
        -size 159x92 \
        -verbose \
        cd_empty.png \
        \(mw2.png -distort Perspective '7,40 4,30   4,124 4,123   85,122 100,123   85,2 100,30'\) \
         -geometry +3+20 \
        -composite cover-after.png

дает мне в качестве вывода:

cd_empty.png PNG 92x159 92x159+0+0 8-bit sRGB 16.1KB 0.000u 0:00.000
convert: unable to open image '(mw2.png': No such file or directory @ error/blob.c/OpenBlob/2641.
convert: unable to open file '(mw2.png' @ error/png.c/ReadPNGImage/3741.
convert: invalid argument for option Perspective : 'require at least 4 CPs' @ error/distort.c/GenerateCoefficients/807.
convert: no images defined 'cover-after.png' @ error/convert.c/ConvertImageCommand/3044.

Исправление Курта Пфайфла:

У команды есть синтаксическая ошибка, потому что она не окружает разделители \( и \) (как минимум одним) пробелом с каждой стороны, как того требует ImageMagick!

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

   convert                         \
        -virtual-pixel transparent \
        -size 159x92               \
        -verbose                   \
         cd_empty.png              \
           \(                      \
           mw2.png -distort Perspective '7,40 4,30  4,124 4,123  85,122 100,123  85,2  100,30' \
           \)                      \
        -geometry +3+20            \
        -composite                 \
         cover-after.png

Ответ 1

Вы видели это очень подробное объяснение алгоритмов искажения ImageMagick? Он также содержит немало иллюстраций.

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

Конечно, пример, который вы указали с параметром 0,0 0,0 0,0 0,0, не делает того, что вы хотите.

Многие из методов искажения, доступных в ImageMagick, работают следующим образом:

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

Пример:

S x1, S y1 D x1, D y1  S x2, S y2 D x2, D y2  S x3, S y3 D x3, D y3  ...  S xn, S yn D xn, D yn  

x используется для представления координаты X.
y используется для представления координаты Y.
1, 2, 3,... n используется для представления первого, второго, третьего,... n-го пикселя.
S используется здесь для исходного пикселя.
D используется здесь для целевого пикселя.

Сначала: метод -distort perspective

Метод искажения perspective гарантирует, что прямые линии в исходном изображении останутся прямыми линиями в целевом изображении. Другие методы, такие как barrel или bilinearforward, не имеют: они будут искажать прямые линии на кривые.

Для -distort perspective требуется набор из не менее 4 предварительно вычисленных пар координат пикселей (где последний может быть равен нулю). Более 4 пар пиксельных координат обеспечивают более точные искажения. Итак, если вы использовали, например:

-distort perspective '1,2  3,4     5,6  7,8     9,10  11,12     13,14  15,16'

(для удобства чтения с использованием более {необязательных} пробелов между парами отображения, чем требуется) будет означать:

  • Из исходного изображения возьмите пиксель в координате (1,2) и нарисуйте его по координате (3,4) в целевом изображении.
  • Из исходного изображения возьмите пиксель в координате (5,6) и нарисуйте его по координате (7,8) на целевом изображении.
  • Из исходного изображения возьмите пиксель в координате (9,10) и нарисуйте его по координате (11,12) в целевом изображении.
  • Из исходного изображения возьмите пиксель в координате (13,14) и нарисуйте его по координате (15,16) в целевом изображении.

Возможно, вы видели фотоизображения, где вертикальные линии (например, углы строительных стен) не выглядят вертикально (из-за некоторого наклона камеры при съемке). Метод -distort perspective может исправить это.

Он может даже достичь таких вещей, как "выпрямление" или "исправление" одного лица здания, которое появляется в "правильной" перспективе исходной фотографии:

original image==> distorted image

Контрольные точки, используемые для этого искажения, обозначаются углами красного (элементы управления источником) и синими прямоугольниками (элементами управления назначения), нарисованными над исходным изображением:

source control points: corners of 'red'==> destination control points: corners of 'blue'

Это конкретное искажение, используемое

-distort perspective '7,40 4,30   4,124 4,123   85,122 100,123   85,2 100,30'

Заполните команду для вашего удовольствия от копирования:

convert                                                                      \
  -verbose                                                                   \
   http://i.stack.imgur.com/SN7sm.jpg                                        \
  -matte                                                                     \
  -virtual-pixel transparent                                                 \
  -distort perspective '7,40 4,30  4,124 4,123  85,122 100,123  85,2 100,30' \
   output.png

Второе: метод -distort perspective-projection

Метод -distort perspective-projection получен из более понятного метода perspective. Он достигает точно такого же результата искажения, что и -distort perspective, но не использует (по крайней мере) 4 пары значений координат (не менее 16 целых чисел) в качестве параметра, но 8 коэффициентов с плавающей запятой.

Он использует...

  • Набор из ровно 8 предварительно вычисленных коэффициентов;
  • Каждый из этих коэффициентов является значением с плавающей запятой (в отличие от -distort perspective, где для значений допускаются только целые числа);
  • Эти 8 значений представляют собой матрицу вида

    s x   r y   t x
      r x   s y   t y
      р <суб> хсуб>    р <суб> усуб>

    который используется для вычисления целевых пикселей из исходных пикселей в соответствии с этой формулой:

    X-of-destination = (sx*xs + ry+ys +tx) / (px*xs + py*ys +1)
    Y-of-destination = (rx*xs + sy+ys +ty) / (px*xs + py*ys +1)
    
    (TO BE DONE -- 
        I've no time right now to find out how to
        properly format + put formulas into the SO editor)
    

Чтобы избежать (более сложного) вычисления 8 требуемых коэффициентов для повторно используемого метода -distort perspective-projection , вы можете...

  • ПЕРВЫЙ (проще) вычислить координаты для -distort perspective ,
  • SECOND, запустите этот -distort perspective с добавленным параметром -verbose ,
  • ПОСЛЕДНИЕ, прочитайте 8 коэффициентов с выхода, напечатанного на stderr .

Приведенный выше пример команды (выше приведенный) выплевывает эту информацию:

Perspective Projection:
  -distort PerspectiveProjection \
    '1.945622, 0.071451, -12.187838, 0.799032, 
     1.276214, -24.470275, 0.006258, 0.000715'

Ответ 2

Благодаря этой странице и предыдущему ответу я получил этот чистый, понятный код... надеюсь, вы найдете его полезным :)))

$points = array(

                0,0, # Source Top Left
                0,0, # Destination Top Left

                0,490, # Source Bottom Left 
                2.2,512, # Destination Bottom Left 

                490,838, # Source Bottom Right 
                490,768, # Destination Bottom Right 

                838,0, # Source Top Right 
                838,50 # Destination Top Right 

                );

$imagick->distortImage(Imagick::DISTORTION_PERSPECTIVE, $points, false);

Пожалуйста, имейте в виду, что каждый набор координат разделен на два частей. Первая ось X, а вторая ось Y.. поэтому, когда мы говорим 838,0 в пункте назначения справа вверху мы имеем в виду ось X пункта назначения справа вверху равно 838, а ось Y равна нулю (0).

Буду рад ответить на ваш вопрос :)