以下链接中的示例使用findHomography
来获取两组点之间的转换。我想限制转换中使用的自由度,因此希望用findHomography
替换estimateRigidTransform
。
下面我使用estimateRigidTransform
来获取对象和场景点之间的转换。 objPoints
和scePoints
由vector <Point2f>
表示。
Mat H = estimateRigidTransform(objPoints, scePoints, false);
按照上面教程中使用的方法,我想使用转换H
转换角点值。本教程使用perspectiveTransform
和findHomography
返回的3x3矩阵。使用刚性变换时,它仅返回2x3矩阵,因此无法使用此方法。
如何使用此2x3矩阵转换角点的值,表示为vector <Point2f>
。我只是想要执行与教程相同的功能,但转换的自由度较低。我也查看了其他方法,例如warpAffine
和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的大小是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
答案 0 :(得分: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行
此代码以严格的转换扭曲了IMAGES。
我想要变形/变换点,你必须使用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]
答案 1 :(得分:3)
仿射变换(cv::estimateRigidTransform
的结果)应用于具有函数cv::warpAffine
的图像。
答案 2 :(得分:2)
刚性变换的3x3单应形式是:
a1 a2 b1
-a2 a3 b2
0 0 1
因此,当使用estimateRigidTransform
时,您可以添加[0 0 1]作为第三行,如果您想要3x3矩阵。