图像去畸变和添加畸变

背景:最近的项目中用到的图像去畸变的知识,刚开始是直接调用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;
}	

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/252283.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win10上编译libharu库

背景&#xff1a; 最近的项目需要自动的生成pdf文件&#xff0c;我在网上查看相关的资料&#xff0c;发现目前比较流行的生成pdf文件的库有两个&#xff0c;一个是libpdf&#xff0c;另一个是libharu。libpdf个人使用时免费的但是商业使用就需要收费了&#xff0c;否则得到的p…

爬虫——正则表达式re模块

为什么要学习正则表达式 实际上爬虫一共就四个主要步骤&#xff1a; 明确目标&#xff1a;需清楚目标网站爬&#xff1a;将所有的目标网站的内容全部爬下来取&#xff1a;在爬下来的网站内容中去掉对我们没有用处的数据&#xff0c;只留取我们需要的数据处理数据&#xff1a;按…

深入Spring Boot:快速集成Dubbo + Hystrix

2019独角兽企业重金招聘Python工程师标准>>> 背景 Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点&#xff0c;从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离&#xff0c;请求缓存和请求打包&#xff…

BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】

题目 有N个节点&#xff0c;标号从1到N&#xff0c;这N个节点一开始相互不连通。第i个节点的初始权值为a[i]&#xff0c;接下来有如下一些操作&#xff1a; U x y: 加一条边&#xff0c;连接第x个节点和第y个节点 A1 x v: 将第x个节点的权值增加v A2 x v: 将第x个节点所在的连通…

opencv图像仿射变换和普通旋转

背景&#xff1a;今天需要对程序生成的图像进行旋转90度和下采样操作&#xff0c;当然还有改变图像类型的操作&#xff0c;就是把原来.png的图像转换为.jpg的图像&#xff0c;主要是我目前使用libharu库&#xff0c;无法成功从本地加载png图像到pdf中去&#xff0c;不得不使用j…

讨厌麻烦的ora 01722无效数字

webservice开发过程中&#xff0c;数据库由原来的oracle改为现在的sql server。然后重新调试&#xff0c;结果报出ora 01722无效数字的错误。 由于连接oracle数据库的时候并没有问题&#xff0c;所以一开始我以为是数据库不同&#xff0c;导致部分数据类型差异&#xff0c;&…

CSS样式:覆盖规则

规则一&#xff1a;由于继承而发生样式冲突时&#xff0c;最近祖先获胜。 CSS的继承机制使得元素可以从包含它的祖先元素中继承样式&#xff0c;考虑下面这种情况: <html><head><title>rule 1</title><style>body {color:black;}p {color:blue;}…

try{}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会 不会被执行,什么时候被执行,在 return 前还是后?...

这是一道面试题&#xff0c;首先finally{}里面的code肯定是会执行的&#xff0c;至于在return前还是后&#xff0c; 看答案说的是在return后执行&#xff0c;我觉得不对&#xff0c;百度了一下&#xff0c;有说return前的&#xff0c;有说return后的&#xff0c;还有return中间…

相机和镜头选型需要注意哪些问题

背景&#xff1a; 最近需要优于项目需求需要对工业相机和镜头进行选型&#xff0c;于是我就开启的学习相机之旅&#xff0c;虽然我一直在做机器视觉方向&#xff0c;但是我对相机的了解还是很少&#xff0c;我想正好趁这次机会好好学习一下。如果有错误的观点请指正。 一、相…

响应式网页布局 - W3Schools How-Tos 01

W3Schools教学系列 W3Schools是知名的网页设计&#xff0f;前端开发教学网站&#xff0c;不仅提供HTML、CSS、JavaScript等的详尽教学&#xff0c;还可以把它当作说明文件&#xff08;Documents&#xff09;。有经验的前端或多或少已经接触过这个网站&#xff0c;因为它经常出现…

正則表達式,终极使用!3个工具,搞定一切

