Вычисление матрицы, которая преобразует четырехугольник в другой четырехугольник в 2D

На рисунке ниже цель состоит в том, чтобы вычислить матрицу гомографии H, которая преобразует точки a1 a2 a3 a4 в их аналоги b1 b2 b3 b4. Это:

[b1 b2 b3 b4] = H * [a1 a2 a3 a4]

Какой способ вы бы посоветовали наилучшим образом рассчитать H (3x3). a1 ... b4 - это точки в 2D, которые представлены в однородных системах координат (то есть [a1_x a1_y 1] ', ...). РЕДАКТИРОВАТЬ: для этих типов проблем мы используем SVD, поэтому я хотел бы увидеть, как это можно просто сделать в Matlab.

ИЗМЕНИТЬ:

Вот как я изначально пытался решить эту проблему с помощью svd (H = Q / P) в Maltlab. Cosider следующий код для данного примера

px=[0 1 1 0];  % a square
py=[1 1 0 0];

qx=[18 18 80 80];    % a random quadrangle
qy=[-20 20 60 -60];
if (DEBUG)
  fill(px,py,'r');
  fill(qx,qy,'r');
end

Q=[qx;qy;ones(size(qx))];
P=[px;py;ones(size(px))];
H=Q/P;
H*P-Q
answer:
   -0.0000         0         0         0         0
  -20.0000   20.0000  -20.0000   20.0000    0.0000
   -0.0000         0         0         0   -0.0000

Я ожидаю, что ответ будет нулевой матрицей, но это не так! ... и поэтому я задал этот вопрос в StackOverflow. Теперь мы все знаем, что это проективное преобразование, не очевидно евклидово. Однако полезно знать, возможно ли в целом вычисление такой матрицы с использованием только 4 точек.

вычисление матрицы


person C graphics    schedule 30.07.2012    source источник
comment
Это не моя область, но я считаю, что лучшее, что вы можете сделать, - это решение методом наименьших квадратов, поскольку в вашем уравнении больше ограничений, чем свободных параметров.   -  person Isaac    schedule 30.07.2012
comment
Совершенно верно, SVD - это решение, однако мне что-то не хватает в моем коде.   -  person C graphics    schedule 30.07.2012
comment
Что вы сейчас пытаетесь? По аналогии с линейным методом наименьших квадратов, мое первое предположение было бы H = B * A' * inv( A * A' )   -  person Isaac    schedule 30.07.2012
comment
в Matlab просто H = B / A, где B = [b1 b2 b3 b4], A = [a1 a2 a3 a4]   -  person C graphics    schedule 30.07.2012
comment
И вы думаете, что должна существовать матрица, которая работает лучше? Я не уверен, о чем вы спрашиваете ...   -  person Isaac    schedule 30.07.2012
comment
Перекрестная ссылка: см. этот пост на Math SE для математического обсуждения того, как найти проективное преобразование без специальных инструментов. из матлаб.   -  person MvG    schedule 28.08.2015


Ответы (5)


Используя опубликованные вами данные:

P = [px(:) py(:)];
Q = [qx(:) qy(:)];

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

H = Q/P;

применить преобразование:

Q2 = H*P;

Сравните результаты:

err = Q2-Q

вывод:

err =
   7.1054e-15   7.1054e-15
  -3.5527e-15  -3.5527e-15
  -1.4211e-14  -2.1316e-14
   1.4211e-14   1.4211e-14

который является нулем во всех смыслах и целях ..


РЕДАКТИРОВАТЬ:

Итак, как вы указали в комментариях, вышеуказанный метод не будет вычислять матрицу гомографии 3x3. Он просто решает систему уравнений с таким количеством уравнений, сколько указано точек:

H * A = B   -->   H = B*inv(A)   -->   H = B/A (mrdivide)

В противном случае MATLAB имеет функцию CP2TFORM в наборе инструментов обработки изображений. Вот пример, примененный к показанному изображению:

%# read illustration image
img = imread('http://i.stack.imgur.com/ZvaZK.png');
img = imcomplement(im2bw(img));

%# split into two equal-sized images
imgs{1} = img(:,fix(1:end/2));
imgs{2} = img(:,fix(end/2:end-1));

%# extract the four corner points A and B from both images
C = cell(1,2);
for i=1:2
    %# some processing
    I = imfill(imgs{i}, 'holes');
    I = bwareaopen(imclearborder(I),200);
    I = imfilter(im2double(I), fspecial('gaussian'));

    %# find 4 corners
    C{i} = corner(I, 4);

    %# sort corners in a consistent way (counter-clockwise)
    idx = convhull(C{i}(:,1), C{i}(:,2));
    C{i} = C{i}(idx(1:end-1),:);
end

%# show the two images with the detected corners
figure
for i=1:2
    subplot(1,2,i), imshow(imgs{i})
    line(C{i}(:,1), C{i}(:,2), 'Color','r', 'Marker','*', 'LineStyle','none')
    text(C{i}(:,1), C{i}(:,2), num2str((1:4)'), 'Color','r', ...
        'FontSize',18, 'Horiz','left', 'Vert','bottom')
end

Теперь, когда углы обнаружены, мы можем получить пространственное преобразование:

%# two sets of points
[A,B] = deal(C{:});

%# infer projective transformation using CP2TFORM
T = cp2tform(A, B, 'projective');

%# 3x3 Homography matrix
H = T.tdata.T;
Hinv = T.tdata.Tinv;

%# align points in A into B
X = tformfwd(T, A(:,1), A(:,2));

%# show result of transformation
line(X([1:end 1],1), X([1:end 1],2), 'Color','g', 'LineWidth',2)

Результат:

>> H = T.tdata.T
H =
      0.74311    -0.055998    0.0062438
      0.44989      -1.0567   -0.0035331
      -293.31       62.704      -1.1742

>> Hinv = T.tdata.Tinv
Hinv =
       -1.924     -0.42859   -0.0089411
      -2.0585      -1.2615   -0.0071501
       370.68       39.695            1

скриншот

Мы можем подтвердить расчет сами:

%# points must be in Homogenous coordinates (x,y,w)
>> Z = [A ones(size(A,1),1)] * H;
>> Z = bsxfun(@rdivide, Z, Z(:,end))   %# divide by w
Z =
          152           57            1
          219          191            1
           62          240            1
           92          109            1

который отображается в точки в B:

%# maximum error
>> max(max( abs(Z(:,1:2)-B) ))
ans =
   8.5265e-14
person Amro    schedule 30.07.2012
comment
Это не то, что я искал. В вашем решении H равно 4x4, что означает, что если мы добавим n точек, H станет nxn. Мы ищем матрицу гомографии 3x3. - но все равно спасибо - person C graphics; 01.08.2012
comment
@Cgraphics: это правда, спасибо, что указали на это. Возможно, поскольку для решения системы достаточно всего 4 баллов, это не должно быть проблемой ... В любом случае, у меня есть пример с использованием CP2TFORM, как предлагается chaohuang. Он правильно выведет матрицу гомографии 3x3 проективного преобразования как минимум из 4 контрольных точек. Скоро выложу, может кому пригодится - person Amro; 01.08.2012

Вы можете попробовать функцию cp2tform, которая определяет пространственное преобразование из пар контрольных точек. Поскольку в вашем случае параллельность не сохраняется, вы должны установить transformtype как «проективный». Дополнительная информация находится здесь

person chaohuang    schedule 30.07.2012

Для этой цели можно использовать алгоритм DLT. Для этого доступны подпрограммы MATLAB на домашней странице Питера Ковеси.

person jmbr    schedule 30.07.2012

Объедините все координаты в векторы столбца. В случае 2D это: ax, ay, bx, by;

Определять:

A = [ax, ay];
B = [bx, by];
input = [ones(size(A, 1), 1), A];

Рассчитать матрицу преобразования:

H = input \ B;

Если вам нужно применить его к новым наблюдениям A_new:

input_new = [ones(size(A_new, 1), 1), A_new];
B_new = input_new * H;

Изменить: вы также можете вычислить H по: H = inv(input' * input) * input' * B;, но \, если это безопасно.

person Serg    schedule 30.07.2012
comment
@Amro: Извини, что захватил эту ветку, но я хотел узнать мнение Амро. Если вы посмотрите на мой ответ, я сослался на свое решение на предыдущий вопрос. Я считаю, что это не технически точная копия, но, возможно, разница не имеет значения в SO. Что вы думаете? - person Jacob; 31.07.2012
comment
@ Джейкоб: безусловно, это отличный ответ. Возможно, вам стоит разместить здесь код, адаптированный к этой проблеме. (кстати, похоже, есть мертвая ссылка, указывающая на некоторые слайды). ИМО, эти вопросы похожи, хотя и не являются точными дубликатами. - person Amro; 31.07.2012

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

person Jacob    schedule 30.07.2012
comment
Спасибо, Джейкоб, ты прав, это точно такой же вопрос. На самом деле я искал гомографию. - person C graphics; 31.07.2012