C++ 如何获得物体的距离,如何正确使用摄像机标定矩阵?
我成功地用opencv校准了我的相机。我正在使用的照相机镜头。 内部和外部摄像机参数如下所示C++ 如何获得物体的距离,如何正确使用摄像机标定矩阵?,c++,opencv,computer-vision,C++,Opencv,Computer Vision,我成功地用opencv校准了我的相机。我正在使用的照相机镜头。 内部和外部摄像机参数如下所示 cv::Mat cameraMatrix(3, 3, cv::DataType<double>::type); cameraMatrix.at<double>(0) = 1782.80;//fx //432.2 in mm cameraMatrix.at<double>(1) = 0; cameraMatrix.at<double>
cv::Mat cameraMatrix(3, 3, cv::DataType<double>::type);
cameraMatrix.at<double>(0) = 1782.80;//fx //432.2 in mm
cameraMatrix.at<double>(1) = 0;
cameraMatrix.at<double>(2) = 3.0587694283633488e+002;//cx
cameraMatrix.at<double>(3) = 0;
cameraMatrix.at<double>(4) = 1782.80;//fy
cameraMatrix.at<double>(5) = 3.0535864258476721e+002;//cy
cameraMatrix.at<double>(6) = 0;
cameraMatrix.at<double>(7) = 0;
cameraMatrix.at<double>(8) = 1;
cv::Mat disCoeffs(1, 5, cv::DataType<double>::type);
disCoeffs.at<double>(0) = -8.1752937039996709e-001;//k1
disCoeffs.at<double>(1) = -2.5660653367749450e+001;//k2
disCoeffs.at<double>(2) = -1.5556922931812768e-002;//p1
disCoeffs.at<double>(3) = -4.4021541217208054e-002;//p2
disCoeffs.at<double>(4) = 1.5042036073609015e+002;//k3
cv::Mat-cameraMatrix(3,3,cv::DataType::type);
cameraMatrix.at(0)=1782.80//fx//432.2英寸(毫米)
cameraMatrix.at(1)=0;
摄影机矩阵at(2)=3.0587694283633488e+002//cx
cameraMatrix.at(3)=0;
cameraMatrix.at(4)=1782.80//fy
摄影机矩阵at(5)=3.0535864258476721e+002//赛义德
cameraMatrix.at(6)=0;
cameraMatrix.at(7)=0;
cameraMatrix.at(8)=1;
cv::Mat Discoffs(1,5,cv::DataType::type);
(0)处的discoffs.at=-8.17529370039996709E-001//k1
(1)处的位移=2.5660653367749450e+001//k2
在(2)处的偏差=1.5556922931812768e-002//p1
(3)处的discoffs.at=-4.4021541217208054e-002//p2
(4)处的位移=1.5042036073609015e+002//k3
我知道这个公式是用来计算物体的距离的。但我很困惑如何正确使用它
我相机的分辨率是640x480
焦距=1782.80(px)不知道如何正确转换为毫米
我知道焦距是从传感器到图像平面的距离。那么这个值实际上代表什么呢?像素只是屏幕上代表点的一个单位
我使用的对象是圆。
半径=22。(宽和高44*44)
圆心点:300300(x,y)
不知道传感器的高度如何得到
我在哪里使用原则点
我如何获得从相机到物体的距离?如何获得圆的真实世界坐标
我知道这要求太多了。我试了一个月。没有找到合适的解决办法
我使用函数solvePnP来获得摄像机的平移和旋转矩阵。但我有问题如何计算对象点 您的
cx
和cy
似乎是错误的,因为它们应该是分辨率的一半:640/2
和480/2
。
fx
和fy
是校准过程中获得的像素单位。要将它们转换为mm,请使用以下公式:
pixels width = (image width in pixels) * (focal length in mm) / (CCD width in mm)
pixels height = (image height in pixels) * (focal length in mm) / (CCD height in mm)
当你校准你的相机时,你使用这些公式来确保你有正确的值。对我来说,cx
和cy
是错误的,因为它们代表图像的中心(它们不应该相等,除非您的图像是正方形,而不是正方形)。对于fx
和fy
我说不出来,因为我不知道你相机的CCD。如果CCD为正方形,则它们可以相等
不要手动更改这些参数,而是让校准软件计算它们
现在您有了这些参数,如何计算距离?
从某种意义上说,如果你能测量实际高度,你通常能测量距离(至少在你的情况下),你给出的公式是没有用的。。那为什么要用照相机呢
因此,要计算真实世界中的距离,您还需要两件事:外部参数(您的cameraMatrix
矩阵是内部参数)和真实世界坐标中至少四个点(点越多越好)。
一旦你有了这些东西,你就可以使用solvePnP
函数来找到一个物体的姿势。姿势表示相对于相机帧的平移和旋转
http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#solvepnp
这是一段代码,可以帮助您做到这一点:
//Four points in real world with `x,y and z` coordinates
vector<Point3f> vec3d;
vec3d.push_back(Point3f(0, 0, 0));
vec3d.push_back(Point3f(0, 211, 0));
vec3d.push_back(Point3f(295, 211, 0));
vec3d.push_back(Point3f(295, 0, 0));
最后,您可以将与tvec的实际距离计算为欧几里德距离:d=std::sqrt(tx*tx+ty*ty+tz*tz)
您的问题:
不知道传感器的高度如何得到
在互联网或手册中查找您的相机规格,您会找到它
我在哪里使用原则点
它们是你的内在参数。你不能单独使用它们
我如何获得从相机到物体的距离?如何获得圆的真实世界坐标
我在上面解释过。你需要四个点和一个圆,你只有一个不足以计算姿势
但我有问题如何计算对象点
solvePnP中的对象点是真实世界的坐标。例如,棋盘有一个角,我们知道每个角相对于棋盘中选择的世界框架的精确位置,单位为mm。它可以在左上角或类似的地方,z=0,因为棋盘是在一张纸上打印的,就像你的圆圈一样
编辑:
您可以在手册第13页找到更多规格。据说7.4 x 7.4µm
:
f (mm)=f(pixel) x pixel_size(mm) => f (mm) = 1782.80x7.2e-6 = 12.83616 (mm)
这不是4毫米!!然后你需要再做一次校准,有点不对劲
三维点:
矢量矢量三维;
vec3d
是存储3D坐标点的位置。我给你举了一个例子,第一点是原点:
vec3d.push_back(Point3f(0, 0, 0)); //y,x,z
EDIT3
如果你采取这样的模式
然后选择左上角或右上角的圆,其坐标为(0,0,0)
,即原点。之后,它旁边的圆是第二个点,它将有(x,0,0)
x
是两个圆之间的距离,单位为(mm)。。对模式中的四个点执行相同的操作。你们可以选择任何你们想要的图案,只要你们能在你们的图像中检测到它,并以像素为单位检索它们的坐标。
如果您仍然不理解,我建议您学习
投影几何
和相机模型
课程。。因此,您可以理解每个参数的含义。根据您发布的网站,焦距为4.0mm。除此之外,您只需要传感器的高度。当谈论你们的图像时,你们需要用屏幕坐标,而不是模型坐标或世界坐标。我如何获得传感器的高度?那个么为什么我需要摄像机矩阵?我知道图像坐标,我需要得到世界坐标?你们用的是物理摄像机
vec3d.push_back(Point3f(0, 0, 0)); //y,x,z