opencv改变y坐标_关于opencv:从图像点计算x,y坐标(3D)

本文介绍如何在3D坐标系中定位带有已知Z坐标的颜色标记,通过相机校准、解决PnP问题,计算旋转和平移矢量,将图像点转换为世界坐标。在实践中,作者发现尽管对于近距离目标误差较小,但随着距离增加,误差可达20-40mm。讨论包括如何处理图像失真以及提高精度的可能方法。
摘要由CSDN通过智能技术生成

我的任务是在3D坐标系中定位对象。由于我必须获得几乎准确的X和Y坐标,因此我决定跟踪一个具有已知Z坐标的颜色标记,该颜色标记将放置在移动对象的顶部,例如此图中的橙色球:

首先,我已经完成了相机校准以获取固有参数,然后使用cv :: solvePnP来获取旋转和平移矢量,如以下代码所示:

std::vector<:point2f> imagePoints;

std::vector<:point3f> objectPoints;

//img points are green dots in the picture

imagePoints.push_back(cv::Point2f(271.,109.));

imagePoints.push_back(cv::Point2f(65.,208.));

imagePoints.push_back(cv::Point2f(334.,459.));

imagePoints.push_back(cv::Point2f(600.,225.));

//object points are measured in millimeters because calibration is done in mm also

objectPoints.push_back(cv::Point3f(0., 0., 0.));

objectPoints.push_back(cv::Point3f(-511.,2181.,0.));

objectPoints.push_back(cv::Point3f(-3574.,2354.,0.));

objectPoints.push_back(cv::Point3f(-3400.,0.,0.));

cv::Mat rvec(1,3,cv::DataType::type);

cv::Mat tvec(1,3,cv::DataType::type);

cv::Mat rotationMatrix(3,3,cv::DataType::type);

cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);

cv::Rodrigues(rvec,rotationMatrix);

在拥有所有矩阵之后,该方程式可以帮助我将图像点转换为世界坐标:

其中M是cameraMatrix,R-rotationMatrix,t-tvec,而s是未知数。 Zconst表示橙色球所在的高度,在此示例中为285毫米。

因此,首先我需要求解前面的方程,得到" s",然后可以通过选择图像点找出X和Y坐标:

解决这个问题,我可以使用矩阵的最后一行找出变量" s",因为Zconst是已知的,因此下面的代码如下:

cv::Mat uvPoint = (cv::Mat_(3,1) << 363, 222, 1); // u = 363, v = 222, got this point using mouse callback

cv::Mat leftSideMat  = rotationMatrix.inv() * cameraMatrix.inv() * uvPoint;

cv::Mat rightSideMat = rotationMatrix.inv() * tvec;

double s = (285 + rightSideMat.at(2,0))/leftSideMat.at(2,0));

//285 represents the height Zconst

std::cout <

此后,我得到结果:P = [-2629.5,1272.6,285.]

当我将其与测量进行比较时,即:Preal = [-2629.6,1269.5,285.]

误差很小,非常好,但是当我将盒子移到房间的边缘时,误差可能在20-40mm之间,我想对此进行改进。谁能帮助我,您有什么建议吗?

您是否使用固有参数对图像应用了不失真? 尤其是在图像边缘,任何COTS镜头的畸变都可能非常高,这可能至少是您收到此错误的原因之一。

@ count0是的,我做到了,首先我从xml文件中加载了cameraMatrix和distCoeffs,然后应用了cv::undistort(inputImage,undistorted,cameraMatrix,distCoeffs);之后,通过鼠标回调,我选择了橙色球并将其值存储在uvPoint中。

我认为,使用COTS相机和一个跨度为几米的房间,您将不得不承受2-4厘米的误差。 对于这样的系统,它实际上是相当不错的。 要处理真实的3D,您无论如何都必须使用多视图相机系统,并且由于视差误差,距离相机更远的对象的误差会更高。 因此,这里的答案是:使用任何种类的多种测量。

好的,非常感谢您抽出宝贵的时间。

想知道有用的例子。 谢谢!

非常有用的示例,帮助我解决了投影问题

根据您的配置,边缘的平均误差为20-40mm。 看来您做得很好。

不修改相机/系统配置,很难做得更好。 您可以尝试重做相机校准并希望获得更好的结果,但这并不能改善它们(您最终可能会得到更差的结果,因此请不要删除实际的内部参数)

如count0所述,如果需要更高的精度,则应进行多次测量。

好的,我不确定我是否做得正确,谢谢您的建议。

您是否从失真或未失真的图像中获得绿点(imagePoints)? 因为功能solvePnP已经使imagePoints不失真(除非您不传递失真系数或将它们传递为null)。 如果要从未失真的图像中获取这些imagePoints,可能会使它们两次失真,这最终会导致角落错误增加。

https://github.com/Itseez/opencv/blob/master/modules/calib3d/src/solvepnp.cpp

这不能为问题提供答案。 要批评或要求作者澄清,请在其帖子下方留下评论-您可以随时对自己的帖子发表评论,一旦拥有足够的声誉,您就可以对任何帖子发表评论。

嗨,瑞克。 我编辑了答案。 我希望现在会更好。 谢谢你的建议。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值