6

下面链接中的示例findHomography用于获取两组点之间的转换。我想限制转换中使用的自由度,所以想findHomographyestimateRigidTransform.

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);

按照上面教程中使用的方法,我想使用 transformation 转换角值H。本教程使用perspectiveTransform返回的 3x3 矩阵findHomography。使用刚性变换,它只返回一个 2x3 矩阵,因此不能使用此方法。

我将如何转换角的值,vector <Point2f>用这个 2x3 矩阵表示。我只是希望执行与教程相同的功能,但转换的自由度较低。我也看过其他方法,例如warpAffineand getPerspectiveTransform,但到目前为止还没有找到解决方案。

编辑:

我已经尝试过 David Nilosek 的建议。下面我将额外的行添加到矩阵中。

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

但是,这在使用 perspectiveTransform 时会出现此错误。

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 的大小是objCornersand的大小sceCorners

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

这给出了下面的错误,这表明错误的类型。objCorners并代表 4 个角sceCornersvector <Point2f>我认为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
4

3 回答 3

5

仿射变换( 的结果cv::estimateRigidTransform)通过函数 应用于图像cv::warpAffine

于 2014-04-29T19:06:21.927 回答
5

我过去是这样做的:

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());

这与 David Nilosek 建议的相同:在矩阵末尾添加 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]
于 2014-04-30T07:01:40.120 回答
4

刚性变换的 3x3 单应形式是:

 a1 a2 b1
-a2 a3 b2
  0  0  1

因此estimateRigidTransform,如果您想要 3x3 矩阵,则在使用时可以添加 [0 0 1] 作为第三行。

于 2014-04-29T19:07:21.983 回答