Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何获得物体的距离,如何正确使用摄像机标定矩阵?_C++_Opencv_Computer Vision - Fatal编程技术网

C++ 如何获得物体的距离,如何正确使用摄像机标定矩阵?

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>

我成功地用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>(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