【发布时间】:2017-05-21 02:09:29
【问题描述】:
我正在尝试使用立体相机获取 3D 坐标。
第二种方法是在opencv中使用reprojectImageTo3D。
但是我不知道这个方法的原理。
结果不是毫米,所以很难匹配大小。
请告诉我这两种方法的区别。
(这些代码中的第一个是匹配后将Point Feature转换为3D坐标。) (第二个代码是使用SGBM计算整个立体图像的视差,使用reprojectImageTo3D计算点特征的3d坐标。)
*第一种方法
cv::Mat depth(m_input.m_leftImg.size(), CV_32FC3, cv::Scalar::all(0));
int size = feOutput.m_leftKp.size();
for (int i = 0; i < size; i++)
{
cv::Point pt = cv::Point((int)(feOutput.m_leftKp.at(i).pt.x + 0.5f), (int)(feOutput.m_leftKp.at(i).pt.y + 0.5f));
depth.at<cv::Vec3f>(pt)[2] = fX * baseLine / (feOutput.m_leftKp.at(i).pt.x - feOutput.m_rightKp.at(i).pt.x); // Z
depth.at<cv::Vec3f>(pt)[0] = (feOutput.m_leftKp.at(i).pt.x - cX) * depth.at<cv::Vec3f>(pt)[2] / fX; // X
depth.at<cv::Vec3f>(pt)[1] = (feOutput.m_leftKp.at(i).pt.y - cY) * depth.at<cv::Vec3f>(pt)[2] / fY; // Y
}
depth /= 1000.f; //milli-meter to meter
*第二种方法
cv::Mat disparity16S(m_input.m_leftImg.size(), CV_16S);
sgbm->compute(m_input.m_leftImg, m_input.m_rightImg, disparity16S);
cv::Mat xyz;
cv::Matx44d Q = cv::Matx44d(
1.0, 0.0, 0.0, -cX,
0.0, 1.0, 0.0, -cY,
0.0, 0.0, 0.0, fX,
0.0, 0.0, -1.0 / baseLine, 0/*(CX - CX) / baseLine*/
);
cv::reprojectImageTo3D(disparity16S, xyz, Q, true);
cv::Mat pointXYZ(xyz.size(), xyz.type(), cv::Scalar::all(0));
for (int i = 0; i < size; i++)
{
cv::Point pt = cv::Point((int)(feOutput.m_leftKp.at(i).pt.x + 0.5f), (int)(feOutput.m_leftKp.at(i).pt.y + 0.5f));
pointXYZ.at<cv::Vec3f>(pt) = xyz.at<cv::Vec3f>(pt) / 1000.f;
}
添加+ 粉色是reprojectImageTo3D方法缩放到1/100的尺寸,黄色是第一种方法中1/1000(mm 2米)的尺寸。 如果这两种方法是一样的,为什么会有规模差异?
【问题讨论】:
标签: c++ opencv 3d camera-calibration stereo-3d