Использование оценкиRigidTransform вместо findHomography

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

http://docs.opencv.org/doc/tutorials/features2d/feature_homography/feature_homography.html#feature-homography

Ниже я использую estimateRigidTransform, чтобы получить преобразование между точками объекта и сцены. objPoints и scePoints представлены vector <Point2f>.

Mat H = estimateRigidTransform(objPoints, scePoints, false);

Следуя методу, использованному в уроке выше, я хочу преобразовать значения углов, используя преобразование H. В учебнике используется perspectiveTransform с матрицей 3x3, возвращаемой findHomography. С жестким преобразованием он возвращает только матрицу 2x3, поэтому этот метод нельзя использовать.

Как бы я преобразовал значения углов, представленных как vector <Point2f> с этой матрицей 2x3. Я просто хочу выполнить те же функции, что и в учебнике, но с меньшими степенями свободы для трансформации. Я просмотрел и другие методы, такие как warpAffine и getPerspectiveTransform, но пока не нашел решения.

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

Я попробовал предложение Дэвида Нилосека. Ниже я добавляю дополнительную строку в матрицу.

Mat row = (Mat_<double>(1,3) << 0, 0, 1);
H.push_back(row);

Однако это дает эту ошибку при использовании перспективыTransform.

OpenCV Error: Assertion failed (mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0)) in create, file /Users/cgray/Downloads/opencv-2.4.6/modules/core/src/matrix.cpp, line 1486
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /Users/cgray/Downloads/opencv-2.4.6/modules/core/src/matrix.cpp:1486: error: (-215) mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) in function create

ChronoTrigger предложил использовать warpAffine. Я вызываю метод warpAffine ниже, размер 1 x 5 соответствует размеру objCorners и sceCorners.

warpAffine(objCorners, sceCorners, H, Size(1,4));

Это дает ошибку ниже, которая предлагает неправильный тип. objCorners и sceCorners — это vector <Point2f>, представляющие 4 угла. Я думал, что warpAffine примет Mat изображений, которые могут объяснить ошибку.

