优化鱼眼相机图像去畸变:边缘保留与OpenCV实践

1. 鱼眼去畸变,为什么你的图像边缘总在“消失”?

如果你玩过鱼眼相机,或者在做机器人、车载环视、VR项目,肯定遇到过这个头疼的问题:好不容易把鱼眼图像校正得不那么“鼓”了,结果一看,图片四周被切掉了一大圈,关键的边缘信息全没了!我刚开始做视觉项目时,也在这个坑里摔过好几次。比如做车位检测,车旁边的角标刚好在图像边缘,一校正,角标没了,算法直接“瞎了”。这感觉就像你费劲修好了一幅画,结果画框把画的内容裁掉了一半,非常让人沮丧。

这个问题的根源,其实就藏在 cv::remap 这个核心函数里。简单来说,去畸变的过程,就是为校正后的图像上每一个“规整”的像素点,在原始鱼眼图像上找到它“扭曲”前的位置,然后把那个位置的像素值拿过来。你可以把它想象成一张“寻宝地图”(映射图 map1 和 map2),地图上标明了“宝藏”(像素)在原始图像中的坐标。但是,鱼眼镜头边缘的畸变非常严重,当算法试图把这些严重扭曲的边缘像素“拉直”回正常位置时,计算出的原始坐标往往会超出原始图像的边界remap 函数遇到这种“地图坐标指向界外”的情况,通常的处理方式就是直接填一个默认值(比如黑色),这就导致了我们看到的黑边和边缘信息丢失。

所以,常规的 cv::fisheye::initUndistortRectifyMap 配合 cv::remap 流程,默认产出的是一张和原图尺寸完全相同的去畸变图。它为了保证输出图像每个位置都有值,只能牺牲那些映射到界外的像素。这就像你用固定大小的相框去装一张被拉伸过的照片,为了把照片全装进去,你只能把拉伸出去的部分剪掉。理解了这个底层逻辑,我们才能有的放矢地去优化,目标很明确:既要中心区域校正得完美,又要尽可能多地保住边缘的像素。

2. 初探优化:一个“简单”却错误的扩边思路

面对边缘丢失,我最初的想法和很多人一样,非常直接:既然像素跑出去了是因为原图“不够大”,那我把原图边界扩大一圈,给那些“跑出去”的像素留出空间不就行了?这个思路听起来合情合理,而且 OpenCV 正好提供了 cv::copyMakeBorder 这个方便的扩边函数。我当时兴致勃勃地试了一把,具体操作是这样的:

首先,我把原图的高和宽各增加了 1/2(即上下各扩高度的1/4,左右各扩宽度的1/4)。这样,新图像的尺寸就变成了原来的 1.5 倍。这里有个关键细节:图像扩大了,但相机内参矩阵 K 并不是一成不变的。内参矩阵里的 cxcy 代表的是光心在图像像素坐标系中的位置。原图中心点坐标是 (cx, cy),现在图像整体变大了,中心点的像素坐标自然也变了。因为我是均匀扩边,中心点相对于新图像的位置比例没变,但绝对坐标值变成了原来的 1.5 倍。所以,我需要同步更新内参矩阵,将 cx 和 **cy` 乘以 1.5。

// 原始内参
cv::Mat K = (cv::Mat_<double>(3, 3) << 652.86, 0, 1262.10, 0, 653.19, 928.09, 0, 0, 1);
// 扩边后的新内参(注意cx, cy的变化)
cv::Mat K_new = (cv::Mat_<double>(3, 3) << 652.86, 0, 1.5*1262.10, 0, 653.19, 1.5*928.09, 0, 0, 1);

cv::Mat expanded_image;
// 上下左右各扩原图尺寸的1/4
int top = raw_image.rows / 4;
int bottom = raw_image.rows / 4;
int left = raw_image.cols / 4;
int right = raw_image.cols / 4;
cv::copyMakeBorder(raw_image, expanded_image, top, bottom, left, right, cv::
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值