立体视觉 -- 相机畸变矫正(去畸变)

相机畸变矫正

在双目立体视觉中,常常会使用张正友的相机标定方法,得到相机的参数(相机内参和畸变),进而矫正由于相机透镜制造工艺等因素造成的图像畸变。在Opencv 和 Matlab 中都有封装好的函数或者标定工具箱供我们使用,可以利用这些标定得到的数据进行畸变矫正。

重点来了!!!怎么自己编写呢?且看下方讲解。。

  • 内参矩阵
A = [fx, 0, cx; 0, fy, cy; 0, 0, 1]
  • 畸变系数
D = [k1, k2, p1, p2, k3](通常没有k3)
  • 参数说明
fx = f/dx;
fy = f/dy;

1、dx和dy是相机单个感光单元芯片的长度和宽度,是一个物理尺寸,有时候会有dx=dy,这时候感光单元是一个正方形;
2、cx和cy分别代表相机感光芯片的中心点在x和y方向上可能存在的偏移;
3、f代表相机的焦距;
4、k1, k2, k3为径向畸变系数;
5、p1, p2为切向畸变系数。

  • 去畸变步骤

1、先将图像像素坐标系转换到相机坐标系

x_w = (x-cx)/fx;
y_w = (y-cy)/fy; 

2、在相机坐标系中做去畸变

r = x_w^2 + y_w^2;
x_w1 = x_w*(1 + k1*r + k2*r^2 + k3*r^3) + 2*p1*x_w*y_w + p2*(r + 2*x_w^2);
y_w1 = y_w*(1 + k1*r + k2*r^2 + k3*r^3) + 2*p2*x_w*y_w + p1*(r + 2*y_w^2);

3、去畸变后重新将相机坐标系转换到图像像素坐标系

x_p = x_w1*fx + cx;
y_p = y_w1*fy + cy;

4、使用源图像对新图像插值

w = x_p; 
h = y_p; 
I1(y, x) = ([w+1]-w)*([h+1]-h)*I([h],[w])+
([w+1]-w)*(h-[h])*I([h+1],[w])+
(w-[w])*([h+1]-h)*I([h],[w+1])+
(w-[w])*(h-[h])*I([h+1],[w+1])+

注:[]表示取整,I1为矫正后图像,I为源图像。

  • 矫正结果
    矫正前后图像(左:源图像;右:校正后图像)
  • 3
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是使用Visual Studio 2017和OpenCV 4.5.2进行双目视觉矫正的示例代码,其中将畸变系数直接写入代码: ```cpp #include <> #include <opencv2/opencv.hpp> int main() { // 读取左右相机图像 cv::Mat imgLeft = cv::imread("left.png", cv::IMREAD_GRAYSCALE); cv::Mat imgRight = cv::imread("right.png", cv::IMREAD_GRAYSCALE); // 定义立体匹配算法参数 int numDisparities = 16; // 视差范围 int blockSize = 15; // 匹配块大小 // 创建立体匹配对象 cv::Ptr<cv::StereoBM> stereo = cv::StereoBM::create(numDisparities, blockSize); // 计算视差图 cv::Mat disparity; stereo->compute(imgLeft, imgRight, disparity); // 进行立体矫正 cv::Mat Q; // 重投影矩阵 cv::Mat R1, R2, P1, P2; // 矫正变换矩阵 cv::Mat map1x, map1y, map2x, map2y; // 矫正映射表 // 定义相机的内参和畸变系数 cv::Mat cameraMatrix1 = (cv::Mat_<double>(3, 3) << fx1, 0, cx1, 0, fy1, cy1, 0, 0, 1); cv::Mat distCoeffs1 = (cv::Mat_<double>(1, 5) << k1_1, k2_1, p1_1, p2_1, k3_1); cv::Mat cameraMatrix2 = (cv::Mat_<double>(3, 3) << fx2, 0, cx2, 0, fy2, cy2, 0, 0, 1); cv::Mat distCoeffs2 = (cv::Mat_<double>(1, 5) << k1_2, k2_2, p1_2, p2_2, k3_2); // 进行双目矫正 cv::stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imgLeft.size(), R, T, R1, R2, P1, P2, Q); // 生成矫正映射表 cv::initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R1, P1, imgLeft.size(), CV_32FC1, map1x, map1y); cv::initUndistortRectifyMap(cameraMatrix2, distCoeffs2, R2, P2, imgRight.size(), CV_32FC1, map2x, map2y); // 应用矫正映射表进行立体矫正 cv::Mat imgLeftRect, imgRightRect; cv::remap(imgLeft, imgLeftRect, map1x, map1y, cv::INTER_LINEAR); cv::remap(imgRight, imgRightRect, map2x, map2y, cv::INTER_LINEAR); // 显示立体矫正后的图像和视差图 cv::imshow("Left Rectified", imgLeftRect); cv::imshow("Right Rectified", imgRightRect); cv::imshow("Disparity", disparity); cv::waitKey(0); return 0; } ``` 请将代码中的`left.png`和`right.png`替换为实际的左右相机图像路径。此外,还需要根据实际情况填写相机的内参和畸变系数。这些参数可通过相机标定程序获得。 希望这对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值