• 三维重建-相机标定


    相机标定就是设置各种参数(即投影公式中的项目)的过程。

    相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。

    相机标定的输入:标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上)。

    相机标定的输出:摄像机的内参、外参系数。

    过程:

    1. 准备标定图片
    2. 对每一张标定图片,提取角点信息(先说明角点数量,再利用函数findchessboardcorners)

    FindChessboardCorners是opencv的一个函数,可以用来寻找棋盘图的内角点位置。

        int cvFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH );

        

    Image:

    输入的棋盘图,必须是8位的灰度或者彩色图像。

    pattern_size:

    棋盘图中每行和每列角点的个数。

    Corners:

    检测到的角点

    corner_count:

    输出,角点的个数。如果不是NULL,函数将检测到的角点的个数存储于此变量。

    Flags:

    各种操作标志,可以是0或者下面值的组合:

    CV_CALIB_CB_ADAPTIVE_THRESH -使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。

    CV_CALIB_CB_NORMALIZE_IMAGE -在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。

    CV_CALIB_CB_FILTER_QUADS -使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。

        注意:

    • pattern_size参数传递内点数,8*8的棋盘只有7*7内点。
    1. 对每一张标定图片,进一步提取亚像素角点信息

    cv::goodFeaturesToTrack()提取到的角点只能达到像素级别,在很多情况下并不能满足实际的需求,这时,我们则需要使用cv::cornerSubPix()对检测到的角点作进一步的优化计算,可使角点的精度达到亚像素级别。

    具体调用形式如下:

     void cv::cornerSubPix(
            cv::InputArray image, // 输入图像
            cv::InputOutputArray corners, // 角点(既作为输入也作为输出)
            cv::Size winSize, // 区域大小为 NXN; N=(winSize*2+1)
            cv::Size zeroZone, // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
            cv::TermCriteria criteria // 停止优化的标准
        );

        

    第一个参数是输入图像,和cv::goodFeaturesToTrack()中的输入图像是同一个图像。
    第二个参数是检测到的角点,即是输入也是输出。

    第三个参数是计算亚像素角点时考虑的区域的大小,大小为NXN; N=(winSize*2+1)。

    第四个参数作用类似于winSize,但是总是具有较小的范围,通常忽略(即Size(-1, -1))。

    第五个参数用于表示计算亚像素时停止迭代的标准,可选的值有cv::TermCriteria::MAX_ITER 、cv::TermCriteria::EPS(可以是两者其一,或两者均选),前者表示迭代次数达到了最大次数时停止,后者表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()构造函数进行指定。


       

    1. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)
    cvDrawChessboardCorners(
    IntPtr image,
    Size patternSize,
    IntPtr corners,
    int count,
    int patternWasFound
    )
    image——输入的目标图像,必须是8位彩色图像
    patternSize——内心的角落每棋盘的行和列的数目角,也就是标定板角点的行数和列数
    corners——检测到的角阵列,也就是用cvFindCornerSubPix函数检测到的角点的坐标(cvFindCornerSubPix的第二个参数)
    count——角数,每张标定图所有角点的数目
    patternWasFound——指出是否已找到所有的角点(该值为0表示不能找到所有的角点,不为0则表示能够找出所有的角点),该参数值由cvFindChessboardCorners函数的返回值给出
    1. 相机标定

        

    double cv::calibrateCamera (
    InputArrayOfArrays objectPoints,//世界坐标系中的点。在使用时,应该输入vector< vector< Point3f > >。
    InputArrayOfArrays imagePoints,//其对应的图像点。和objectPoints一样,应该输入vector< vector< Point2f > >型的变量。
    Size imageSize,//图像的大小,在计算相机的内参数和畸变矩阵需要用到;
    InputOutputArray cameraMatrix,//内参数矩阵。输入一个Mat cameraMatrix即可。
    InputOutputArray distCoeffs,//畸变矩阵。输入一个Mat distCoeffs即可。
    OutputArrayOfArrays rvecs,//旋转向量;应该输入一个Mat的vector,即vector< Mat > rvecs因为每个vector< Point3f >会得到一个rvecs。
    OutputArrayOfArrays tvecs,//位移向量;和rvecs一样,也应该为vector tvecs。
    int flags = 0,
    TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON)
    )

    o:

    stdDeviationsIntrinsics :内参数的输出向量。输出顺序为: (fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy) ,如果不估计其中某一个参数,值等于0

    stdDeviationsExtrinsics :外参数的输出向量。输出顺序: (R1,T1,…,RM,TM) ,M是标定图片的个数, Ri,Ti 是1x3的向量 。

    perViewErrors 每个标定图片的重投影均方根误差的输出向量。

    criteria: 迭代优化算法的终止准则

    flags :标定函数是所采用的模型(重点)”。
    可输入如下某个或者某几个参数:

    CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,将包含有效的fx,fy,cx,cy的估计值的内参矩阵cameraMatrix,作为初始值输入,然后函数对其做进一步优化。如果不使用这个参数,用图像的中心点初始化光轴点坐标(cx, cy),使用最小二乘估算出fx,fy(这种求法好像和张正友的论文不一样,不知道为何要这样处理)。注意,如果已知内部参数(内参矩阵和畸变系数),就不需要使用这个函数来估计外参,可以使用solvepnp()函数计算外参数矩阵。

    CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点,光轴点将保持为图像的中心点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,保持为输入的值。

    CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy的实际输入值将会被忽略,只有fx/fy的比值被计算和使用。

    CV_CALIB_ZERO_TANGENT_DIST:切向畸变系数(P1,P2)被设置为零并保持为零。

    CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:对应的径向畸变系数在优化中保持不变。如果设置了CV_CALIB_USE_INTRINSIC_GUESS参数,就从提供的畸变系数矩阵中得到。否则,设置为0。

    CV_CALIB_RATIONAL_MODEL(理想模型):启用畸变k4,k5,k6三个畸变参数。使标定函数使用有理模型,返回8个系数。如果没有设置,则只计算其它5个畸变参数。

    CALIB_THIN_PRISM_MODEL (薄棱镜畸变模型):启用畸变系数S1、S2、S3和S4。使标定函数使用薄棱柱模型并返回12个系数。如果不设置标志,则函数计算并返回只有5个失真系数。

    CALIB_FIX_S1_S2_S3_S4 :优化过程中不改变薄棱镜畸变系数S1、S2、S3、S4。如果cv_calib_use_intrinsic_guess设置,使用提供的畸变系数矩阵中的值。否则,设置为0。

    CALIB_TILTED_MODEL (倾斜模型):启用畸变系数tauX and tauY。标定函数使用倾斜传感器模型并返回14个系数。如果不设置标志,则函数计算并返回只有5个失真系数。

    CALIB_FIX_TAUX_TAUY :在优化过程中,倾斜传感器模型的系数不被改变。如果cv_calib_use_intrinsic_guess设置,从提供的畸变系数矩阵中得到。否则,设置为0。

    函数返回
    重投影的总的均方根误差。

    1. 对标定结果进行评价
    2. 查看标定效果——利用标定结果对棋盘图进行矫正

    void initUndistortRectifyMap(InputArray cameraMatrix,//输入相机矩阵
     InputArray distCoeffs, //畸变矩阵  失真系数(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]])为4、5或8个元素的输入矢量。如果矢量为 NULL/空,则假设为零失真系数。
    InputArray R,//对象空间(3x3矩阵)中的可选校正转换
     InputArray newCameraMatrix,//新相机矩阵A'=vecthreethree{f_x'}{0}{c_x'}{0}{f_y'}{c_y'}{0}{0}{1}。
     Size size, //未畸变的图像大小
    int m1type, 第一个输出地图的类型,可以CV_32FC1CV_16SC2。
    OutputArray map1, //对应x方向映射
    OutputArray map2)//对应y方向映射
    
    
    
    

    dst(x, y) = src( mapx(x, y), mapy(x, y) )


    void
    remap( InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode = BORDER_CONSTANT, const Scalar& borderValue = Scalar() )

    InputArray类型的src,输入图像,填Mat类的对象即可,且需要为单通道8位或者浮点型的图像;
    2)OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和原图片有一样的尺寸和类型。
    3)InputArray类型的map1,它有两种可能的表示对象;
    表示点(x, y)的第一个映射;
    表示CV_16S, CV_32FC1或CV_32FC2类型的X值;
    4)InputArray类型的map2,同样,它有两种可能的表示对象,而且它会根据map1来确定表示那种对象;
    若map1表示点(x, y)时,这个参数不代表任何值;
    表示CV_16UC1,CV_32FC1类型的Y值(第二个值);
    5)int类型的interpolation,插值方式,之前的resize()函数中有讲到,需要注意,resize()函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
    INTER_NEAREST:最近邻插值;
    INTER_LINEAR:双线性插值(默认值);
    INTER_CUBIC:双三次样条插值(逾4x4像素邻域内的双三次插值);
    INTER_LANCZOS4:Lanczos插值(逾8x8像素邻域的Lanczos插值)
    6)int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点”的像素不会被此函数修改;
    7)const Scalar&类型的 borderValue,当有常数边界时使用的值,默认值为0;

    后续:相机姿态还原;用标定相机实现三维重建,计算立体图像深度

  • 相关阅读:
    jenkins配置html报告
    JMeter并发测试(设置集合点)
    jmeter压力测试 设置一秒发送一次请求,一秒两次请求
    jmeter压力测试的简单实例+badboy脚本录制
    JMeter问题集
    英语自然拼读法基本规则和小窍门
    Jmeter工具做性能测试 常见的错误汇总
    如何使用JDK自带工具JConsole
    第七章 JMeter 逻辑控制器
    第六篇:JMeter 断言
  • 原文地址:https://www.cnblogs.com/KAVEI/p/14764943.html
Copyright © 2020-2023  润新知