• 前言

参考 OpenCV畸变校正原理以及损失有效像素原理分析 - 一度逍遥 - 博客园 我们知道目前opencv在标定完后得到相机内参及畸变系数,要么通过cv::undistort()直接得到去畸变的图像,要么通过cv::getOptimalNewCameraMatrix()得到新的矩阵,再通过cv::initUndistortRectifyMap()得到x轴与y轴映射,最后通过cv::remap()将原图映射到新图。

  • 两者的不同

在说两者不同之前,我们先介绍下getOptimalNewCameraMatrix()函数。

getOptimalNewCameraMatrix(cv::InputArray _cameraMatrix,cv::InputArray _distCoeffs,cv::Size imgSize, double alpha, cv::Size newImgSize,cv::Rect* validPixROI, bool centerPrincipalPoint)

alpha之前的参数自不必说,alpha之后的参数都可以视为默认。关键就在alpha的含义。

 icvGetRectangles(cameraMatrix, distCoeffs, 0, 0, imgSize, inner, outer);// Projection mapping inner rectangle to viewportdouble fx0 = (newImgSize.width) / inner.width;double fy0 = (newImgSize.height) / inner.height;double cx0 = -fx0 * inner.x;double cy0 = -fy0 * inner.y;// Projection mapping outer rectangle to viewportdouble fx1 = (newImgSize.width) / outer.width;double fy1 = (newImgSize.height) / outer.height;double cx1 = -fx1 * outer.x;double cy1 = -fy1 * outer.y;// Interpolate between the two optimal projectionsM[0][0] = fx0*(1 - alpha) + fx1*alpha;M[1][1] = fy0*(1 - alpha) + fy1*alpha;M[0][2] = cx0*(1 - alpha) + cx1*alpha;M[1][2] = cy0*(1 - alpha) + cy1*alpha;

在getOptimalNewCameraMatrix()函数中,有上述一段代码,意思是从内参/畸变系数中得到两个inner和outer矩阵,当alpha为0时,取inner即内矩阵,用内矩阵大小作为新的图像大小,重新得到fx,fy,cx,cy,因此新的内参矩阵诞生了. 当alpha为1时,取outer即外矩阵。当alpha介于0~1时,则按照比例重新计算fx,fy,cx,cy。

事实上,内矩阵等同于不含任何黑色边框的图幅大小,而外矩阵等同于原图大小。

alpha=1
alpha=0

继续深究,那么它的inner和outer又是怎么来的呢?

  • inner和outer的来源

inner和outer又是怎么来的,和原来的内参与畸变又有什么关系呢? 在icvGetRectangles()函数中有这样一段代码

for (y = k = 0; y < N; y++) //opencv 默认为 9for (x = 0; x < N; x++)pts[k++] = cvPoint2D32f((float)x*imgSize.width / (N - 1),(float)y*imgSize.height / (N - 1));
cvUndistortPoints2(_pts, _pts, cameraMatrix, distCoeffs, R, newCameraMatrix);
float iX0 = -FLT_MAX, iX1 = FLT_MAX, iY0 = -FLT_MAX, iY1 = FLT_MAX;
float oX0 = FLT_MAX, oX1 = -FLT_MAX, oY0 = FLT_MAX, oY1 = -FLT_MAX;
// find the inscribed rectangle.
// the code will likely not work with extreme rotation matrices (R) (>45%)
for (y = k = 0; y < N; y++)for (x = 0; x < N; x++){CvPoint2D32f p = pts[k++];oX0 = MIN(oX0, p.x);oX1 = MAX(oX1, p.x);oY0 = MIN(oY0, p.y);oY1 = MAX(oY1, p.y);if (x == 0)iX0 = MAX(iX0, p.x);if (x == N - 1)iX1 = MIN(iX1, p.x);if (y == 0)iY0 = MAX(iY0, p.y);if (y == N - 1)iY1 = MIN(iY1, p.y);}inner = cv::Rect_<float>(iX0, iY0, iX1 - iX0, iY1 - iY0);outer = cv::Rect_<float>(oX0, oY0, oX1 - oX0, oY1 - oY0);

这段代码的含义是指,按照输入图像的大小,生成长宽分别按照 imgSize.width / 8的间隔和 imgSize.height / 8 间隔的9*9个点。

再对这81个点,进行去畸变转换得到新的点。

81个点的转换(部分)

再从去畸变后的点中相互比较,得到外围矩阵oX0,oY0,oX1,oY1,及由原四个角点得到的内围矩阵,也就是outer与inner。

  • 结束语

之所以会研究这部分代码,是因为在处理Ladybug相机时,它可以自动提供去畸变后的图片,例如

ladybug某个镜头的图像

但是黑色边框却没有去掉,因为想偷懒尝试通过getOptimalNewCameraMatrix()将alpha设为0得到去黑边图像,但由于ladybug自身只提供相机内参而不提供畸变系数,当我设畸变系数为空时,内参并没有变化,出于好奇就稍深入研究了下源码。现在明白了当畸变系数为空时,inner与outer由于undistortpoint()大小相同,fx,fy,cx,cy当然就没有变化。

