this demo on github

前言

鱼眼镜头相比传统的镜头,视角更广,采集的图像信息更加丰富,但是如果要对图像进行处理,就需要对其进行展开的操作,理论部分在很多论文中都已经有所提及,已经有比较成熟的方案,也不是什么比较新鲜的事情,笔者在此梳理整体的思路,总结一下所学知识,最后简单实现一下这个功能,如有错误之处,希望各位指正。

理论部分

鱼眼图像的展开涉及到各个坐标系的转换,其过程大致如下图所示,过程还是比较繁琐的,可以想象一下如何将地球仪展开成平面图,可能会比较容易理解一点。

鱼眼展开流程

Created with Raphaël 2.2.0开始设置输出图片尺寸获取输出图片上的单像素点标准坐标A将标准坐标A转换空间坐标P(x,y,z)通过坐标P求出鱼眼标准坐标FishCoord标准坐标FishCoord求出鱼眼图片上对应的坐标结束

鱼眼标准坐标计算

OpenCv读取一张鱼眼图片,其图片数据可以想象成发布在一个2D的笛卡尔坐标中的像素点的集合:x∈[0,cols−1]x \in [ 0,cols-1]x∈[0,cols−1] y∈[0,cols−1]y \in [ 0,cols-1]y∈[0,cols−1]将输入的鱼眼图片坐标换算成标准鱼眼坐标:normalCoord.x=(float)((float)x∗2/cols−1)normalCoord.x = (float)((float)x * 2 / cols - 1 )normalCoord.x=(float)((float)x∗2/cols−1) normalCoord.y=(float)((float)y∗2/rows−1)normalCoord.y = (float)((float)y * 2 / rows - 1 )normalCoord.y=(float)((float)y∗2/rows−1)

鱼眼坐标系相当于球体在一个平面上的2D投影,坐标范围是[ -1, 1],现需要将2D的坐标A(x,y)转化为空间坐标P(x,y,z)

标准坐标系与球坐标的转换

球坐标的表示方式:P(r,θ,ϕ)⋯⋯(1)P(r,\theta,\phi) \cdots\cdots(1)P(r,θ,ϕ)⋯⋯(1)P(p,ϕ,θ)⋯⋯(2)P(p,\phi,\theta) \cdots\cdots(2)P(p,ϕ,θ)⋯⋯(2)

其中(1)为物理中普遍的表示方式,式(2)为数学中约定的表示方式。

ppp :点P与原点O连线的径向距离,下面即用OP表示;

θ\thetaθ :OP与Z轴之间的夹角;

ϕ\phiϕ :OP在XOY平面的投影与正X轴的夹角;**

这里有空间坐标点A(x,y,z)A(x,y,z)A(x,y,z),以下公式将球坐标系P点转换成笛卡尔坐标系:

x=p∗sinθ∗cosϕx = p * sin\theta * cos\phi x=p∗sinθ∗cosϕ y=p∗sinθ∗sinϕy = p * sin\theta * sin \phiy=p∗sinθ∗sinϕ z=p∗cosθz = p * cos\theta z=p∗cosθ

以上公式在图片中未提及,这里提及以加深理解。

代码实现

这里主要贴一下坐标的转换代码,整个项目工程请转到 github

FishEye& FishEye::ImgExpand2()
{
if (mImg.empty()) {
return *this;
}
printf("Current x is (%d ,%d)\n", mImg.cols, mImg.rows); Point2i circleCoord;
circleCoord.x = mImg.cols / 2 + 2;
circleCoord.y = mImg.rows / 2 + 5;
int R = mImg.cols / 2; for (int i = 0; i < mDesImg.cols; i++) {
for (int j = 0; j < mDesImg.rows; j++) { Point2f pointDst = this->Shpere2Fish(i, j);
int cols = (int)((pointDst.x + 1) * mImg.cols / 2);
int rows = (int)((pointDst.y + 1) * mImg.rows / 2);
printf("Current %d %d is (%d, %d) ", i, j, cols, rows);
if (rows < mImg.rows && cols < mImg.cols
&& rows >= 0 && cols >= 0) {
Vec3b color_value = mImg.at<Vec3b>(rows, cols);
mDesImg.at<Vec3b>(j, i) = color_value;
std::cout << color_value << std::endl;
}
}
}
return *this;
} cv::Point2f FishEye::Shpere2Fish(int x, int y)
{
//归一化
Point2f normalCoord;
normalCoord.x = (float)(x * 2.0f / mFishMapImg.cols - 1);
normalCoord.y = (float)(y * 2.0f / mFishMapImg.rows - 1); float longitude = (float)(normalCoord.x * PI);
float latitude = (float)(normalCoord.y * PI/2); Point3f coordP;
coordP.x = cos(latitude)*cos(longitude);
coordP.y = cos(latitude)*sin(longitude);
coordP.z = sin(latitude);
float r = 2 * atan2(sqrt(coordP.x*coordP.x + coordP.z*coordP.z), coordP.y) / MFOV;
float theta = atan2(coordP.z, coordP.x); Point2f fishCoord;
fishCoord.x = r * cos(theta);
fishCoord.y = r * sin(theta); return fishCoord;
}

