针孔相机模型和相机内参矩阵K

在这里插入图片描述

上图为针孔相机模型的成像原理图。

O − x − y − z O-x-y-z Oxyz 为相机坐标系, O O O 为相机的光心(同样也是针孔模型中的针孔)。现实世界的空间点 P P P ,经过光心 O O O 投影之后,落在了物理成像平面 O ′ − x ′ − y ′ O^{\prime}-x^{\prime}-y^{\prime} Oxy 上,成像点为 P ′ P' P

设空间点 P P P 的坐标为 [ X , Y , Z ] T [X, Y, Z]^{T} [X,Y,Z]T P ′ P' P 的坐标为 [ X ′ , Y ′ , Z ′ ] T [X', Y', Z']^{T} [X,Y,Z]T,并且设物理成像平面到光心的距离(即焦距)为 f f f 。那么由三角形相似关系有:

Z f = − X X ′ = − Y Y ′ (1) \frac{Z}{f}=-\frac{X}{X^{\prime}}=-\frac{Y}{Y^{\prime}} \tag{1} fZ=XX=YY(1)

其中负号表示成的像是倒立的。为了简化模型,我们可以把成像平面对称到相机前方,和三维空间点一起放在摄像机坐标系的同一侧(如下图所示)。

在这里插入图片描述

简化之后去掉负号,便可以得到:

Z f = X X ′ = Y Y ′ (2) \frac{Z}{f}=\frac{X}{X^{\prime}}=\frac{Y}{Y^{\prime}} \tag{2} fZ=XX=YY(2)

整理之后,有:

X ′ = f X Z Y ′ = f Y Z (3) \begin{aligned} &X^{\prime}=f \frac{X}{Z} \\ &Y^{\prime}=f \frac{Y}{Z} \end{aligned} \tag{3} X=fZXY=fZY(3)

上面公式表示的是空间中的点 P P P 和它在成像平面对应的点 P ′ P' P 之间的几何关系。当时在相机中,图片是由一个个像素表示的,因此还需要在成像平面上进行采样和量化。下图是成像平面坐标系和像素平面坐标系的图示,两者有以下区别:

  • 单位不一样:成像平面坐标系的单位是米,像素坐标系的单位是像素
  • 坐标系原点的位置不一样:成像平面坐标系的原点在中心,像素坐标系的原点在左上方

在这里插入图片描述

因此,为了将成像平面上的点转换到像素坐标系上,需要进行单位之间转换的缩放和原点的平移。

假设成像平面坐标系为 O ′ − x ′ − y ′ O^{\prime}-x^{\prime}-y^{\prime} Oxy ,像素坐标系为 o − u − v o-u-v ouv。假设成像平面坐标系转换到像素坐标系 u u u 轴上缩放了 α \alpha α 倍,转换到像素坐标系 v v v 轴上缩放了 β \beta β 倍,原点平移了 [ c x , c y ] T \left[c_{x}, c_{y}\right]^{T} [cx,cy]T(单位:像素)。那么 P ′ P' P 的坐标与像素坐标 [ u , v ] T [u, v]^{T} [u,v]T 的关系为:

