我为中国火星第一图做鱼眼矫正(附代码)

极市平台

共 4078字,需浏览 9分钟

 ·

2021-05-25 10:46

↑ 点击蓝字 关注极市平台

作者丨于仕琪
来源丨于仕琪
编辑丨极市平台

极市导读

 

作者使用了C++和OpenCV库,纯手工制作,逐个像素计算和搬运将中国火星的第一张鱼眼变形修正,附有相关代码。 >>加入极市CV技术交流群,走在计算机视觉的最前沿

以下是昨日发布的内容。今天把代码整理了一下,放到GitHub。包含注释和空行,C++代码一共70行,欢迎测试及指正!

代码链接:https://github.com/ShiqiYu/mars-fisheye-correct

2021年5月19日18点多,中国火星探测器拍摄的第一张图片在互联网上发布。图片是火星车的前避障相机拍摄,为了追求广角,所以拍到的照片有鱼眼变形。火星地面成了曲面,而非平面,如下图。

作为一名计算机视觉的从业人员,我觉得应该用自己的知识做点什么。晚上陪孩子游泳回家就9点多了,马上动手!

为了表达敬意,不能用现成的程序来做这个事,我选择了C++和OpenCV库,纯手工制作,逐个像素计算和搬运!大约花了30分钟,矫正结果出来了,如下图。可以看到火星地平面变平了!

鱼眼矫正的原理图需要理解摄像机的小孔成像模型,以及了解一点立体几何知识,高中数学足够。成像原理示意图如下,然后再动手写个程序就可以了。

上图来自论文:Chan, Sixian & Zhou, Xiaolong & Huang, Chengbin & Chen, Shengyong & Li, Youfu. (2016). An improved method for fisheye camera calibration and distortion correction. 579-584. 10.1109/ICARM.2016.7606985.

为了更让大家更容易地理解鱼眼镜头成像,我手绘了如下示意图,时间仓促有点简陋,望谅解。

70行C++代码如下:

#include <opencv2/opencv.hpp>using namespace cv;using namespace std;// map the fisheye image position to the rectilinear image position// input:  src_x, src_y, center_x, center_y, R,// output: dst_x, dst_yint rectxy2fisheyexy(double src_x, double src_y,             double *dst_x, double *dst_y,            double center_x, double center_y,            int image_width,            double R){  double phi;  double theta;  double D = sqrt( R * R - image_width*image_width/4);
src_x -= center_x; src_y -= center_y;
phi = atan( sqrt( double(src_x*src_x+src_y*src_y))/ D ); theta = atan2(src_y, src_x);
*dst_x = R * sin(phi) * cos(theta) + center_x; *dst_y = R * sin(phi) * sin(theta) + center_y;
return 0;}int main(int argc, char ** argv){ if(argc != 2) { cout << "Usage: " << argv[0] << " filename.jpg" << endl; return -1; } // read a fisheye image Mat input = imread(argv[1]); if(input.empty()) { cerr << "Cannot read input image file " << argv[1] << endl; return -1; } double fisheye_radius = 1500; //you can adjust the parameter in range [1500, +INF] int input_width = input.cols; int input_height = input.rows; // the output image is 1.25x large int output_width = cvRound(input_width*1.25); int output_height = cvRound(input_height*1.25); Mat output(output_height, output_width, input.type(), Scalar(0,0,0)); // copy each pixel from the fisheye image // the current implementation is using NN // bilinear interpolation can make the result more smooth for ( int r = 0; r < output.rows; r++) for ( int c = 0; c < output.cols; c++) { double src_r = 0; double src_c = 0; rectxy2fisheyexy(c-(output_width-input_width)/2 , r-(output_height-input_width)/2, &src_c, &src_r, input_width/2.0, input_height/2.0, input_width, fisheye_radius); // copy the current pixel if it's in the range if ( src_r > 0 && src_r < input_height-1 && src_c > 0 && src_c < input_width-1) //using pointer nor at() functioin can gain better performance output.at<Vec3b>(r, c) = input.at<Vec3b>( cvRound(src_r), cvRound(src_c)); } // save the result and show it in a window imwrite("result.jpg", output); imshow("result", output); waitKey(0); return 0;}

如果觉得有用,就请分享到朋友圈吧!

△点击卡片关注极市平台,获取最新CV干货

公众号后台回复“83”获取朱思语:基于深度学习的视觉稠密建图和定位~


极市干货
YOLO教程:一文读懂YOLO V5 与 YOLO V4大盘点|YOLO 系目标检测算法总览全面解析YOLO V4网络结构
实操教程:PyTorch vs LibTorch:网络推理速度谁更快?只用两行代码,我让Transformer推理加速了50倍PyTorch AutoGrad C++层实现
算法技巧(trick):深度学习训练tricks总结(有实验支撑)深度强化学习调参Tricks合集长尾识别中的Tricks汇总(AAAI2021
最新CV竞赛:2021 高通人工智能应用创新大赛CVPR 2021 | Short-video Face Parsing Challenge3D人体目标检测与行为分析竞赛开赛,奖池7万+,数据集达16671张!


CV技术社群邀请函 #

△长按添加极市小助手
添加极市小助手微信(ID : cvmart2)

备注:姓名-学校/公司-研究方向-城市(如:小极-北大-目标检测-深圳)


即可申请加入极市目标检测/图像分割/工业检测/人脸/医学影像/3D/SLAM/自动驾驶/超分辨率/姿态估计/ReID/GAN/图像增强/OCR/视频理解等技术交流群


每月大咖直播分享、真实项目需求对接、求职内推、算法竞赛、干货资讯汇总、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企视觉开发者互动交流~



觉得有用麻烦给个在看啦~  
浏览 53
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报