我为中国第一张火星照片做鱼眼矫正

点击下方卡片,关注“CVer”公众号

AI/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_y
int 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;
}

论文PDF和代码下载

后台回复:火星,即可下载上述代码

后台回复:CVPR2021,即可下载CVPR 2021论文和代码开源的论文合集

后台回复:Transformer综述,即可下载最新的两篇Transformer综述PDF

CVer-Transformer交流群成立
扫码添加CVer助手,可申请加入CVer-Transformer 微信交流群,方向已涵盖:目标检测、图像分割、目标跟踪、人脸检测&识别、OCR、姿态估计、超分辨率、SLAM、医疗影像、Re-ID、GAN、NAS、深度估计、自动驾驶、强化学习、车道线检测、模型剪枝&压缩、去噪、去雾、去雨、风格迁移、遥感图像、行为识别、视频理解、图像融合、图像检索、论文投稿&交流、PyTorch和TensorFlow等群。
一定要备注:研究方向+地点+学校/公司+昵称(如Transformer+上海+上交+卡卡),根据格式备注,可更快被通过且邀请进群
▲长按加小助手微信,进交流群▲点击上方卡片,关注CVer公众号
整理不易,请给CVer点赞和在看
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值