文章前提&#xff0c;本人。不会正则的不论什么语法&#xff0c;仅仅懂一点正则的概念。本人从未自己写过正则&#xff0c;都是网上收罗进行改动的。相同。没有时间去研究正则。 可是为了方便&#xff0c;入手了几个工具。 如今就为大家一一展示。 第一个&#xff0c;regexBuil…

iOS 在tableview的侧滑事件里执行tableView.selectRow无效的解决办法

很奇怪的问题&#xff0c;在执行默认选中一个cell的时候&#xff0c;突然发现这句话不起作用了 &#xff08;我的场景是&#xff1a;当前cell侧滑删除后&#xff0c;默认选中上一个cell&#xff09; 搞了半天&#xff0c;终于发现罪魁祸首竟然是因为&#xff1a;这句话写在了侧…

VS2017 C++工程 执行python脚本

我解决了哪怕很小的一个问题&#xff0c;我也想记录下来来见证我的经历。 背景&#xff1a; 一、使用libhuru库生成pdf报告 最近参与一些测试工作&#xff0c;希望测试结束后能够根据测试得到的数据和图像自动生成测试报告&#xff0c;最开始调研到了生成报告的库有libharu和…

标准正弦波变频电源调制方式的实现

目前变频电源正不断向规模化、专业化、智能化、精细化方向发展。变频电源的技术随着工业电器电子制造的兴起而不断得到重视和发展。其中,中港扬以正弦脉SPWM为核心变频电源系统电路便是一个很好的代表。纯硬件电路在焊接电路上比较复杂&#xff0c;但是调节出来的SPWM波形比较完…

Jmeter教程索引贴

Jmeter教程索引贴 新的一年即将到来&#xff0c;不知不觉2015年自己在Jmeter方面总结的文章有十几篇&#xff0c;在此汇总一下&#xff0c;顺便也算是个总结吧。2016年&#xff0c;继续学习技术&#xff0c;总结&#xff0c;写文章。 一、基础部分&#xff1a; 使用Jmeter进行h…

类与接口(二)java的四种内部类详解

引言 内部类&#xff0c;嵌套在另一个类的里面&#xff0c;所以也称为 嵌套类; 内部类分为以下四种&#xff1a; 静态内部类成员内部类局部内部类匿名内部类一、静态内部类 静态内部类&#xff1a; 一般也称”静态嵌套类“&#xff0c;在类中用static声明的内部类。 因为是stat…

单例设计模式和多线程

单例设计模式 单例&#xff1a;整个项目中&#xff0c;有某个类或者某些特殊的类&#xff0c;属于该类的对象只能建立一个。 #include<iostream> using namespace std;class MyCAS { private:MyCAS(){}private:static MyCAS *m_instance;public:static MyCAS *GetInstanc…

运行imgui例程

背景&#xff1a;目前在做一个视觉测试系统&#xff0c;需要做一个界面&#xff0c;将相机获取的图像&#xff0c;以及测试过程中的数据呈现在界面上&#xff0c;在我印象里&#xff0c;做界面就用qt吧&#xff0c;直到这个月真要开始做界面了&#xff0c;我的领导给我建议用im…

性能测试总结(三)--工具选型篇

性能测试总结(三)--工具选型篇 本篇文章主要简单总结下性能测试工具的原理以及如何选型。性能测试和功能测试不同&#xff0c;性能测试的执行是基本功能的重复和并发&#xff0c;需要模拟多用户&#xff0c;在性能测试执行时需要监控指标参数&#xff0c;同时性能测试的结果不是…

创建一个最简单的imgui测试用例

在上一篇文章中&#xff0c;我们初步认识了一下imgui,并且成功运行了他提供的demo。这只是开始学习imgui的第一步&#xff0c;在实际使用时&#xff0c;我们需要将imgui应用到自己的工程中去&#xff0c;所以你需要具备将imgui加到你工程中去的能力&#xff0c;简单起见&#x…