Python实现相机标定及标定结果评估

Python实现相机标定及标定结果评估

  • python实现相机标定(内参和畸变系数)
  • 平均重投影误差
  • 畸变参数的估计误差

1.Python实现相机标定

import numpy as np
import cv2
import os
from PIL import Image

# 遍历照片
def read_images_from_folder(folder_path):
    images = []
    for filename in os.listdir(folder_path):
        if filename.endswith(".jpg") or filename.endswith(".png"):
            image_path = os.path.join(folder_path, filename)
            try:
                image = Image.open(image_path)
                images.append(image_path)
            except IOError:
                print("Cannot open image: ", filename)
    return images

# 标定板格点数量和大小
pattern_size = (9, 6)  # 内部角点数量
square_size = 25  # 棋盘格方块大小(毫米)

# 存储棋盘格角点的3D坐标
obj_points = []
# 存储棋盘格对应的图像点坐标
img_points = []

# 准备棋盘格的3D坐标
objp = np.zeros((pattern_size[0] * pattern_size[1], 3), dtype=np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) * square_size

# 指定文件夹路径
folder_path = "G:/实习/image/2"
# 调用函数读取图片
images = read_images_from_folder(folder_path)

# 遍历所有标定图像
for image_path in images:
    # 读取图像并将其转换为灰度图
    image = cv2.imread(image_path)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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

    # 如果找到棋盘格角点则存储对应的3D和2D坐标
    if ret:
        obj_points.append(objp)
        img_points.append(corners)

        # 在图像上绘制棋盘格角点
        cv2.drawChessboardCorners(image, pattern_size, corners, ret)
        cv2.imshow('Chessboard Corners', image)
        cv2.waitKey(500)

# 进行相机内参标定
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None)

# 打印相机内参和畸变系数
print("Camera Matrix:\n", camera_matrix)
print("\nDistortion Coefficients:\n", dist_coeffs)
np.savetxt('camera_matrix.txt', camera_matrix)
np.savetxt('dist_coeffs.txt', dist_coeffs)

相机内参和畸变系数(k1,k2,k3,p1,p2)
在这里插入图片描述

2.平均重投影误差

**重投影误差(Reprojection Error)**是指将通过标定得到的相机参数,将三维空间点重新投影到图像平面上得到的二维点与实际观测到的二维点之间的差异。以每个空间点为单位,重投影误差的计算方式如下:

  1. 将三维空间点通过相机的内外参数投影到图像平面,得到重投影的二维点。
  2. 计算重投影的二维点与实际观测到的二维点之间的欧式距离或其他距离度量。
  3. 将所有空间点的重投影误差求和,并取平均值,即可得到整体的重投影误差。
import cv2
import numpy as np
from PIL import Image
import os

def read_images_from_folder(folder_path):
    images = []
    for filename in os.listdir(folder_path):
        if filename.endswith(".jpg") or filename.endswith(".png"):
            image_path = os.path.join(folder_path, filename)
            try:
                image = Image.open(image_path)
                images.append(image_path)
            except IOError:
                print("Cannot open image: ", filename)
    return images
# 加载标定结果
camera_matrix = np.loadtxt('camera_matrix.txt')
dist_coeffs = np.loadtxt('dist_coeffs.txt')

# 指定文件夹路径
folder_path = "G:/实习/image/2"
# 调用函数读取图片
images = read_images_from_folder(folder_path)

# 计算评估指标
reprojection_errors = []
for image_file in images:
    # 加载图像
    image = cv2.imread(image_file)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 检测角点
    ret, corners = cv2.findChessboardCorners(gray, (9, 6), None)

    # 如果检测到角点,则进行评估
    if ret:
        # 畸变校正
        undistorted_corners = cv2.undistortPoints(corners, camera_matrix, dist_coeffs)

        # 计算重投影误差
        mean_error = np.sqrt(np.mean(np.square(undistorted_corners - corners)))
        reprojection_errors.append(mean_error)

# 计算平均重投影误差
mean_reprojection_error = np.mean(reprojection_errors)
# 打印结果
print("mean_reprojection_error:\n", mean_reprojection_error)
np.savetxt('mean_reprojection_error.txt', mean_reprojection_error.flatten()

mean_reprojection_error:
 1580.7643

3.畸变参数的估计误差

import cv2
import numpy as np
from PIL import Image
import os

def read_images_from_folder(folder_path):
    images = []
    for filename in os.listdir(folder_path):
        if filename.endswith(".jpg") or filename.endswith(".png"):
            image_path = os.path.join(folder_path, filename)
            try:
                image = Image.open(image_path)
                images.append(image_path)
            except IOError:
                print("Cannot open image: ", filename)
    return images

# 设置棋盘格角点的行数和列数
rows = 9
cols = 6

# 生成棋盘格角点的世界坐标
world_points = np.zeros((rows * cols, 3), np.float32)
world_points[:, :2] = np.mgrid[0:cols, 0:rows].T.reshape(-1, 2)

# 存储棋盘格角点的世界坐标和图像坐标
world_points_list = []  # 世界坐标系中的点
image_points_list = []  # 图像坐标系中的点

folder_path = "G:/实习/image/2"
# 加载图片进行角点检测
images = read_images_from_folder(folder_path)

for image_path in images:
    image = cv2.imread(image_path)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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

    # 如果找到棋盘格角点,则进行相机标定
    if ret:
        world_points_list.append(world_points)
        image_points_list.append(corners)

# 进行相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(world_points_list, image_points_list, gray.shape[::-1], None, None)

# 通过反投影误差估计畸变参数的估计误差
mean_error = 0
for i in range(len(world_points_list)):
    image_points, _ = cv2.projectPoints(world_points_list[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(image_points_list[i], image_points, cv2.NORM_L2) / len(image_points)
    mean_error += error

reprojection_error=mean_error / len(world_points_list)
print("畸变参数的估计误差: ", reprojection_error)
np.savetxt('reprojection_error.txt', reprojection_error.astype(float).flatten())
畸变参数的估计误差:  0.19547892484795085

综上所述,畸变参数的估计误差和平均重投影误差是用来评估相机标定结果的两个重要指标,其中估计误差表示畸变参数估计的准确程度,平均重投影误差表示标定结果的精度和稳定性。对于高质量的相机标定来说,畸变参数的估计误差应该尽可能小,平均重投影误差也应该尽可能小。
自己拍摄的用于标定的图片

猜你喜欢

转载自blog.csdn.net/m0_46406029/article/details/131573717