zoukankan      html  css  js  c++  java
  • opencv 从像素坐标得到世界坐标系坐标

    坐标变换详解

    1.1 坐标关系
    在这里插入图片描述

    相机中有四个坐标系,分别为world,camera,image,pixel

    • world为世界坐标系,可以任意指定轴和轴,为上图P点所在坐标系。
    • camera为相机坐标系,原点位于小孔,z轴与光轴重合,轴和轴平行投影面,为上图坐标系。
    • image为图像坐标系,原点位于光轴和投影面的交点,轴和轴平行投影面,为上图坐标系。
    • pixel为像素坐标系,从小孔向投影面方向看,投影面的左上角为原点,uv轴和投影面两边重合,该坐标系与图像坐标系处在同一平面,但原点不同。

    坐标转换

    下式为像素坐标pixel与世界坐标world的转换公式,左侧第一个矩阵为相机内参数矩阵,第二个矩阵为相机外参数矩阵。假设图像坐标已知,同时相机内参数矩阵通过标定已获取,还需计算比例系数s和外参数矩阵。
    s [ u v 1 ] = [ f x 0 c x 0 f y c y 0 0 1 ] [ r 11 r 12 r 13 t 1 r 21 r 22 r 23 t 2 r 31 r 32 r 33 t 3 ] [ x y z 1 ] s left[

    uv1uv1

    ight] =left[

    fx00amp;0amp;fyamp;0amp;cxamp;cyamp;1fxamp;0amp;cx0amp;fyamp;cy0amp;0amp;1

    ight] left[

    r11r21r31amp;r12amp;r22amp;r32amp;r13amp;r23amp;r33amp;t1amp;t2amp;t3r11amp;r12amp;r13amp;t1r21amp;r22amp;r23amp;t2r31amp;r32amp;r33amp;t3

    ight] left[

    xyz1xyz1

    ight]suv1=fx000fy0cxcy1r11r21r31r12r22r32r13r23r33t1t2t3xyz1 ight] = M(Rleft[ ight]+t)

    比例系数s转换公式可简化为:


    s [ u v 1 ] = M ( R [ X Y Z c o n s t ] + t ) s left[

     

    uv1uv1

     

    XYZconstXYZconstsuv1=M(RXYZconst+t) ight] = left[ ight] +R^{-1}t

    M为相机内参数矩阵,R为旋转矩阵,t为平移矩阵,为世界坐标系高度,可设置为0。

    通过矩阵变换可得下式:


    R − 1 M − 1 s [ u v 1 ] = [ X Y Z c o n s t ] + R − 1 t R^{-1}M^{-1}s left[

     

    uv1uv1

     

    XYZconstXYZconstR1M1suv1=XYZconst+R1t

    求解出旋转矩阵和平移矩阵即可算得s。

    代码实现

    • input:Point2f inPoints - 像素坐标系下的点Mat rvec - 标定得到的rvecs(下的rvecs[i])Mat tvec - 标定得到的tvecs(下的tvecs[i]) ------以第i个棋盘格顶点建立坐标系Mat cameraMatrix - 标定得到的内参矩阵



    vector<Mat>
    vector<Mat>

    • output: (return value)Point3f worldPoint

     

    
    

    Point3f getWorldPoints(Point2f &inPoints, Mat &rvec, Mat &tvec, Mat &cameraMatrix) { //initialize parameter Mat rotationMatrix;//3*3 Rodrigues(rvec,rotationMatrix); double zConst = 0;//实际坐标系的距离,若工作平面与相机距离固定可设置为0 double s; //获取图像坐标 cv::Mat imagePoint = (Mat_<double>(3,1)<<double(inPoints.x),double(inPoints.y),1); // cv::Mat::ones(3, 1, cv::DataType<double>::type); //u,v,1 // imagePoint.at<double>(0, 0) = inPoints.x; // imagePoint.at<double>(1, 0) = inPoints.y; //计算比例参数S cv::Mat tempMat, tempMat2; tempMat = rotationMatrix.inv() * cameraMatrix.inv() * imagePoint; tempMat2 = rotationMatrix.inv() * tvec; s = zConst + tempMat2.at<double>(2, 0); s /= tempMat.at<double>(2, 0); //计算世界坐标 Mat wcPoint = rotationMatrix.inv() * (s * cameraMatrix.inv() * imagePoint - tvec); Point3f worldPoint(wcPoint.at<double>(0, 0), wcPoint.at<double>(1, 0), wcPoint.at<double>(2, 0)); return worldPoint; }

     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    参考:

    https://blog.csdn.net/Kalenee/article/details/80659489

    作者:柒月
    Q群 :2122210(嵌入式/机器学习)
  • 相关阅读:
    31天重构指南之二十:提取子类
    31天重构指南之二十二:分解方法
    大叔手记(17):大叔2011年读过的书及2012年即将要读的书
    深入理解JavaScript系列(5):强大的原型和原型链
    深入理解JavaScript系列(10):JavaScript核心(晋级高手必读篇)
    深入理解JavaScript系列(11):执行上下文(Execution Contexts)
    深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP
    深入理解JavaScript系列(4):立即调用的函数表达式
    深入理解JavaScript系列(3):全面解析Module模式
    深入理解JavaScript系列(7):S.O.L.I.D五大原则之开闭原则OCP
  • 原文地址:https://www.cnblogs.com/Ph-one/p/13874981.html
Copyright © 2011-2022 走看看