Гораздо лучший способ сделать это - обратное отображение .
По сути, вы хотите "деформировать" изображение, верно? Это означает, что каждый пиксель в исходном изображении переходит в предопределенную точку - предопределением является матрица преобразования, которая говорит вам, как вращать, масштабировать, переводить, сдвигать и т. Д. Изображение, которое по существу принимает некоторую координату (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)
, а затем выполнить билинейную интерполяцию на исходном изображении, чтобы выяснить соответствующее значение!
Матрица преобразования
Хорошо, как вы определяете матрицу преобразования для аффинного преобразования? Этот веб-сайт рассказывает, как это сделать, составляя различные матрицы преобразования для вращения, сдвига и т. Д.
Трансформация:
Compositing:
Окончательная матрица может быть достигнута путем компоновки каждой матрицы в указанном порядке, и вы инвертируете ее, чтобы получить обратное отображение - используйте эту функцию для вычисления положений пикселей в исходном изображении и интерполяции.