相机去畸变,以及双目平行校正----极线校正(二)————之双目平行校正详细过程

本文介绍了一种双目相机平行校正的方法,包括去畸变和平行校正的具体步骤。通过对左、右相机坐标系的旋转操作实现平行校正,并提供了编程实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过相机标定的程序获取了两个相机各自的内参矩阵和畸变系数,以及两个相机达到平行时各自的旋转矩阵。 Opencv Matlab 都给了我们现成的函数,可以利用这些数据进行去畸变或者双目平行校正,因为有需求要将去畸变和平行校正移植到硬件上,那么自己如何利用这些参数和矩阵写去畸变的程序和双目平行校正的程序呢?我本人发现的网上这方面资料较少。在此总结一下。

去畸变的过程就是针对单目相机进行的变换,平行校正就是针对双目相机的操作。


本文针对双目平行校正的方法展开叙述:


做双目平行校正时,是已经通过相机标定获取了左、右相机的内参矩阵和畸变系数,以及左、右相机达到平行时各需要的旋转矩阵,另外,已知左右两个相机拍摄出来的两幅图片。

注:这里双目相机各参数标定是通过左右相机拍摄的15对棋盘格图像,通过opencv双目标定程序获取的。

内参矩阵:


畸变系数:

旋转矩阵:


构建一个两个相机共同的理想内参矩阵:

即:


双目平行校正,它是在左、右相机去畸变的过程中对左、右相机坐标系分别多进行了一步旋转操作。它的操作步骤如下:


1),分别将两个图像的像素坐标系通过共同的内参矩阵转换到相机坐标系:


2),分别对两个相机坐标系进行旋转得到新的相机坐标系。通过左乘旋转矩阵R1R2


3),针对新的相机坐标分别进行左、右相机的去畸变操作。


4),去畸变操作结束后,分别用左、右相机的内参矩阵将左、右两个相机坐标系重新转换到左、右图像像素坐标系。


5),并分别用左、右源图像的像素值对新左、右图像的像素点进行插值。


编程实例:


左右相机拍摄的图像:


左:


              



右:


                              


共同显示:


             


左摄像头处理程序:

  1. f1=1;%焦距倍数  
  2. gama=0;  
  3. for x=1:W1 %640  
  4.     for y=1:H1  %480  
  5.         yy=(y-cy)/fy;%转换到相机坐标系  
  6.         xx=(x-cx-gama*yy)/fx;  
  7.         pos=[xx;yy;f1]; %3x1  
  8.         pos=inv(R1)*pos; %旋转相机坐标系,3x1  
  9.         xx=pos(1,:)/pos(3,:);%归一化  
  10.         yy=pos(2,:)/pos(3,:);  
  11.         r=xx^2+yy^2;  
  12.         xxx=xx*(1+k11*r+k12*r^2+k13*r^3)+2*p11*xx*yy+p12*(r+2*xx^2);  
  13.         yyy=yy*(1+k11*r+k12*r^2+k13*r^3)+2*p12*xx*yy+p11*(r+2*yy^2);  
  14.         xxxx=xxx*fx1+cx1;  
  15.         yyyy=yyy*fy1+cy1;  
  16.         if (xxxx>1 && xxxx<=W1 && yyyy>1 && yyyy<=H1)  
  17.             h=yyyy;  
  18.             w=xxxx;  
  19.             I11(y,x)=(floor(w+1)-w)*(floor(h+1)-h)*I1(floor(h),floor(w))+(floor(w+1)-w)*(h-floor(h))*I1(floor(h+1),floor(w))+(w-floor(w))*(floor(h+1)-h)*I1(floor(h),floor(w+1))+(w-floor(w))*(h-floor(h))*I1(floor(h+1),floor(w+1));  
  20.         end  
  21.     end  
  22. end  