测试效果如下图

总结

整个过程中,遇到过一个较大的问题,之前一直难以理解。如果先输入一张鱼眼图像,通过鱼眼图像的坐标映射到展开图片,会出现很多像素点缺失的情况,可以测试一下,仓库对应的方法为ImgExpand()。在ImgExpand2中解决了这个问题,是从输出图片的坐标去推算并寻找鱼眼图片上相应的像素点,同样的,还有一些参数需要提取进行接口化的设计。比如提取鱼眼图像的有效区域有效区域半径的计算读取exif获取镜头视角或者预留接口展开图片后的抗锯齿化处理等等,还需要完善,另外有什么问题,望不吝赐教。

OpenCV 经纬法将鱼眼图像展开的更多相关文章

  1. 【图像处理】openCV光流法追踪运动物体

    openCV光流法追踪运动物体 email:chentravelling@163.com 一.光流简单介绍 摘自:zouxy09 光流的概念是Gibson在1950年首先提出来的.它是空间运动物体在观 ...

  2. 【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析(转)

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/20537737 作者:毛星云(浅墨)  ...

  3. (原)使用opencv的warpAffine函数对图像进行旋转

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5070576.html 参考网址: http://stackoverflow.com/questions ...

  4. OpenCV成长之路:图像直方图的应用

    OpenCV成长之路:图像直方图的应用 2014-04-11 13:57:03 标签:opencv 图像 直方图 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否 ...

  5. OpenCV成长之路:图像滤波

    http://ronny.blog.51cto.com/8801997/1394138 OpenCV成长之路:图像滤波 2014-04-11 14:28:44 标签:opencv 边缘检测 sobel ...

  6. OpenCV 鼠标手动绘制掩码图像

    OpenCV 鼠标手动绘制掩码图像 完整的代码: #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui ...

  7. 【opencv学习笔记六】图像的ROI区域选择与复制

    图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...

  8. Python 图像处理 OpenCV (4):图像算数运算以及修改颜色空间

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  9. Python 图像处理 OpenCV (5):图像的几何变换

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

随机推荐

  1. 用Python介绍了企业资产情况的数据爬取、分析与展示。

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:张耀杰 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自 ...

  2. async,await执行流看不懂?看完这篇以后再也不会了

    昨天有朋友在公众号发消息说看不懂await,async执行流,其实看不懂太正常了,因为你没经过社会的毒打,没吃过牢饭就不知道自由有多重要,没生过病就不知道健康有多重要,没用过ContinueWith就 ...

  3. CAS原理解析

    CAS底层原理 概念 CAS的全称是Compare-And-Swap,它是CPU并发原语 它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的 CAS并发原语体现在Jav ...

  4. Java中Random类

    Random:产生随机数的类 构造方法: public Random();没有给种子,用的是默认种子,是当前时间的毫秒值. public Random(long seed);给出指定的种子 //给定种 ...

  5. 基于 HTML WebGL 的会展中心智能监控系统

    前言 随着近几年物联网.万物互联等诸多概念的大行其道,智慧城市的概念也早已经被人们耳熟能详,而作为城市的组成部分,智慧建筑也是重中之重,智慧园区,智慧小区等也如雨后春笋般的相继出现. 智慧建筑是指通过 ...

  6. 好用的反向代理工具NATAPP

    这里推荐一个好用的反向代理工具NATAPP NATAPP1分钟快速新手图文教程 有免费的和付费的个人建议付费的,免费还需要身份证验证,付费版最低9元/月,看个人需求! 这里给个邀请码贴在这需要的话可以 ...

  7. centos7下端口映射

    firewall-cmd --zone=external --add-forward-port=port=:proto=tcp:toport=:toaddr=192.168.10.10 --perma ...

  8. Docker help详细帮助

    常用的 docker 命令 docker # docker 命令帮助 Commands: attach Attach to a running container # 当前 shell 下 attac ...

  9. 多线程并行请求问题及SplashActivity预加载问题解决方案

    1. 问题描述(一): 现有3个线程thread1, thread2, thread3.这3个线程是并发执行的,当着3个线程都执行完成以后,需要执行一个finish()事件. 1.1 实现方法: /* ...

  10. js 实现淘宝放大镜功能,可更改配置参数 带完整版解析代码[magnifier.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝放大镜效果 基本功能: 运 ...