Измените изображение от 3-й перспективы до 2-го

Мне нужна обратная перспектива, преобразовывают написанный в Pascal/Delphi/Lazarus. Посмотрите следующее изображение:

image process

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

function redraw_3d_to_2d(sourcebitmap:tbitmap, sourceaspect:extended, point_a, point_b, point_c, point_d:tpoint, megapixelcount:integer):tbitmap;
var
   destinationbitmap:tbitmap;
   x,y,sx,sy:integer;
begin
  destinationbitmap:=tbitmap.create;
  destinationbitmap.width=megapixelcount*sourceaspect*???;//I dont how to calculate this
  destinationbitmap.height=megapixelcount*sourceaspect*???;//I dont how to calculate this
  for x:=0 to destinationbitmap.width-1 do
    for y:=0 to destinationbitmap.height-1 do
    begin
        sx:=??;
        sy:=??;
        destinationbitmap.canvas.pixels[x,y]=sourcebitmap.canvas.pixels[sx,sy];
    end;
  result:=destinationbitmap;
end;

Мне нужна реальная формула... Таким образом, решение OpenGL не было бы идеально...

17
nl ja de

2 ответы

Note: There is a version of this with proper math typesetting on the Math SE.

Вычисление проективного преобразования

Перспектива - особый случай a проективное преобразование, который в свою очередь определяется на четыре пункта.

Step 1: Starting with the 4 positions in the source image, named (x1,y1) through (x4,y4), you solve the following system of linear equations:

[x1 x2 x3] [λ]   [x4]
[y1 y2 y3]∙[μ] = [y4]
[ 1  1  1] [τ]   [ 1]

Форма colums однородные координаты: одно измерение больше, созданный, добавляя 1 как последний вход. В последующих шагах сеть магазинов этих векторов будет использоваться, чтобы обозначить те же самые пункты. Посмотрите последний шаг для примера того, как повернуться спиной в двумерные координаты.

Step 2: Scale the columns by the coefficients you just computed:

    [λ∙x1 μ∙x2 τ∙x3]
A = [λ∙y1 μ∙y2 τ∙y3]
    [λ    μ    τ   ]

Эта матрица нанесет на карту (1,0,0) к кратному числу (x1, y1,1) , (0,1,0) к кратному числу (x2, y2,1) , (0,0,1) к кратному числу (x3, y3,1) и (1,1,1) , чтобы (x4, y4,1) . Таким образом, это нанесет на карту эти четыре специальных вектора (назвал базисные векторы в последующих объяснениях) к указанным позициям по изображению.

Step 3: Repeat steps 1 and 2 for the corresponding positions in the destination image, in order to obtain a second matrix called B.

Это - карта от базисных векторов до положений назначения.

Step 4: Invert B to obtain B⁻¹.

B maps from basis vectors to the destination positions, so the inverse matrix maps in the reverse direction.

Step 5: Compute the combined Matrix C = A∙B⁻¹.

B⁻¹ maps from destination positions to basis vectors, while A maps from there to source positions. So the combination maps destination positions to source positions.

Step 6: For every pixel (x,y) of the destination image, compute the product

