Скос изображения с помощью Перспективы Преобразовывает

Я пытаюсь выполнить скос на изображении, как один показанный здесь


(источник: microsoft.com)
.

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

10
задан Glorfindel 30 June 2019 в 19:04
поделиться

3 ответа

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

По сути, вы хотите «исказить» изображение, не так ли? Это означает, что каждый пиксель в исходном изображении переходит в предопределенную точку - предопределение представляет собой матрицу преобразования, которая сообщает вам, как вращать, масштабировать, сдвигать, сдвигать и т. Д. Изображение, которое, по сути, принимает некоторую координату (x, y ) на вашем изображении и говорит: «Хорошо, новая позиция для этого пикселя - (f (x), g (y)) .

По сути, это то, что делает« деформация ».

Теперь подумайте о масштабировании изображения ... скажем, в десять раз больше. Это означает, что пиксель в (1,1) становится пикселем в (10,10 ) - а затем следующий пиксель, (1,2) становится пикселем (10,20) в новом изображении. Но если вы продолжите делать это, вы не имеют значений для пикселя, (13,13) , потому что, (1.3,1.3) не определен в исходном изображении, и у вас будет куча дыр в новом изображении - вам придется интерполировать это значение, используя четыре пикселя вокруг него в новом изображении, то есть ( 10,10), (10,20), (20,10), (200,2) - это называется билинейной интерполяцией .

Но вот еще одна проблема. Предположим, ваше преобразование не было простым масштабированием и было аффинным (как в опубликованном вами примере изображения) - тогда (1,1) станет чем-то вроде ( 2.34,4.21) , а затем вам нужно будет округлить их в выходном изображении до (2,4) и , затем вам нужно будет выполнить билинейную интерполяцию на новое изображение для заполнения дыр или более сложная интерполяция - беспорядок, не так ли?

Теперь нет способа выйти из интерполяции, но мы можем обойтись без билинейной интерполяции, всего лишь один раз . Как? Простое, обратное отображение.

Вместо того, чтобы смотреть на него как на исходное изображение, идущее к новому изображению, подумайте, откуда в исходном изображении берутся данные для нового изображения! Итак, (1,1) в новом изображении будет получено из некоторого обратного отображения в исходном изображении, скажем, (3.4, 2.1) , а затем выполнить билинейную интерполяцию на исходном изображении. выяснить соответствующее значение!

Матрица преобразования

Итак, как вы определяете матрицу преобразования для аффинного преобразования? На этом веб-сайте рассказывается, как это сделать, составляя различные матрицы преобразования для вращения, сдвига и т. Д.

Преобразования:

alt text

Составление:

alt text

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

53
ответ дан 3 December 2019 в 13:17
поделиться

Как прокомментировал KennyTM, вам просто нужно аффинное преобразование, которое является линейным отображением, полученным путем умножения каждого пикселя на матрицу M и добавления результата к вектору перевода V. Это простая математика

end_pixel_position = M*start_pixel_position + V

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

Например, если вы хотите повернуть изображение, матрица поворота определяется следующим образом:

    | cos(a) -sin(a) |
M = |                |
    | sin(a)  cos(a) |

где a - угол, на который вы хотите повернуть изображение.

При масштабировании используется матрица вида:

    | s1   0 |
M = |        |
    | 0   s2 |

где s1 и s2 - коэффициенты масштабирования по обеим осям.

Для перевода у вас есть только вектор V:

    | t1 |
V = |    |
    | t2 |

который добавляет t1 и t2 к координатам пикселей.

Затем вы объединяете матрицы в одно преобразование, например, если у вас есть масштабирование, поворот и перевод, то в итоге получится что-то вроде:

| x2 |             | x1 |
|    | = M1 * M2 * |    | + T
| y2 |             | y1 |

где:

  • x1 и y1 - координаты пикселя до применения преобразования,
  • x2 и y2 - пиксели после преобразования,
  • M1 и M2 - матрицы, используемые для масштабирования и вращения (ПОМНИТЕ: состав матриц не коммутативен! Обычно M1 * M2 * Vect != M2 * M1 * Vect),
  • T - вектор перевода, используемый для перевода каждого пикселя.
2
ответ дан 3 December 2019 в 13:17
поделиться

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

3
ответ дан 3 December 2019 в 13:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: