findHomography, getPerspectiveTransform и getAffineTransform

Этот вопрос касается функций OpenCV findHomography, getPerspectiveTransform и getAffineTransform

  1. В чем разница между findHomography и getPerspectiveTransform?. Насколько я понимаю из документации, getPerspectiveTransform вычисляет преобразование, используя 4 соответствия (что является минимумом, необходимым для вычисления гомографического/перспективного преобразования), где findHomography вычисляет преобразование, даже если вы предоставляете более 4 соответствий (предположительно, используя что-то вроде метода наименьших квадратов). метод?). Это правильно? (В этом случае единственная причина, по которой OpenCV все еще продолжает поддерживать getPerspectiveTransform, должна быть устаревшей?)

  2. Моя следующая проблема заключается в том, что я хочу знать, есть ли эквивалент findHomography для вычисления аффинного преобразования? то есть функция, которая использует метод наименьших квадратов или эквивалентный надежный метод для вычисления и аффинного преобразования. Согласно документации getAffineTransform принимает только 3 соответствия (это минимум, необходимый для вычисления аффинного преобразования).

Лучший,


person tetradeca7tope    schedule 28.06.2012    source источник
comment
Возможно, вам подойдет estimateRigidTransform.   -  person cgat    schedule 10.01.2014


Ответы (5)


Вопрос 1. Да, функция findHomography пытается найти наилучшее преобразование между двумя наборами точек. Он использует нечто более умное, чем метод наименьших квадратов, называемый RANSAC, который имеет возможность отклонять выбросы — если хотя бы 50% + 1 из ваших точек данных в порядке, RANSAC сделает все возможное, чтобы найти их и построить надежное преобразование.

У getPerspectiveTransform есть много полезных причин для того, чтобы остаться — это основа для findHomography, и она полезна во многих ситуациях, когда у вас есть только 4 точки, и вы знаете, что они правильные. FindHomography обычно используется с наборами точек, обнаруженных автоматически — вы можете найти многие из них, но с низкой достоверностью. getPerspectiveTransform хорош, когда вы точно знаете 4 угла — например, ручная маркировка или автоматическое обнаружение прямоугольника.

Вопрос №2 Для аффинных преобразований нет эквивалента. Вы можете использовать findHomography, потому что аффинные преобразования являются подмножеством гомографий.

person Sam    schedule 28.06.2012

Я согласен со всем, что написал @vasile. Я просто хочу добавить некоторые наблюдения:

getPerspectiveTransform() и getAffineTransform() предназначены для работы с 4 или 3 точками (соответственно), которые заведомо являются правильными соответствиями. На реальных изображениях, сделанных реальной камерой, вы никогда не сможете получить такие точные соответствия, ни с автоматической, ни с ручной пометкой соответствующих точек.

Всегда есть аутсайдеры. Просто взгляните на простой случай, когда вы хотите подобрать кривую через точки (например, возьмем порождающее уравнение с шумом y1 = f(x) = 3.12x + gauss_noise или y2 = g(x) = 0.1x^2 + 3.1x + gauss_noise): гораздо проще найти хорошую квадратичную функцию для оценки точек в обоих случаях, чем хороший линейный. Квадратичный может быть излишним, но в большинстве случаев таковым не будет (после удаления выбросов), и если вы хотите разместить здесь прямую линию, вам лучше быть полностью уверенным, что это правильная модель, иначе вы получите непригодные для использования результаты.

Тем не менее, если вы полностью уверены в правильности аффинного преобразования, вот вам совет:

  • используйте findHomography, в функции которого встроен RANSAC, чтобы избавиться от выбросов и получить начальную оценку преобразования изображения.
  • выбрать 3 верных совпадения-соответствия (соответствующих найденной гомографии) или перепроецировать 3 точки с 1-го изображения на 2-е (используя гомографию)
  • используйте эти 3 совпадения (которые максимально приближены к правильным) в getAffineTransform()
  • заверните все это в свой собственный findAffine(), если хотите - и вуаля!
person penelope    schedule 28.06.2012
comment
Есть ли способ найти лучшую аффинную матрицу? Я хочу, чтобы последняя строка гомографии была [0, 0, 1]. - person Royi; 30.07.2012
comment
@Drazick Алгоритм, который я написал, делает почти это - он использует findHomography, чтобы избавиться от выбросов, и поэтому вам не нужно кодировать свой собственный RANSAC, а затем вы можете использовать getAffineTransform() для любых 3 точек, чтобы получить близкое -к лучшему аффинно. В качестве альтернативы вы можете написать свой собственный алгоритм RANSAC с помощью getAffineTransform() вместо getPerspectiveTransform() в качестве базовой функции. - person penelope; 31.07.2012
comment
@penleope, я нашел решение, как найти лучшее (с точки зрения l2) аффинное преобразование с использованием SVD аналогично тому, как вы оцениваете лучшую гомографию. - person Royi; 05.08.2012
comment
@Drazick здорово. Опишите это в ответе? - person penelope; 11.09.2012

Что касается Q#2, оценкаRigidTransform является эквивалентом getAffineTransform с передискретизацией. Я не знаю, было ли это в OCV, когда это было впервые опубликовано, но оно доступно в версии 2.4.

person Ben    schedule 17.08.2014

Существует простое решение для нахождения аффинного преобразования для системы переопределенных уравнений.

  1. Обратите внимание, что в общем случае аффинное преобразование находит решение переопределенной системы линейных уравнений Ax=B с использованием псевдообратного или аналогичного метода, поэтому

x = (A At )-1 At B

Более того, это обрабатывается в основных функциях openCV простым вызовом для решения (A, B, X).

  1. Ознакомьтесь с кодом аффинного преобразования в opencv/modules/imgproc/src/imgwarp.cpp: на самом деле он делает только две вещи:

    а. переставляет входы для создания системы Ax=B;

    б. затем вызывает решение (A, B, X);

ПРИМЕЧАНИЕ: игнорируйте комментарии к функциям в коде openCV — они сбивают с толку и не отражают фактического порядка элементов в матрицах. Если вы решаете [u, v]’= Affine * [x, y, 1], перестановка будет следующей:

         x1 y1 1 0  0  1
         0  0  0 x1 y1 1
         x2 y2 1 0  0  1
    A =  0  0  0 x2 y2 1
         x3 y3 1 0  0  1
         0  0  0 x3 y3 1

    X = [Affine11, Affine12, Affine13, Affine21, Affine22, Affine23]’

         u1 v1
    B =  u2 v2
         u3 v3 

Все, что вам нужно сделать, это добавить больше очков. Чтобы Solve(A, B, X) работал в переопределенной системе, добавьте параметр DECOMP_SVD. Чтобы просмотреть слайды PowerPoint по теме, используйте эту ссылку< /а>. Если вы хотите узнать больше о псевдоинверсии в контексте компьютерного зрения, лучший источник: ComputerVision, см. главу 15 и приложение C.

Если вы все еще не знаете, как добавить больше очков, посмотрите мой код ниже:

// extension for n points;
cv::Mat getAffineTransformOverdetermined( const Point2f src[], const Point2f dst[], int n )
{
    Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data); // output
    double* a = (double*)malloc(12*n*sizeof(double));
    double* b = (double*)malloc(2*n*sizeof(double));
    Mat A(2*n, 6, CV_64F, a), B(2*n, 1, CV_64F, b); // input

    for( int i = 0; i < n; i++ )
    {
        int j = i*12;   // 2 equations (in x, y) with 6 members: skip 12 elements
        int k = i*12+6; // second equation: skip extra 6 elements
        a[j] = a[k+3] = src[i].x;
        a[j+1] = a[k+4] = src[i].y;
        a[j+2] = a[k+5] = 1;
        a[j+3] = a[j+4] = a[j+5] = 0;
        a[k] = a[k+1] = a[k+2] = 0;
        b[i*2] = dst[i].x;
        b[i*2+1] = dst[i].y;
    }

    solve( A, B, X, DECOMP_SVD );
    delete a;
    delete b;
    return M;
}

// call original transform
vector<Point2f> src(3);
vector<Point2f> dst(3);
src[0] = Point2f(0.0, 0.0);src[1] = Point2f(1.0, 0.0);src[2] = Point2f(0.0, 1.0);
dst[0] = Point2f(0.0, 0.0);dst[1] = Point2f(1.0, 0.0);dst[2] = Point2f(0.0, 1.0);
Mat M = getAffineTransform(Mat(src), Mat(dst));
cout<<M<<endl;
// call new transform
src.resize(4); src[3] = Point2f(22, 2);
dst.resize(4); dst[3] = Point2f(22, 2);
Mat M2 = getAffineTransformOverdetermined(src.data(), dst.data(), src.size());
cout<<M2<<endl;
person Vlad    schedule 16.01.2015

getAffineTransform: аффинное преобразование представляет собой комбинацию переноса, масштабирования, сдвига и вращения https://www.mathworks.com/discovery/affine-transformation.html https://www.tutorialspoint.com/computer_graphics/2d_transformation.htm

getPerspectiveTransform: преобразование перспективы — это отображение проекта введите здесь описание изображения

person silva    schedule 15.05.2019