Opencv单目标定flag的设定

1. flag中的标签顺序:

在代码中的对应如下: 

    enum{
        CALIB_USE_INTRINSIC_GUESS   = 1 << 0,
        CALIB_RECOMPUTE_EXTRINSIC   = 1 << 1,
        CALIB_CHECK_COND            = 1 << 2,
        CALIB_FIX_SKEW              = 1 << 3,
        CALIB_FIX_K1                = 1 << 4,
        CALIB_FIX_K2                = 1 << 5,
        CALIB_FIX_K3                = 1 << 6,
        CALIB_FIX_K4                = 1 << 7,
        CALIB_FIX_INTRINSIC         = 1 << 8,
        CALIB_FIX_PRINCIPAL_POINT   = 1 << 9
    };

其中最低位为:CALIB_USE_INTRINSIC_GUESS , 最高位为: CALIB_FIX_PRINCIPAL_POINT

  int flags = 0;
  flags |= myfisheye::CALIB_RECOMPUTE_EXTRINSIC;
  flags |= myfisheye::CALIB_CHECK_COND;
  flags |= myfisheye::CALIB_FIX_SKEW;
  flags |= myfisheye::CALIB_FIX_K4;
  std::cout <<"flags = " << flags <<std::endl;

如上面那段代码的设定,flags的打印值为142, 转换成二进制入下:

与上面的顺序对应

写得时候记得区分, 因为cv::fisheye对应的参数,与cv:: 对应的参数是不一样的;

举例,比较经典的鱼眼单目标定程序如下:

  cv::Matx33d intrinsic_matrix; /*****    摄像机内参数矩阵    ****/
  cv::Vec4d distortion_coeffs;  /* 摄像机的4个畸变系数:k1,k2,k3,k4*/

  std::vector<cv::Vec3d> rotation_vectors;    /* 每幅图像的旋转向量 */
  std::vector<cv::Vec3d> translation_vectors; /* 每幅图像的平移向量 */
  int flags = 0;
  flags |= myfisheye::CALIB_RECOMPUTE_EXTRINSIC;
  flags |= myfisheye::CALIB_CHECK_COND;
  flags |= myfisheye::CALIB_FIX_SKEW;
 
  //需要传入cornerSeq的点对应的id,去确定其是属于第几行第几列
  myfisheye::calibrate(object_Points, corners_Seq, corners_Id, image_size,
                       intrinsic_matrix, distortion_coeffs, rotation_vectors,
                       translation_vectors, flags,
                       cv::TermCriteria(3, 30, 1e-5));

接下来说一下每个flag参数所表达的意思:

CALIB_RECOMPUTE_EXTRINSIC 是否重新计算外参;如果设定为true,则每一轮的迭代优化后都会重新计算一次rvec和tvec, 也就是每一副图像相对于固定的世界坐标系的外参R,t;一般都会开启;

CALIB_USE_INTRINSIC_GUESS 是否使用输入的内参;如果设定为True,则上面例子中的intrinsic_matrix必须有值;如果设定为False,opencv默认的初始化参数计算如下;

CALIB_FIX_INTRINSIC:是否固定内参;如果设定为True, 则上面例子中的intrin_matrix必须有精确地内参值, 在接下来的单目标定程序中,不会改变这个内参;

                                         这里要和上面的CALIB_USE_INTRINSIC_GUESS做区分, CALIB_USE_INTRINSIC_GUESS是给定一个比较合理的初始值即可,防止后面的优化无法收敛;

CALIB_CHECK_COND:  是否检测条件; 检测最后的雅克比公式中B矩阵是不是满秩矩阵,在鱼眼标定的时候,一般设置为True,可以帮我们筛选掉不好的标定图片;

CALIB_FIX_SKEW:保证内参矩阵的对称性;如果设定为True,内参矩阵的格式为[ fx, 0, cx; 0, fy,cy; 0, 0,1] ;如果设定为false,则内参格式为 [fx' , alpha , cx; 0, fy' ,cy;  0, 0,1], 一般设定为True;

CALIB_FIX_K1,K2,K3,K4:是否固定某个畸变参数; 如果选择CALIB_FIX_K4, 对应的畸变参数为:[K1, K2,K3,0], 同理,如果CALIB_FIX_K3, 则对应的畸变参数为[K1,K2,0,0]

OpenCV源码内参初始化为:

fx = max(image_size.width, image_size.height) / CV_PI;
fy = max(image_size.width, image_size.height) / CV_PI);
cx = image_size.width / 2.0 - 0.5;
cy = image_size.height / 2.0 - 0.5;

CALIB_FIX_SKEW 使用举例:

  int flags = 0;
  flags |= myfisheye::CALIB_RECOMPUTE_EXTRINSIC;
  flags |= myfisheye::CALIB_CHECK_COND;
  flags |= myfisheye::CALIB_FIX_SKEW;
 
  //需要传入cornerSeq的点对应的id,去确定其是属于第几行第几列
  double rms = myfisheye::calibrate(object_Points, corners_Seq, corners_Id, image_size,
                       intrinsic_matrix, distortion_coeffs, rotation_vectors,
                       translation_vectors, flags,
                       cv::TermCriteria(3, 30, 1e-5));

这段代码的执行结果中,内参标定结果为:

[216.7146086633471, 0, 306.9382661479993;
 0, 286.00358341677, 252.6790474661119;
 0, 0, 1]

去除SKEW标签后,同一组图片的标定结果如下:

[219.1049328488637, -0.4470566496293429, 306.370172490616;
 0, 289.1554239282392, 252.4634276394423;
 0, 0, 1]

设定了CALIB_FIX_SKEW之后, 内参的偏差系数将会被设定为0, 反之则会计算偏差系数;

关于偏差系数, 可以看下图, 左图表示理想的归一化相机平面, 右图表示的有偏差的归一化平面, 即x轴与y轴是有夹角的;

具体可以参考这篇文章: 我们是否需要关注Skew coefficient?

总结来讲,对于普通相机不需要在意这个参数, 因为大部分厂商的CCD都是直角的,因此,标定的时候, 添加CALIB_FIX_SKEW 即可, 当有unusual相机的时候要额外注意;

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值