【不墨迹】OpenCV畸变校准教程:校准参数生成及去畸变处理

不墨迹,放代码:

# 相机校准脚本
# 该脚本与所有jpg文件位于同一文件夹
# 使用OpenCV和Python进行相机校准

import numpy as np
import cv2
import glob
import yaml

# ==================== 可修改参数 ====================
# 棋盘格尺寸 (行数, 列数) - 指的是棋盘格的方格数量
CHESSBOARD_SQUARES = (18, 14)

# 角点检测精度参数
CRITERIA = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 图片文件类型
IMAGE_FORMAT = '*.jpg'

# 校准结果保存文件名
OUTPUT_FILE = "calibration_matrix.yaml"

# ====================================================

def main():
    # 计算内部角点的数量
    chessboard_size = (CHESSBOARD_SQUARES[0] - 1, CHESSBOARD_SQUARES[1] - 1)

    # 准备对象点,例如 (0,0,0), (1,0,0), ..., (16,12,0)
    objp = np.zeros((chessboard_size[0] * chessboard_size[1], 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(IMAGE_FORMAT)

    found = 0  # 记录找到的有效图片数量

    for fname in images:
        img = cv2.imread(fname)
        if img is None:
            print(f"无法读取图片: {
      
      fname}")
            continue

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # 查找棋盘角点
        ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)

        if ret:
            objpoints.append(objp)

            # 提高角点检测精度
            corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), CRITERIA)
            imgpoints.append(corners2)

            # 在图片上绘制角点
            img = cv2.drawChessboardCorners(img, chessboard_size, corners2, ret)
            found += 1

            # 显示检测结果
            cv2.imshow('Chessboard Corners', img)
            cv2.waitKey(500)

            # 如果需要保存带有角点的图片,可以取消以下注释
            # output_image_name = f'calibresult_{found}.png'
            # cv2.imwrite(output_image_name, img)
        else:
            print(f"未找到棋盘角点: {
      
      fname}")

    cv2.destroyAllWindows()

    print(f"用于校准的图片数量: {
      
      found}")

    if found < 1:
        print("没有找到足够的图片进行校准。")
        return

    # 进行相机校准
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

    if not ret:
        print("相机校准失败。")
        return

    # 将相机矩阵和畸变系数保存到字典中
    calibration_data = {
    
    
        'camera_matrix': mtx.tolist(),
        'dist_coeff': dist.tolist(),
        'rvecs': [r.tolist() for r in rvecs],
        'tvecs': [t.tolist() for t in tvecs]
    }

    # 将校准数据写入YAML文件
    with open(OUTPUT_FILE, "w") as f:
        yaml.dump(calibration_data, f)

    print(f"校准完成,结果已保存到 {
      
      OUTPUT_FILE}")

if __name__ == "__main__":
    main()

相机校准教程

本教程将指导您如何使用OpenCV和Python进行相机校准,包括生成校准参数和使用这些参数进行图像去畸变。

目录

  1. 安装必要的库
  2. 准备棋盘格
  3. 编写并运行校准脚本
  4. 使用校准参数进行图像去畸变

安装必要的库

在开始之前,确保您已经安装了以下Python库:

  • NumPy
  • OpenCV
  • Glob
  • PyYAML

您可以使用pip来安装这些库:

pip install numpy opencv-python glob2 pyyaml

准备棋盘格

  1. 下载棋盘格图案

    为了进行相机校准,您需要一个18×14的棋盘格图案。您可以使用以下链接生成高分辨率的棋盘格图案:

    生成棋盘格图案

    附一张示例棋盘格:

    请添加图片描述

    注意:确保棋盘格打印清晰,避免模糊或扭曲。

  2. 打印棋盘格

    将棋盘格图案按实际大小打印,并将其粘贴在一个平坦的表面上。确保棋盘格平整,以便在拍摄时能够准确检测角点。

  3. 拍摄校准图片

    从不同的角度和距离拍摄多张包含棋盘格的图片。至少需要15张不同角度的图片,以确保校准的准确性。

不同角度的棋盘格图片:

请添加图片描述

请添加图片描述


编写并运行校准脚本

  1. 准备工作目录

    • 将所有拍摄的.jpg图片与校准脚本放在同一个文件夹中。
  2. 编写校准脚本

    使用您喜欢的文本编辑器(如VS Code、PyCharm等)创建一个新的Python文件,例如camera_calibration.py,并将文章开头的代码粘贴进去:

    代码说明

    • CHESSBOARD_SQUARES:定义棋盘格的方格数量。在本例中为18×14。
    • CRITERIA:角点检测的终止条件。
    • IMAGE_FORMAT:指定要处理的图片格式,此处为所有.jpg文件。
    • OUTPUT_FILE:校准结果保存的YAML文件名。
    • chessboard_size:内部角点的数量,由棋盘格的方格数量减1得到。
    • objp:棋盘格在三维空间中的坐标。
    • objpoints & imgpoints:存储所有图片的对象点和图像点。
    • 校准过程:检测每张图片的棋盘角点,优化角点位置,绘制角点,进行相机校准并保存结果。
  3. 运行校准脚本

    打开终端或命令提示符,导航到脚本所在的文件夹,然后运行:

    python camera_calibration.py
    

    脚本将逐一处理每张图片,显示检测到的棋盘角点,并在完成后生成calibration_matrix.yaml文件。

    检测到的棋盘角点示例:
    请添加图片描述

    示例输出

    用于校准的图片数量:  15
    校准完成,结果已保存到 calibration_matrix.yaml
    

    请添加图片描述


使用校准参数进行图像去畸变

完成相机校准后,您可以使用生成的calibration_matrix.yaml文件对图像进行去畸变处理。以下是一个示例脚本:

# 图像去畸变脚本
import cv2
import yaml
import numpy as np

# 加载校准参数
with open("calibration_matrix.yaml") as f:
    data = yaml.safe_load(f)

camera_matrix = np.array(data['camera_matrix'])
dist_coeff = np.array(data['dist_coeff'])

# 读取需要去畸变的图像
img = cv2.imread('distorted_image.jpg')
h, w = img.shape[:2]

# 获取最佳新相机矩阵
new_camera_mtx, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coeff, (w, h), 1, (w, h))

# 去畸变
undistorted_img = cv2.undistort(img, camera_matrix, dist_coeff, None, new_camera_mtx)

# 裁剪图像(可选)
x, y, w, h = roi
undistorted_img = undistorted_img[y:y+h, x:x+w]

# 保存去畸变后的图像
cv2.imwrite('undistorted_image.jpg', undistorted_img)

# 显示结果
cv2.imshow('Undistorted Image', undistorted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

步骤说明

  1. 加载校准参数:从calibration_matrix.yaml文件中读取相机矩阵和畸变系数。
  2. 读取图像:加载需要去畸变的图像。
  3. 计算新相机矩阵:优化相机矩阵以减少失真。
  4. 去畸变:使用cv2.undistort函数去除图像的畸变。
  5. 裁剪图像(可选):根据ROI裁剪去畸变后的图像,去除无效区域。
  6. 保存和显示:保存去畸变后的图像并显示结果。

去畸变前后的图像对比
请添加图片描述

猜你喜欢

转载自blog.csdn.net/qq_38961840/article/details/143031770