介绍
基础知识参考:相机的内参和外参
1.相机标定
相机标定是计算机视觉中的一个重要步骤,它用于确定相机的内部参数(如焦距、主点坐标、畸变参数)和外部参数(如相机在世界坐标系中的位置和方向)。以下是一个使用OpenCV库进行相机标定的Python代码示例:
import numpy as np
import cv2
import glob
# 定义棋盘格的尺寸
chessboard_size = (9, 6)
# 准备对象点,如 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((np.prod(chessboard_size), 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
# 存储对象点和图像点的数组
objpoints = [] # 3d点在世界坐标系中
imgpoints = [] # 2d点在图像平面中
# 读取所有图像
images = glob.glob('path_to_your_images/*.jpg')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 寻找棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
# 如果找到,添加对象点和图像点
if ret:
objpoints.append(objp)
imgpoints.append(corners)
# 绘制并显示角点
cv2.drawChessboardCorners(img, chessboard_size, corners, ret)
cv2.imshow('img', img)
cv2.waitKey(500)
cv2.destroyAllWindows()
# 标定相机
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print("相机矩阵:\n", camera_matrix)
print("畸变系数:\n", dist_coeffs)
print("旋转向量:\n", rvecs)
print("平移向量:\n", tvecs)
# 计算重投影误差
mean_error = 0
for i in range(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], camera_matrix, dist_coeffs)
error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
mean_error += error
print(f"总重投影误差: {mean_error/len(objpoints)}")
代码说明:
- 定义棋盘格尺寸:
chessboard_size
定义了棋盘格的行数和列数。 - 准备对象点:
objp
是一个数组,存储了棋盘格角点的坐标。 - 读取图像:使用
glob
模块读取指定路径下的所有图像。 - 寻找角点:使用
cv2.findChessboardCorners
函数在每张图像中寻找棋盘格的角点。 - 绘制角点:使用
cv2.drawChessboardCorners
函数绘制找到的角点。 - 标定相机:使用
cv2.calibrateCamera
函数进行相机标定,得到相机矩阵、畸变系数、旋转向量和平移向量。 - 计算重投影误差:通过重投影误差评估标定结果的准确性。
注意事项:
- 确保棋盘格图像清晰且角点检测准确。
- 图像路径需要根据实际情况进行修改。
- 棋盘格尺寸需要与实际使用的棋盘格一致。
使用标定结果处理图像:
在相机标定完成后,我们可以利用标定结果(相机矩阵和畸变系数)来对图像进行处理,以校正图像中的畸变。以下是一个使用OpenCV库进行图像畸变校正的Python代码示例:
import numpy as np
import cv2
# 假设我们已经通过相机标定得到了以下参数
camera_matrix = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]], dtype=np.float32)
dist_coeffs = np.array([k1, k2, p1, p2, k3], dtype=np.float32)
# 读取需要校正的图像
img = cv2.imread('path_to_your_image.jpg')
# 获取图像的尺寸
h, w = img.shape[:2]
# 计算新的相机矩阵以进行畸变校正
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coeffs, (w, h), 1, (w, h))
# 使用cv2.undistort进行畸变校正
undistorted_img = cv2.undistort(img, camera_matrix, dist_coeffs, None, new_camera_matrix)
# 可选:裁剪图像以去除边缘的黑边
x, y, w, h = roi
undistorted_img = undistorted_img[y:y+h, x:x+w]
# 显示和保存校正后的图像
cv2.imshow('Undistorted Image', undistorted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('undistorted_image.jpg', undistorted_img)
代码说明:
- 定义相机矩阵和畸变系数:
camera_matrix
和dist_coeffs
是从相机标定中得到的参数。 - 读取图像:使用
cv2.imread
函数读取需要校正的图像。 - 获取图像尺寸:获取图像的高度和宽度。
- 计算新的相机矩阵:使用
cv2.getOptimalNewCameraMatrix
函数计算新的相机矩阵,以优化畸变校正效果。 - 进行畸变校正:使用
cv2.undistort
函数对图像进行畸变校正。 - 裁剪图像:根据
roi
(感兴趣区域)裁剪图像,去除边缘的黑边。 - 显示和保存校正后的图像:使用
cv2.imshow
显示校正后的图像,并使用cv2.imwrite
保存图像。
注意事项:
- 确保相机矩阵和畸变系数是从准确的相机标定中得到的。
- 图像路径需要根据实际情况进行修改。
- 如果不需要裁剪图像,可以跳过裁剪步骤。
通过上述步骤,可以使用相机标定结果对图像进行畸变校正,从而获得更准确的图像。这对于许多计算机视觉应用(如三维重建、目标检测等)都是非常重要的预处理步骤。
2.图像配准
图像配准(Image Registration)是将不同时间、不同传感器或不同视角下获取的两幅或多幅图像进行匹配的过程。其目的是找到这些图像之间的空间变换关系,使得它们在空间上对齐。图像配准在医学影像、遥感图像处理、计算机视觉等领域有广泛应用。
以下是一个使用OpenCV库进行基于特征的图像配准的Python代码示例:
import cv2
import numpy as np
# 读取参考图像和待配准图像
img1 = cv2.imread('path_to_reference_image.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('path_to_target_image.jpg', cv2.IMREAD_GRAYSCALE)
# 使用ORB检测器检测特征点和描述符
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 使用BFMatcher进行特征匹配
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
# 根据距离排序匹配点
matches = sorted(matches, key=lambda x: x.distance)
# 提取匹配的特征点
pts1 = np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)
pts2 = np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)
# 计算单应性矩阵
H, mask = cv2.findHomography(pts1, pts2, cv2.RANSAC, 5.0)
# 使用单应性矩阵进行图像配准
h, w = img1.shape
aligned_img2 = cv2.warpPerspective(img2, H, (w, h))
# 显示和保存配准后的图像
cv2.imshow('Aligned Image', aligned_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('aligned_image.jpg', aligned_img2)
代码说明:
- 读取图像:使用
cv2.imread
函数读取参考图像和待配准图像。 - 特征检测:使用 ORB 检测器检测两幅图像的特征点和描述符。
- 特征匹配:使用 BFMatcher 进行特征匹配,并根据匹配点的距离进行排序。
- 提取匹配点:提取匹配的特征点坐标。
- 计算单应性矩阵:使用
cv2.findHomography
函数计算单应性矩阵,该矩阵描述了两幅图像之间的空间变换关系。 - 图像配准:使用
cv2.warpPerspective
函数将待配准图像根据单应性矩阵进行变换,使其与参考图像对齐。 - 显示和保存配准后的图像:使用
cv2.imshow
显示配准后的图像,并使用cv2.imwrite
保存图像。
注意事项:
- 确保参考图像和待配准图像的路径正确。
- 可以根据需要选择不同的特征检测器和匹配器。
- 配准结果的精度受特征点检测和匹配质量的影响,可能需要调整参数或使用更高级的算法以获得更好的结果。
通过上述步骤,你可以使用OpenCV库进行基于特征的图像配准,从而将不同图像在空间上对齐。这对于许多应用(如图像拼接、变化检测等)都是非常重要的预处理步骤。