首页 文章

如何获得物体的距离和如何正确使用相机校准矩阵?

提问于
浏览
1

我使用opencv成功校准了我的相机 . 我正在使用的相机镜头 . https://www.baslerweb.com/en/products/vision-components/lenses/basler-lens-c125-0418-5m-f1-8-f4mm/

内部和外部摄像机参数如下 .

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

我知道这个公式用于计算物体的距离 . 但我很困惑如何正确使用它 .

enter image description here

我相机的分辨率为640x480 .

焦距= 1782.80(px)不知道如何正确转换为mm

我知道焦距是从传感器到图像平面的距离 . 那么这个值究竟代表什么呢?像素只是屏幕上的一个单位代表点 .

我正在使用的对象是圆圈 . 半径= 22.(宽度和高度44 * 44)圆心点:300,300(x,y)

传感器高度不知道怎么弄?

我在哪里使用原则点?

我如何从相机到物体的距离?如何获得圆的真实世界坐标?

我知道要问太多了 . 我试了一个月 . 没有找到任何适当的解决方案 .

我使用函数solvePnP来获取相机平移和旋转矩阵 . 但我有问题如何计算对象点?

1 回答

  • 2

    您的 cxcy 似乎是错误的,因为它们应该是分辨率的一半: 640/2480/2 . fxfy 是从校准过程中获得的像素单位 . 要将它们转换为 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)
    

    校准相机时,使用这些公式确保您具有正确的值 . 对我来说 cxcy 是错误的,因为它们代表了图像的中心(它们不应该相等,除非你的图像是正方形而不是这种情况) . 对于 fxfy ,我可以't tell because I don't知道相机的CCD . 如果CCD是方形的,它们可以相等 .

    请勿手动更改这些参数,而是让校准软件对其进行计算 .

    Now you've those parameters, how you compute the distance?

    你提出的公式在某种意义上是没有用的,如果你可以测量真实的高度,你通常可以测量距离(至少在你的情况下)..所以为什么使用相机!?

    因此,要计算现实世界中的距离,还需要两件事:外部参数(你的 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));
    

    z=0 因为你的真实点在一个平面上 .

    //The same four points but in your image plan, therefore there is no z and they're in pixel unit
    vector<Point2f> vec2d;
    vec2d.push_back(Point2f(532, 412)); //(y,x)
    vec2d.push_back(Point2f(583, 594));
    vec2d.push_back(Point2f(927, 535));
    vec2d.push_back(Point2f(817, 364));
    
    //The pose of the object: rvec is your rotation vector, tvec is your translation vector
    cv::Mat rvec, tvec;
    solvePnP(vec3d, vec2d, cameraMatrix, distCoeffs, rvec, tvec);
    

    最后,您可以计算 tvec 与欧几里德距离的实际距离: d=std::sqrt(tx*tx+ty*ty+tz*tz) .

    Your questions:

    传感器高度不知道怎么弄?

    在互联网或手册中查找您的相机规格,您就会找到它 .

    我在哪里使用原则点?

    它们是你的内在参数 . 你不会单独使用它们 .

    我如何从相机到物体的距离?如何获得圆的真实世界坐标?

    我在上面解释过 . 你需要四个点并且有一个圆圈你只有一个不足以计算姿势 .

    但我有问题如何计算对象点?

    solvePnP中的objectPoints是你的真实世界坐标 . 例如,棋盘上有角,我们知道每个角的精确位置,相对于您在棋盘中选择的世界框架 . 它可以在左上角或类似的东西和z = 0,因为棋盘就像你的圆圈一样打印在纸上!

    EDIT:

    您可以在手册页13 here中找到更多规格 . 据说 7.4 x 7.4µm

    f (mm)=f(pixel) x pixel_size(mm) => f (mm) = 1782.80x7.2e-6 = 12.83616 (mm)
    

    哪个不是4mm !!然后你需要再次进行校准,出了点问题!

    3D点:矢量vec3d; vec3d 是您要存储3D坐标点的地方 . 我给你举了一个例子来说明原点的第一点:

    vec3d.push_back(Point3f(0, 0, 0)); //y,x,z
    

    EDIT3

    如果你采取这样的模式

    enter image description here

    然后选择例如左上角或右上角的圆圈,它的坐标为 (0,0,0) ,即原点 . 之后,它旁边的圆圈是你的第二个点,它将具有 (x,0,0) x 是两个圆圈之间的距离(mm) . 你对模式中的四个点做同样的事情 . 您可以选择所需的任何图案,只要您可以在图像中检测到它并以像素为单位检索它们的坐标 . 如果您仍然不明白,我建议您参加 projective geometrycamera models 的课程,以便了解每个参数的含义 .

相关问题