相机标定和图像配准

相机标定和图像配准

  • 介绍
    • 1.相机标定
      • 代码说明:
      • 注意事项:
      • 使用标定结果处理图像:
      • 代码说明:
      • 注意事项:
    • 2.图像配准
      • 代码说明:
      • 注意事项:

介绍

基础知识参考:相机的内参和外参

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)}")

代码说明:

  1. 定义棋盘格尺寸chessboard_size 定义了棋盘格的行数和列数。
  2. 准备对象点objp 是一个数组,存储了棋盘格角点的坐标。
  3. 读取图像:使用 glob 模块读取指定路径下的所有图像。
  4. 寻找角点:使用 cv2.findChessboardCorners 函数在每张图像中寻找棋盘格的角点。
  5. 绘制角点:使用 cv2.drawChessboardCorners 函数绘制找到的角点。
  6. 标定相机:使用 cv2.calibrateCamera 函数进行相机标定,得到相机矩阵、畸变系数、旋转向量和平移向量。
  7. 计算重投影误差:通过重投影误差评估标定结果的准确性。

注意事项:

  • 确保棋盘格图像清晰且角点检测准确。
  • 图像路径需要根据实际情况进行修改。
  • 棋盘格尺寸需要与实际使用的棋盘格一致。

使用标定结果处理图像:

在相机标定完成后,我们可以利用标定结果(相机矩阵和畸变系数)来对图像进行处理,以校正图像中的畸变。以下是一个使用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)

代码说明:

  1. 定义相机矩阵和畸变系数camera_matrixdist_coeffs 是从相机标定中得到的参数。
  2. 读取图像:使用 cv2.imread 函数读取需要校正的图像。
  3. 获取图像尺寸:获取图像的高度和宽度。
  4. 计算新的相机矩阵:使用 cv2.getOptimalNewCameraMatrix 函数计算新的相机矩阵,以优化畸变校正效果。
  5. 进行畸变校正:使用 cv2.undistort 函数对图像进行畸变校正。
  6. 裁剪图像:根据 roi(感兴趣区域)裁剪图像,去除边缘的黑边。
  7. 显示和保存校正后的图像:使用 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)

代码说明:

  1. 读取图像:使用 cv2.imread 函数读取参考图像和待配准图像。
  2. 特征检测:使用 ORB 检测器检测两幅图像的特征点和描述符。
  3. 特征匹配:使用 BFMatcher 进行特征匹配,并根据匹配点的距离进行排序。
  4. 提取匹配点:提取匹配的特征点坐标。
  5. 计算单应性矩阵:使用 cv2.findHomography 函数计算单应性矩阵,该矩阵描述了两幅图像之间的空间变换关系。
  6. 图像配准:使用 cv2.warpPerspective 函数将待配准图像根据单应性矩阵进行变换,使其与参考图像对齐。
  7. 显示和保存配准后的图像:使用 cv2.imshow 显示配准后的图像,并使用 cv2.imwrite 保存图像。

注意事项:

  • 确保参考图像和待配准图像的路径正确。
  • 可以根据需要选择不同的特征检测器和匹配器。
  • 配准结果的精度受特征点检测和匹配质量的影响,可能需要调整参数或使用更高级的算法以获得更好的结果。

通过上述步骤,你可以使用OpenCV库进行基于特征的图像配准,从而将不同图像在空间上对齐。这对于许多应用(如图像拼接、变化检测等)都是非常重要的预处理步骤。

你可能感兴趣的:(算法,数码相机)