不墨迹,放代码:
# 相机校准脚本
# 该脚本与所有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进行相机校准,包括生成校准参数和使用这些参数进行图像去畸变。
目录
安装必要的库
在开始之前,确保您已经安装了以下Python库:
- NumPy
- OpenCV
- Glob
- PyYAML
您可以使用pip
来安装这些库:
pip install numpy opencv-python glob2 pyyaml
准备棋盘格
-
下载棋盘格图案:
为了进行相机校准,您需要一个18×14的棋盘格图案。您可以使用以下链接生成高分辨率的棋盘格图案:
附一张示例棋盘格:
注意:确保棋盘格打印清晰,避免模糊或扭曲。
-
打印棋盘格:
将棋盘格图案按实际大小打印,并将其粘贴在一个平坦的表面上。确保棋盘格平整,以便在拍摄时能够准确检测角点。
-
拍摄校准图片:
从不同的角度和距离拍摄多张包含棋盘格的图片。至少需要15张不同角度的图片,以确保校准的准确性。
不同角度的棋盘格图片:
编写并运行校准脚本
-
准备工作目录:
- 将所有拍摄的
.jpg
图片与校准脚本放在同一个文件夹中。
- 将所有拍摄的
-
编写校准脚本:
使用您喜欢的文本编辑器(如VS Code、PyCharm等)创建一个新的Python文件,例如
camera_calibration.py
,并将文章开头的代码粘贴进去:代码说明:
- CHESSBOARD_SQUARES:定义棋盘格的方格数量。在本例中为18×14。
- CRITERIA:角点检测的终止条件。
- IMAGE_FORMAT:指定要处理的图片格式,此处为所有
.jpg
文件。 - OUTPUT_FILE:校准结果保存的YAML文件名。
- chessboard_size:内部角点的数量,由棋盘格的方格数量减1得到。
- objp:棋盘格在三维空间中的坐标。
- objpoints & imgpoints:存储所有图片的对象点和图像点。
- 校准过程:检测每张图片的棋盘角点,优化角点位置,绘制角点,进行相机校准并保存结果。
-
运行校准脚本:
打开终端或命令提示符,导航到脚本所在的文件夹,然后运行:
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()
步骤说明:
- 加载校准参数:从
calibration_matrix.yaml
文件中读取相机矩阵和畸变系数。- 读取图像:加载需要去畸变的图像。
- 计算新相机矩阵:优化相机矩阵以减少失真。
- 去畸变:使用
cv2.undistort
函数去除图像的畸变。- 裁剪图像(可选):根据ROI裁剪去畸变后的图像,去除无效区域。
- 保存和显示:保存去畸变后的图像并显示结果。
去畸变前后的图像对比