OpenCV Error: Assertion failed ((M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3) in warpAffine, file /Users/cgray/Downloads/opencv-2.4.6/modules/imgproc/src/imgwarp.cpp, line 3280

person Tom smith    schedule 29.04.2014    source источник


Ответы (3)


Я делал это так в прошлом:

cv::Mat R = cv::estimateRigidTransform(p1,p2,false);

    if(R.cols == 0)
    {
        continue;
    }

    cv::Mat H = cv::Mat(3,3,R.type());
    H.at<double>(0,0) = R.at<double>(0,0);
    H.at<double>(0,1) = R.at<double>(0,1);
    H.at<double>(0,2) = R.at<double>(0,2);

    H.at<double>(1,0) = R.at<double>(1,0);
    H.at<double>(1,1) = R.at<double>(1,1);
    H.at<double>(1,2) = R.at<double>(1,2);

    H.at<double>(2,0) = 0.0;
    H.at<double>(2,1) = 0.0;
    H.at<double>(2,2) = 1.0;


    cv::Mat warped;
    cv::warpPerspective(img1,warped,H,img1.size());

что то же самое, что предложил Дэвид Нилосек: добавьте строку 0 0 1 в конце матрицы

этот код искажает ИЗОБРАЖЕНИЯ с помощью жесткого преобразования.

Если вы хотите деформировать/трансформировать точки, вы должны использовать функцию perspectiveTransform с матрицей 3x3 ( http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=perspectivetransform#perspectivetransform )

учебник здесь:

http://docs.opencv.org/doc/tutorials/features2d/feature_homography/feature_homography.html

или вы можете сделать это вручную, перебирая свой вектор и

cv::Point2f result;
result.x = point.x * R.at<double>(0,0) + point.y * R.at<double>(0,1) + R.at<double>(0,2);
result.y = point.x * R.at<double>(1,0) + point.y * R.at<double>(1,1) + R.at<double>(1,2);

надеюсь, это поможет.

примечание: не проверял ручной код, но должен работать. Преобразование PerspectiveTransform здесь не требуется!

изменить: это полный (проверенный) код:

// points
std::vector<cv::Point2f> p1;
p1.push_back(cv::Point2f(0,0));
p1.push_back(cv::Point2f(1,0));
p1.push_back(cv::Point2f(0,1));

// simple translation from p1 for testing:
std::vector<cv::Point2f> p2;
p2.push_back(cv::Point2f(1,1));
p2.push_back(cv::Point2f(2,1));
p2.push_back(cv::Point2f(1,2));

cv::Mat R = cv::estimateRigidTransform(p1,p2,false);

// extend rigid transformation to use perspectiveTransform:
cv::Mat H = cv::Mat(3,3,R.type());
H.at<double>(0,0) = R.at<double>(0,0);
H.at<double>(0,1) = R.at<double>(0,1);
H.at<double>(0,2) = R.at<double>(0,2);

H.at<double>(1,0) = R.at<double>(1,0);
H.at<double>(1,1) = R.at<double>(1,1);
H.at<double>(1,2) = R.at<double>(1,2);

H.at<double>(2,0) = 0.0;
H.at<double>(2,1) = 0.0;
H.at<double>(2,2) = 1.0;

// compute perspectiveTransform on p1
std::vector<cv::Point2f> result;
cv::perspectiveTransform(p1,result,H);

for(unsigned int i=0; i<result.size(); ++i)
    std::cout << result[i] << std::endl;

который дает ожидаемый результат:

[1, 1]
[2, 1]
[1, 2]
person Micka    schedule 30.04.2014
comment
Я все еще получаю то же сообщение об ошибке о типе, который, как я полагаю, означает objCorners и sceCorners. Это не матрицы Mat, это векторы Point2f, так как в данный момент я хочу применить преобразование только к угловым значениям. - person Tom smith; 30.04.2014
comment
а ок, извини. можно просто умножить вручную: result.x = a.x*transf.at<double>(0,0) + a.y*transf.at<double>(0,1) + transf.at<double>(0,3); result.y = ... стандартное матричное умножение. Я считаю, что это менее подвержено ошибкам, чем некоторые преобразования точки в мат. - person Micka; 30.04.2014
comment
@Tomsmith добавил код tested для использования perspectiveTransform в разреженном векторе Point2f с жестким преобразованием - person Micka; 30.04.2014
comment
У меня это работает с ручным кодом, но я также попробую сделанное вами редактирование, спасибо! - person Tom smith; 30.04.2014

Аффинные преобразования (результат cv::estimateRigidTransform) применяются к изображению с помощью функции cv::warpAffine.

person ChronoTrigger    schedule 29.04.2014
comment
Я обновил вопрос с результатами, которые я получил после того, как попробовал ваше предложение. - person Tom smith; 30.04.2014

Форма гомографии 3x3 жесткого преобразования:

 a1 a2 b1
-a2 a3 b2
  0  0  1

Поэтому при использовании estimateRigidTransform вы можете добавить [0 0 1] в качестве третьей строки, если вам нужна матрица 3x3.

person David Nilosek    schedule 29.04.2014
comment
Я пытался реализовать это, я получаю сообщение об ошибке при вызове перспективыTransform, которую я описал в редактировании моего исходного вопроса. - person Tom smith; 30.04.2014
comment
Угадывая по исключению, которое он выбрасывает, матрицы не одного типа. Эта функция представляет собой просто умножение матриц, за которым следует деление, вы можете закодировать ее, если не можете понять, как использовать эту функцию. - person David Nilosek; 30.04.2014
comment
Я не использую матрицы дляspectiveTransform, это два вектора Point2f одного типа. Это те же векторы, которые используются в обучающей ссылке, только с другой матрицей преобразования. - person Tom smith; 30.04.2014