介绍相机模型、去畸变【附示例C++代码】

介绍相机模型、去畸变【附示例C++代码】

相机模型

介绍

以针孔相机模型为例,介绍一下相机模型:

假设相机坐标系和世界坐标系之间的转换关系为:
[ u v 1 ] = [ f x 0 c x 0 f y c y 0 0 1 ] [ r 11 r 12 r 13 t 1 r 21 r 22 r 23 t 2 r 31 r 32 r 33 t 3 0 0 0 1 ] [ X w Y w Z w 1 ] \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix} uv1 = fx000fy0cxcy1 r11r21r310r12r22r320r13r23r330t1t2t31 XwYwZw1

其中, ( u , v ) (u,v) (u,v)是成像平面上的像素坐标, ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)是场景中的一个点的世界坐标, f x f_x fx f y f_y fy是相机的焦距, c x c_x cx c y c_y cy是成像平面的中心点坐标, r 11 , r 12 , r 13 , r 21 , r 22 , r 23 , r 31 , r 32 , r 33 r_{11},r_{12},r_{13},r_{21},r_{22},r_{23},r_{31},r_{32},r_{33} r11,r12,r13,r21,r22,r23,r31,r32,r33 t 1 , t 2 , t 3 t_1,t_2,t_3 t1,t2,t3是相机的外参参数, [ R ∣ t ] [R|t] [Rt]是相机的变换矩阵。

注意,右边做了矩阵变换之后维度为4×1,去掉最后的1,变为3×1,这个时候再做相机模型的变换,进一步表示:

[ u v 1 ] = [ f x 0 c x 0 f y c y 0 0 1 ] [ X Y Z ] \begin{bmatrix}u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}X \\ Y \\ Z \end{bmatrix} uv1 = fx000fy0cxcy1 XYZ

其中, ( u , v ) (u,v) (u,v) 是像素坐标系中的点, ( X , Y , Z ) (X,Y,Z) (X,Y,Z) 是相机坐标系中的点, f x f_x fx f y f_y fy 是相机的焦距, c x c_x cx c y c_y cy 是图像中心的坐标。

去畸变

介绍

在OpenCV中,常用的相机模型有针孔相机模型和广角相机模型两种。其中,针孔相机模型假设成像过程中光线都是直线,而广角相机模型则考虑了光线的弯曲。

在现实拍摄中,由于相机透镜的形状和制造工艺等原因,所拍摄的图像可能会出现畸变。常见的畸变有径向畸变和切向畸变两种。径向畸变会使得直线看起来弯曲,而切向畸变会使得图像出现倾斜。

代码

OpenCV中提供了undistort()函数,可以将畸变图像转换为没有畸变的图像。这个函数需要输入原始畸变图像、相机内参矩阵、畸变系数等参数。

x d i s t o r t e d = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) x_{distorted} = x(1+k_1r^2+k_2r^4+k_3r^6) + 2p_1xy+p_2(r^2+2x^2) xdistorted=x(1+k1r2+k2r4+k3r6)+2p1xy+p2(r2+2x2)
y d i s t o r t e d = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 1 ( r 2 + 2 y 2 ) + 2 P 2 x y y_{distorted} = y(1+k_1r^2+k_2r^4+k_3r^6) + p_1(r^2+2y^2) + 2P_2xy ydistorted=y(1+k1r2+k2r4+k3r6)+p1(r2+2y2)+2P2xy

其中, x , y x,y x,y是归一化坐标。

代码如下:

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    // 读入图像和相机参数
    Mat img = imread("input.jpg");
    Mat K = (Mat_<double>(3,3) << focal_length_x, 0, principal_point_x,
                                  0, focal_length_y, principal_point_y,
                                  0, 0, 1);
    Mat dist_coeffs = (Mat_<double>(5,1) << k1, k2, p1, p2, k3);

    // 进行去畸变
    Mat img_undistorted;
    undistort(img, img_undistorted, K, dist_coeffs);

    // 显示结果
    namedWindow("input", WINDOW_NORMAL);
    namedWindow("undistorted", WINDOW_NORMAL);
    imshow("input", img);
    imshow("undistorted", img_undistorted);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

其中,focal_length_x和focal_length_y是相机的焦距,principal_point_x和principal_point_y是相机的主点,k1、k2、p1、p2和k3是相机的畸变系数。这些参数需要根据相机型号进行确定。在代码中,Mat_表示数据类型为double的Mat对象,<<用于初始化Mat对象。

相机的畸变可以使用opencv中的undistort函数进行去畸变,如果不想使用opencv库,可以自己编写畸变矫正的函数。下面是一个简单的C++代码示例,使用OpenCV相机模型进行去畸变:

#include <cmath>
#include <iostream>
#include <vector>

using namespace std;

// 相机参数
double fx, fy, cx, cy;  // 相机内参
double k1, k2, p1, p2, k3;  // 畸变系数

// 去畸变函数
void undistortPoints(const vector<cv::Point2f>& src, vector<cv::Point2f>& dst) {
	double x, y, r, x_distorted, y_distorted;
    for (int i = 0; i < src.size(); i++) {
        x = (src[i].x - cx) / fx;
        y = (src[i].y - cy) / fy;
		r = sqrt(x * x + y * y);
		x_distorted = x * (1 + k1 * r*r + k2 * r*r*r*r + k3 * r*r*r*r*r*r) + 2 * p1*x*y + p2 * (r*r + 2*x*x);
		y_distorted = y * (1 + k1 * r*r + k2 * r*r*r*r + k3 * r*r*r*r*r*r) + 2 * p2*x*y + p1 * (r*r + 2*y*y);
		dst[i].x = fx * x_distorted + cx;
		dst[i].y = fy * y_distorted + cy;
    }
}

int main() {
    // 读入图像和相机参数
    vector<cv::Point2f> src_points, dst_points;
    // 读入src_points
    undistortPoints(src_points, dst_points);

    // 显示结果
    for (int i = 0; i < src_points.size(); i++) {
        cout << "src_point: (" << src_points[i].x << ", " << src_points[i].y << "), "
             << "dst_point: (" << dst_points[i].x << ", " << dst_points[i].y << ")" << endl;
    }

    return 0;
}

其中,fx和fy是相机的焦距,cx和cy是相机的主点,k1、k2、p1、p2和k3是相机的畸变系数。这些参数需要根据相机型号进行确定。函数undistortPoints输入为原始像素坐标点集src,输出为去畸变后的像素坐标点集dst。去畸变的具体过程可以参考OpenCV官方文档中的相机模型。

如果对整张图像做了去畸变,还可以考虑插值取值。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值