[x']     [x]
[y'] = C∙[y]
[z']     [1]

Это однородные координаты вашего преобразованного пункта.

Step 7: Compute the position in the source image like this:

sx = x'/z'
sy = y'/z'

Это называют dehomogenization координационного вектора.

All this math would be so much easier to read and write if SO were to support MathJax

Выбор размера изображения

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

pixelcount = 1000000.*megapixelcount;
width  = round(sqrt(pixelcount*sourceaspect));
height = round(sqrt(pixelcount/sourceaspect));
21
добавлено
@Thomas, я don' t следуют за вашим беспокойством. Я знаю, что мой подход не обращается ни с какими реальными отклонениями, но, пока идеальная модель камеры с точечной диафрагмой применяется, угол не будет иметь значения: перспектива будет проективным преобразованием, неважно, угол (если ваша оптическая ось не найдется в самолете листка бумаги). И вышеупомянутое вычисление работает на общее prohective преобразование. Таким образом, никакая глубина не требуется. Отметьте это I' m выполнение вычислений в реальном проективном самолете, не в реальном аффинном 3-м месте. Это могли быть вы, неправильно понял этот аспект?
добавлено автор MvG, источник
@Thomas, I' m применение проективного преобразования, не только вращения. Это нанесет на карту изображение прямоугольника, взятого в угле падения к прямоугольнику, заполняющему конечное изображение. Нет никакого требования что фотография быть взятым от непосредственно выше рисунка.
добавлено автор MvG, источник
@Thomas, если megapixelcount восстановленного изображения намного меньше, чем та из входной фотографии, есть шанс, но я соглашаюсь, что в целом точность восстановленного изображения пострадает. Некоторым формам совмещения имен могли бы противостоять методы, такие как супервыборка, но это won' t восстанавливают потерянную информацию в процессе, просто делают их отсутствие менее очевидным.
добавлено автор MvG, источник
@LeonardoHerrera, таким образом, это - видео, в конце концов!:-) я не вижу оснований, почему это не должно работать, за исключением того, что вручную обнаружение углов займет много времени, и опознавание автоматически их требует еще некоторой работы для признания изображения, обнаружения края в частности. Более вертикальное, которое ваша оптическая ось, и чем выше resoltution protograph, тем лучше результаты будут.
добавлено автор MvG, источник
Я наконец написал версия этого ответа на Математике Stackexchange, у которого есть лучшие математические возможности форматирования из-за его использования MathJax.
добавлено автор MvG, источник
Это только действительно, если фотография была сделана в нормальном уровне. Если это было взято под углом, вам будет нужна глубина углов также - они могут, однако, быть выведены из угла.
добавлено автор Thomas, источник
Предположим, что фотография была сделана в угле падения рисунка - можно применить вращение, как обычно, чтобы получить правильно выровненную фотографию, но все еще в угле падения, который не является желаемым результатом (OP хочет "прямо выше бумаги"). OP не упоминал, делались ли введенные фотографии всегда от непосредственно выше рисунка.
добавлено автор Thomas, источник
Ах, я вижу. У вас, однако, не будет достаточной информации, чтобы точно восстановить заключительное изображение, так как вы будете upscaling "раздавленные" пиксели к пикселям с желаемым форматным соотношением, но это неизбежно.
добавлено автор Thomas, источник
Я вижу, что все вы знают намного больше о математике, чем я.... Однако мне первоначально понравится иметь ответ на том, возможно ли это проективное преобразование технически сделать? Позвольте мне обрисовывать в общих чертах, куда исходное изображение прибывает из... У пользователя есть связка исходных изображений, которые оттянуты небольшое изменение в каждом - перспектива моего проекта должна создать инструмент для развития остановите движения. Если я мог некоторые, как автоматическое опознавание углы бумаги это будет еще лучше...
добавлено автор Kasper DK, источник
В этом случае алгоритм должен рассмотреть только единственное исходное изображение за один раз. Есть ли человек, который готов преобразовать решение MvG исходного кода Паскаля? Я был бы чрезвычайно благодарен за это...
добавлено автор Kasper DK, источник
@Thomas - конечно, пиксели будут интерполированы, и восстановленное изображение будет более или менее изменено. Я don' t видят, как еще это могло быть сделано - после того, как вся необходимая информация не присутствует в 2-й фотографии (CSI и все подобные сериалы, несмотря на это.) Есть некоторые впечатляющие вещи, сделанные с видео в этом отношении, но увы, это не видео.
добавлено автор Leonardo Herrera, источник
@KasperDK - ай, это - полная новая область.
добавлено автор Leonardo Herrera, источник

Использовать Graphics32, определенно TProjectiveTransformation (чтобы использовать с Преобразовать метод). Не забывайте оставлять некоторый прозрачный край в своем исходном изображении, таким образом, вы не получаете зубчатые края.

4
добавлено
+1 спасибо за указатель
добавлено автор Jan Doggen, источник
Infernal Math
Infernal Math
389 участник(ов)

http://www.zepta.ru/index.php?title=Заглавная_страница Приглашение в чат: https://t.me/matheden

comput.math
comput.math
289 участник(ов)

Прикладная математика и численные методы. Без оффтопа, рекламы, флуда. Вышмат: @higher_math Физика: @physpub Новичкам: @starter_math @JuliaLanguage @rlang_ru Книги брать здесь: libgen.io И по хештегу #book

Delphi & Lazarus
Delphi & Lazarus
274 участник(ов)

Чат про Delphi и Lazarus

higher.math
higher.math
234 участник(ов)

Higher mathematics / высшая математика Подборка книжек: https://ru.stackoverflow.com/a/683632/1084 Вычмат: @comput_math Физика: @physpub LaTeX: @pro_latex

Starter Math
Starter Math
79 участник(ов)

Для тех, кто боится спросить в @higher_math Вычмат: @comput_math Физика: @physpub