右摄像头处理程序:

  1. f2=1;%焦距  
  2. gama=0;  
  3. for x=1:W1 %640  
  4.     for y=1:H1  %480  
  5.         yy=(y-cy)/fy;%转换到相机坐标系  
  6.         xx=(x-cx-gama*yy)/fx;  
  7.         pos=[xx;yy;f2]; %3x1  
  8.         pos=inv(R2)*pos; %旋转相机坐标系,3x1  
  9.         xx=pos(1,:)/pos(3,:);%归一化  
  10.         yy=pos(2,:)/pos(3,:);  
  11.         r=xx^2+yy^2;  
  12.         xxx=xx*(1+k21*r+k22*r^2+k23*r^3)+2*p21*xx*yy+p22*(r+2*xx^2);  
  13.         yyy=yy*(1+k21*r+k22*r^2+k23*r^3)+2*p22*xx*yy+p21*(r+2*yy^2);  
  14.         xxxx=xxx*fx2+cx2;  
  15.         yyyy=yyy*fy2+cy2;  
  16.         if (xxxx>1 && xxxx<=W2 && yyyy>1 && yyyy<=H2)  
  17.             h=yyyy;  
  18.             w=xxxx;     I22(y,x)=(floor(w+1)-w)*(floor(h+1)-h)*I2(floor(h),floor(w))+(floor(w+1)-w)*(h-floor(h))*I2(floor(h+1),floor(w))+(w-floor(w))*(floor(h+1)-h)*I2(floor(h),floor(w+1))+(w-floor(w))*(h-floor(h))*I2(floor(h+1),floor(w+1));  
  19.         end  
  20.     end  
  21. end  

经过去畸变和平行校正处理后的图像:


平行放置并划线对比显示可见,两幅图像已经达到极线平行:



注意:原文链接http://blog.youkuaiyun.com/wangxiaokun671903/article/details/38017055

### 关于双目相机极线校正的代码实现 #### OpenCV Python 实现 为了执行双目相机极线校正,可以利用 `cv2.stereoRectify` 函数来计算用于使两幅图像对准同一平面所需的变换矩阵。下面给出一段基于Python的示例代码: ```python import numpy as np import cv2 # 假设已经获取了内参矩阵 K1,K2 和畸变系数 D1,D2 以及旋转和平移向量 R,t K1 = ... # 左侧相机内参数矩阵 D1 = ... # 左侧相机畸变系数 K2 = ... # 右侧相机内参数矩阵 D2 = ... # 右侧相机畸变系数 R = ... # 相机之间的相对旋转关系 t = ... # 相机之间沿光轴方向的距离矢量 img_size = (width, height) # 计算重映射所需的地图 R1, R2, P1, P2, Q, roi_left, roi_right = \ cv2.stereoRectify(K1, D1, K2, D2, img_size, R, t) mapx1, mapy1 = cv2.initUndistortRectifyMap(K1, D1, R1, P1, img_size, cv2.CV_32FC1) mapx2, mapy2 = cv2.initUndistortRectifyMap(K2, D2, R2, P2, img_size, cv2.CV_32FC1) # 应用重映射函数到原始图像上得到校正后的图像 left_rectified = cv2.remap(left_img, mapx1, mapy1, interpolation=cv2.INTER_LINEAR) right_rectified = cv2.remap(right_img, mapx2, mapy2, interpolation=cv2.INTER_LINEAR) ``` 这段程序首先通过调用 `stereoRectify()` 来获得两个新的投影矩阵P1和P2,它们定义了一个理想化的平行视图几何结构;接着创建两张映射表(map),最后再使用这些映射表去修正输入图片中的像素位置。 #### C++ 实现 对于C++版本来说,逻辑几乎相同,只是语法有所区别: ```cpp #include <opencv2/opencv.hpp> using namespace cv; // 定义变量存储内外参数... Mat K1, D1, K2, D2; Vec3d R, T; Size imageSize(width,height); // 调用 stereoRectify() 获取必要的转换矩阵 Mat R1,R2,P1,P2,Q; Rect validRoi[2]; stereoRectify(K1, D1, K2, D2, imageSize, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 1, imageSize, &validRoi[0], &validRoi[1]); // 初始化未失真矩形化映射 Mat map11,map12,map21,map22; initUndistortRectifyMap(K1, D1, R1, P1, imageSize, CV_16SC2, map11, map12); initUndistortRectifyMap(K2, D2, R2, P2, imageSize, CV_16SC2, map21, map22); // 对左右图像进行重新映射操作 Mat rImgL,rImgR; remap(imgL, rImgL, map11, map12, INTER_LINEAR); remap(imgR, rImgR, map21, map22, INTER_LINEAR); ``` 上述过程实现了从原始采集的数据中去除镜头扭曲效应并调整视角使得两条基线上所有的对应点都位于同一条水平直线上[^1]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值