最后还是自己手动截取可视范围,保持fx,fy不变,根据新左上角重新计算cx,cy。得到新的去黑边后的图像以及对应的新相机内参。

[1]: OpenCV畸变校正原理以及损失有效像素原理分析 - 一度逍遥 - 博客园

[2]: OpenCV: OpenCV modules

相机内参中cx cy_Opencv中的两种去畸变函数相关推荐

  1. c语言中的普通字符包括什么,【判断题】C语言中的字符常量通常有两种形式:普通字符和转义字符。...

    [判断题]C语言中的字符常量通常有两种形式:普通字符和转义字符. 更多相关问题 ---Can you speak French?---Yes, but only____.A.a littleB.lit ...

  2. Json返回时间中出现乱码问题的两种解决方法

    Json返回时间中出现乱码问题的两种解决方法 参考文章: (1)Json返回时间中出现乱码问题的两种解决方法 (2)https://www.cnblogs.com/hanyinglong/archiv ...

  3. .net中对HTTP请求的两种请求:Get和Post的操作

    .net中对HTTP请求的简单操作总结 第一部分,HTTP协议的简单了解 一.           什么是HTTP协议 超文本传输协议 (HTTP-Hypertext transfer protoco ...

  4. android中的定时任务一般有两种机制,android 定时任务

    使用timertask进行定时任务 首先创建TimerTask: class SynchroTimerTask extends TimerTask { @Override public void ru ...

  5. Java中的string定义的两种方法和区别

    java中的String定义的两种方法和区别 第一种:new方式 String s1 = new String("hello world"); String s2 = new St ...

  6. php 嵌套 mysql_PHP中实现MySQL嵌套事务的两种解决方案,mysql嵌套_PHP教程

    PHP中实现MySQL嵌套事务的两种解决方案,mysql嵌套 一.问题起源 在MySQL的官方文档中有明确的说明不支持嵌套事务: 1. Transactions cannot be nested. T ...

  7. html中获取modelandview中的json数据_从Bitmap中获取YUV数据的两种方式

    从Bitmap中我们能获取到的是RGB颜色分量,当需要获取YUV数据的时候,则需要先提取R,G,B分量的值,然后将RGB转化为YUV(根据具体的YUV的排列格式做相应的Y,U,V分量的排列) 所以这篇 ...

  8. JSP页面中的pageEncoding和contentType两种属性

    关于JSP页面中的pageEncoding和contentType两种属性的区别: pageEncoding是jsp文件本身的编码 contentType的charset是指服务器发送给客户端时的内容 ...

  9. 在.NET中执行Async/Await的两种错误方法

    微信公众号:架构师高级俱乐部 关注可了解更多的编程,架构知识.问题或建议,请公众号留言; 如果你觉得此文对你有帮助,欢迎转发 在.NET中执行异步/等待的两种错误方法 在应用开发中,我们为了提高应用程 ...

最新文章

  1. 我的KT库之-----扩展方法
  2. 遍历文件夹_使用JavaScript遍历本地文件夹的文件
  3. 用vim看代码的常用指令
  4. python打开.data_DataX初体验-python命令启动以及纯java启动
  5. 透视变换--基于getPerspectiveTransform()及像素赋值(未涉及插值)
  6. Pycharm 加载pygame解决方案
  7. python机器学习库sklearn——K最近邻、K最近邻分类、K最近邻回归
  8. 漫步微积分三十七——力和功
  9. Java项目:医院门诊收费管理系统(java+html+jdbc+mysql)
  10. 网上购物系统设计类图
  11. 深度卷积神经网络是什么,卷积神经网络结构设计
  12. Scheme语言 入门语法
  13. 连载 北漂十二年祭 3 --Leo第二次面试,无意中的霸王面
  14. Python-实验4
  15. [学习笔记]多项式与有标号简单图计数
  16. 铁路 信号组调工 技师 练习题 01
  17. 福昕阅读器和编辑器使用注意事项高级查找功能两个应用软件共用。但是注意不能卸载福昕编辑器,试验过卸载后福昕阅读器就没有查找功能了
  18. Redis - 启动
  19. 第一周------继续
  20. 你想要拥有自己的搜索引擎吗?

热门文章

  1. 度微尔开发者联盟网站
  2. [ES6] 细化ES6之 -- 字符串的扩展
  3. 前端经常遇到的跨域问题几种解决方案
  4. 在javascript中关于局部变量和全局变量简析
  5. CSS3-变换-过渡-动画
  6. c/c++中指针参数如何传递内存!
  7. NG RouteReuseStrategy(路由复用策略)
  8. JAVA-求整数序列中出现次数最多的数
  9. 7-35 情人节 (15 分)
  10. 7-96 福到了 (15 分)