import cv2
import numpy as np
import glob

# 图片储存的路径
img_path = "/home/sunrise/yiliao_ws/imagebag_outputs"

# 棋盘格参数
CHECKERBOARD = (8, 5)  # 内角点数量（列×行）
square_size = 27  # 棋盘格方块实际尺寸（单位：毫米）

# 存储3D和2D点
objpoints = []  # 世界坐标系中的点
imgpoints = []  # 图像坐标系中的点

# 生成世界坐标系中的角点坐标（z=0）
objp = np.zeros((CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2) * square_size


# 读取所有棋盘格图片
images = glob.glob(f'{img_path}/*.png')

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

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

    if ret:
        objpoints.append(objp)

        # 亚像素角点优化
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
        corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners2)

        # 绘制角点（可选）
        # cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)
        # cv2.imshow('Detected Corners', img)
        # cv2.waitKey(500)

# cv2.destroyAllWindows()

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

# 输出标定结果
print("相机内参矩阵:\n", mtx)
print("\n畸变系数:", dist.ravel())

# 计算重投影误差
mean_error = 0
for i in range(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
    mean_error += error
print("\n平均重投影误差:", mean_error / len(objpoints))

# 保存参数
np.savez('cali.npz', mtx=mtx, dist=dist)


# 测试校正效果
img = cv2.imread(fname)  # 替换为实际的图片路径
# ret, img = cap.read()
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))

