背景:最近的项目中用到的图像去畸变的知识,刚开始是直接调用opencv中提供的函数cv::initUndistortRectifyMap()和cv::remap()函数,实现图像的全局去畸变,但是由于图像的分辨率很高,再加上,实际过程中我们只用到了很小一块的图像,所以为了降低电脑的负担,则想选用局部图像去畸变的方法来代替全局图像去畸变。

于是我想到了《SLAM十四讲》书中在相机模型中有相关的去畸变的代码,我就直接使用测试了,效果还不错。

void LocalZoneUndistortion(cv::Mat& localImage, cv::Mat& undistortLocalImage) {undistortLocalImage = cv::Mat(localImage.rows, localImage.cols, CV_8UC1);for (int row = 0; row < localImage.rows; ++row) {for (int col = 0; col < localImage.cols; ++col) {double x = (col - cx_) / fx_;double y = (row - cy_) / fy_;double r = sqrt(x * x + y * y);double xDistorted = x * (1 + k1_ * r * r + k2_ * r * r * r * r) + 2 * p1_* x * y + p2_ * (r * r + 2 * x * x);double yDistorted = y * (1 + k1_ * r * r + k2_ * r * r * r * r) + p1_ * (r * r + 2 * y * y) + 2 * p2_* x * y;double uDistorted = fx_ * xDistorted + cx_;double vDistorted = fy_ * yDistorted + cy_;if (uDistorted  >= 0 && vDistorted >= 0 && uDistorted < localImage.cols && vDistorted < localImage.rows) {undistortLocalImage.at<uchar>(row, col) = localImage.at<uchar>((int)vDistorted,(int)uDistorted);}else {undistortLocalImage.at<uchar>(row, col) = 0;} }}}

当然在使用的时候要把相机内参和畸变系数传进去呦,我这里是把它们定义为成员变量,就没有传进去。其实我之前一直对这个去畸变的过程很困惑的,这明明是一个添加畸变的过程,为啥可以达到去畸变的效果呢?时隔多日之后再次使用这个函数,其实我还是没怎么关心她背后的逻辑,直到我同时又需要完成对点添加畸变的任务,这个时候我才重新审视这两个过程背后的逻辑。

添加畸变的函数如下