{ u = α X ′ + c x v = β Y ′ + c y (4) \left\{\begin{array}{l} u=\alpha X^{\prime}+c_{x} \\ v=\beta Y^{\prime}+c_{y} \end{array}\right. \tag{4} {u=αX+cxv=βY+cy(4)

将 (3) 式代入 (4) 中,并将 α f \alpha f αf 记为 f x f_x fx β f \beta f βf 记为 f y f_y fy,可得:

{ u = f x X Z + c x v = f y Y Z + c y (5) \left\{\begin{array}{l} u=f_{x} \frac{X}{Z}+c_{x} \\ v=f_{y} \frac{Y}{Z}+c_{y} \end{array}\right. \tag{5} {u=fxZX+cxv=fyZY+cy(5)

其中, f f f 的单位是米, α \alpha α β \beta β 的单位是像素/米,所以 f x f_x fx f y f_y fy 的单位为像素。

为了使得公式更加简洁,可以将该式写成矩阵形式,不过左侧需要用到齐次坐标:

( u v 1 ) = 1 Z ( f x 0 c x 0 f y c y 0 0 1 ) ( X Y Z ) ≜ 1 Z K P (6) \left(\begin{array}{l} u \\ v \\ 1 \end{array}\right)=\frac{1}{Z}\left(\begin{array}{ccc} f_{x} & 0 & c_{x} \\ 0 & f_{y} & c_{y} \\ 0 & 0 & 1 \end{array}\right)\left(\begin{array}{c} X \\ Y \\ Z \end{array}\right) \triangleq \frac{1}{Z} \boldsymbol{K} \boldsymbol{P} \tag{6} uv1=Z1fx000fy0cxcy1XYZZ1KP(6)

按照传统习惯,可以将 Z Z Z 移到等式左边,则有:

Z ( u v 1 ) = ( f x 0 c x 0 f y c y 0 0 1 ) ( X Y Z ) ≜ K P (7) Z\left(\begin{array}{l} u \\ v \\ 1 \end{array}\right)=\left(\begin{array}{ccc} f_{x} & 0 & c_{x} \\ 0 & f_{y} & c_{y} \\ 0 & 0 & 1 \end{array}\right)\left(\begin{array}{l} X \\ Y \\ Z \end{array}\right) \triangleq \boldsymbol{K} \boldsymbol{P} \tag{7} Zuv1=fx000fy0cxcy1XYZKP(7)

上式中,中间的量组成的矩阵 K \boldsymbol{K} K 被称为相机的内参矩阵(Camera Intrinsics)。

参考文献:视觉SLAM十四讲

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV提供了一种简单的针孔模型标定方法,可以用来标定相机的内部参数。可以使用下面的示例代码来调用针孔模型:cv::Mat intrinsic = cv::Mat::eye(3, 3, CV_64F); cv::Mat distCoeffs; std::vector<cv::Point2f> imagePoints;cv::calibrateCamera(objectPoints, imagePoints, imageSize, intrinsic, distCoeffs, rvecs, tvecs); ### 回答2: 下面是一个使用OpenCV相机标定针孔模型的示例: 首先,我们需要准备一些相机标定的图片。这些图片应该包括一些具有明确角点的棋盘格图像。确保摄像机在不同的位置和角度下拍摄足够数量的图像。 在代码中,我们首先导入必要的库: import cv2 import numpy as np 接下来,我们定义几个参数: pattern_size = (6, 9) # 棋盘格内角点数量 square_size = 1.0 # 棋盘格边长(单位:厘米) 然后,我们创建一个空的列表用于存储图像中检测到的角点: obj_points = [] # 世界坐标系中的角点 img_points = [] # 图像坐标系中的角点 接下来,我们加载图像并进行标定: for i in range(num_images): # num_images指图像数量 img = cv2.imread(f'calibration{i}.jpg') # 加载图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度图像 # 检测图像中的棋盘格角点 ret, corners = cv2.findChessboardCorners(gray, pattern_size, None) if ret == True: obj_points.append(np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32)) obj_points[-1][:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) img_points.append(corners) # 在图像上绘制角点 cv2.drawChessboardCorners(img, pattern_size, corners, ret) cv2.imshow('img', img) cv2.waitKey(500) cv2.destroyAllWindows() 最后,我们使用收集到的角点进行相机的标定: ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None) 其中,ret返回一个标志,表示标定是否成功,mtx、dist、rvecs、tvecs分别是相机内参矩阵、畸变系数、旋转向量和平移向量。 这就是一个使用OpenCV相机标定针孔模型的示例。在实际应用中,你可以根据自己的需求调整参数和代码。 ### 回答3: 要使用OpenCV进行相机标定,首先需要准备一组已知的世界坐标系下的标定板图像,标定板上的角点需要已知其真实世界坐标。然后通过拍摄这组标定板图像,并提取出每幅图像中的角点,即图像坐标。 以下是一个使用OpenCV进行相机标定的代码示例: ```python import cv2 import numpy as np # 定义标定板参数 num_corners_x = 9 num_corners_y = 6 square_size = 25 # 每个角点的实际大小,单位为毫米 # 准备角点的真实世界坐标 objp = np.zeros((num_corners_x * num_corners_y, 3), np.float32) objp[:, :2] = np.mgrid[0:num_corners_x, 0:num_corners_y].T.reshape(-1, 2) * square_size # 初始化存储角点的数组 objpoints = [] # 真实世界坐标 imgpoints = [] # 图像坐标 # 拍摄标定板图像,提取角点 for filename in glob.glob('calibration_images/*.jpg'): # 修改为存储标定板图像的路径 img = cv2.imread(filename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 查找角点 ret, corners = cv2.findChessboardCorners(gray, (num_corners_x, num_corners_y), None) # 如果找到角点,则添加到数组中 if ret == True: objpoints.append(objp) imgpoints.append(corners) # 可视化角点 cv2.drawChessboardCorners(img, (num_corners_x, num_corners_y), corners, ret) cv2.imshow('img', img) cv2.waitKey(500) cv2.destroyAllWindows() # 进行相机标定 ret, camera_matrix, distortion_coeff, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) # 打印结果 print("相机内参矩阵:") print(camera_matrix) print("\n相机畸变系数:") print(distortion_coeff) # 对测试图像进行矫正 img = cv2.imread('test_image.jpg') # 替换为待校正的图像路径 h, w = img.shape[:2] new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, distortion_coeff, (w, h), 1, (w, h)) dst = cv2.undistort(img, camera_matrix, distortion_coeff, None, new_camera_matrix) # 显示校正前后的图像 cv2.imshow('Original Image', img) cv2.imshow('Undistorted Image', dst) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上代码会利用OpenCV提供的`findChessboardCorners`函数在标定板图像中查找角点,然后使用`calibrateCamera`函数进行相机标定,最后通过`undistort`函数对待校正的图像进行畸变矫正。在代码中需要根据实际情况修改标定板图像的路径和待校正的图像路径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值