void Tracking::DistortPoints(cv::Point2f& undistPoint, cv::Point2f& distPoint) {double x = (undistPoint.x - cx_) / fx_;double y = (undistPoint.y - cy_) / fy_;double r2 = x * x + y * y;// Radial distorsiondouble xDistort = x * (1 + k1_ * r2 + k2_ * r2 * r2 + k3_ * r2 * r2 * r2);double yDistort = y * (1 + k1_ * r2 + k2_ * r2 * r2 + k3_ * r2 * r2 * r2);// Tangential distorsionxDistort = xDistort + (2 * p1_ * x * y + p2_ * (r2 + 2 * x * x));yDistort = yDistort + (p1_ * (r2 + 2 * y * y) + 2 * p2_ * x * y);// Back to absolute coordinates.xDistort = xDistort * fx_ + cx_;yDistort = yDistort * fy_ + cy_;distPoint = cv::Point2f((float)xDistort, (float)yDistort);};

我们平时遇到的都是将带有畸变的点转换为不带畸变的点,很少会遇到在不带畸变的点上添加畸变,因为我要在一个带有畸变的图像上标注一个不带畸变的点,那标注出的位置和我们真正的目标之间就有一定的偏差了,这个时候只有在这些不带畸变的点上添加上畸变,这样才能适应带有畸变的图像。

我们可以发现,上面两个过程,去畸变和添加畸变刚开始的部分都是在添加畸变的过程,

首先是将像素位置点,从像平面内转换到归一化平面内,

double x = (col - cx_) / fx_;
double y = (row - cy_) / fy_;
double x = (undistPoint.x - cx_) / fx_;
double y = (undistPoint.y - cy_) / fy_;

然后再分别添加,径向畸变和切向畸变,

// Radial distorsion
double xDistort = x * (1 + k1_ * r2 + k2_ * r2 * r2 + k3_ * r2 * r2 * r2);
double yDistort = y * (1 + k1_ * r2 + k2_ * r2 * r2 + k3_ * r2 * r2 * r2);// Tangential distorsion
xDistort = xDistort + (2 * p1_ * x * y + p2_ * (r2 + 2 * x * x));
yDistort = yDistort + (p1_ * (r2 + 2 * y * y) + 2 * p2_ * x * y);

然后在把点转换到像平面内。

// Back to absolute coordinates.
xDistort = xDistort * fx_ + cx_;
yDistort = yDistort * fy_ + cy_;

以上这些步骤两个过程是一样的,最后一步是不一样的。

在去畸变过程中,我们相当于给不带畸变的坐标PointA添加畸变,得到带有畸变的点PointB,而这正是我们直接获取得到的带有畸变的图像I上的点,这个时候我们可以将带有畸变的图像上的PointB位置处的灰度值映射赋值给PointA的位置处,这样操作图像I上所有有效点,就完成了对带有畸变的图像I的去畸变操作。

if (uDistorted  >= 0 && vDistorted >= 0 && uDistorted < localImage.cols && vDistorted < localImage.rows) {undistortLocalImage.at<uchar>(row, col) = localImage.at<uchar>((int)vDistorted,(int)uDistorted);
} else {undistortLocalImage.at<uchar>(row, col) = 0;
}   

而添加畸变的过程就比较好理解了,就是给不带有畸变的点添加上径向畸变和切向畸变,直接得到带畸变的点。

图像去畸变和添加畸变相关推荐

  1. 图像去畸变矫正及双线性内插法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 通过采集的图像我们可以得到畸变后的图像,要得到没有畸变的图像要通过畸变模型推导其映射关系. 真实图像 ...

  2. 超实用!图像去畸变矫正及双线性内插法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 通过采集的图像我们可以得到畸变后的图像,要得到没有畸变的图像要通过畸变模型推导其映射关系. 真实图像 ...

  3. 根据相机内参进行图像去畸变

    cv::Mat img; cv::Mat img_undistort; double fx,fy, cx, cy, k1, k2, p1, p2, k3;for(int v = 0; v < i ...

  4. opencv 图像添加畸变

    opencv 图像添加畸变 因为需要对相机标定效果进行评价,首先要制作一张有畸变的标定板图片.可是opencv对图片只能去畸变,没有直接添加畸变的方法. 基于畸变公式可以对求得畸变后的点的坐标.本文的 ...

  5. OpenCV 【十一】—— 图像去畸变,对极约束之undistort,initUndistortRectifyMap,undistort

    目录 0.极限约束,对极校正 1.摄像机成像原理简述 2.成像畸变 2.1. 畸变数学模型 2.2. 公式推导 3.畸变校正 3.1. 理论推导 4. 图像去畸变** 5. 图像尺度缩放与内参的关系* ...

  6. 计算机视觉:Opencv图像去畸变

    计算机视觉:Opencv图像去畸变 针孔相机模型图像去畸变 方法一 方法二 区别与联系 鱼眼相机模型图像去畸变 方法一 方法二 区别与联系 参考文献 针孔相机模型图像去畸变 针对畸变参数,k1,k2, ...

  7. opencv图像去畸变

    图像去畸变的思路 对于目标图像(无畸变图像)上的每个像素点,转换到normalize平面,再进行畸变变换,进行投影,得到这个像素点畸变后的位置,然后将这个位置的源图像(畸变图像)的像素值作为目标图像该 ...

  8. 基于MATLAB的图像去雾系统

    基于MATLAB的图像去雾系统 (一)图像去雾基础原理 1.雾霭的形成机理 雾实际上是由悬浮颗粒在大气中的微小液滴构成的气溶胶,常呈现乳白色,其底部位于地球表面,所以也可以看作是接近地面的云.霭其实跟 ...

  9. matlab图像去雾实现

    目录 一.课题意义 1 (一)研究意义 1 (二)研究现状 1 二.相关知识 4 (一)系统功能及简介: 4 (二)用到的知识 5 三.系统设计与实现 5 (一)实现条件 5 硬件条件:计算机 5 软 ...

最新文章

  1. Linux复制文件scp
  2. 关于Silverlight安装问题之二
  3. 分析师洞察:边缘数据中心的UPS系统
  4. Axure RP一个专业的快速界面原型设计工具
  5. 神经网络入门-MLP, RNN, BiRNN
  6. Centos7 install firefox-china
  7. java配置文件放置到jar外_java相关:Spring Boot 把配置文件和日志文件放到jar外部...
  8. Node — 第一天
  9. windows 系统监视器_使用Windows 7中的可靠性监视器对计算机问题进行故障排除
  10. Windows 如何用命令终端(CMD)启动和停止 MySQL 数据库服务
  11. python取文本中间_Python读取两个字符串之间的特定文本行
  12. 剑指Offer - 面试题9. 用两个栈实现队列
  13. 迭代器协议、斐波那契数列
  14. Android Activity(一)Activity间的跳转
  15. 用Python搭建股票舆情分析系统
  16. 面试记录五:腾讯后台研发
  17. 详解哈夫曼树和哈夫曼编码
  18. python怎么调用外部软件_python调用其他程序
  19. 情绪管理---第二课:情绪包含四方面的反应
  20. 使用UE4开发VR项目_性能优化(三)_思路和方法

热门文章

  1. Inside the C++ Object Model | Outline
  2. 3DMax插件和它的3DXI接口
  3. [开发手记] 使用.NET实现你的IP切换器
  4. 怎样在PHP中通过ADO调用Asscess数据库和COM程序
  5. Promise 的基本使用 与 Ajax的jQuery封装
  6. 关于Unity中NGUI的背包实现之Scrollview(基于Camera)
  7. SDL 库 无法解析的外部符号 __imp__fprintf
  8. iOS 开发者账号共用发布证书 (Distribution)问题
  9. Spring的bean实例化过程
  10. es6 --- 自制迭代器