python 相机内参标定

抄这位大哥的 python+opencv相机标定, 他的 第10行 objp[:, :2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2), 6和9写反了好像。
原理:张正友标定法翻译

1.环境配置

pip3 install --upgrade pip
sudo pip3 install opencv-python -i https://pypi.douban.com/simple
import cv2
import numpy as np
import glob

def cal(h, w, image_path_list):
    # h, w: 棋盘格角点规格

    # 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001
    criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)

    # 获取标定板角点的在世界坐标系位置, 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y
    '''
    objp:
    [[0. 0. 0.]
    [1. 0. 0.]
    [2. 0. 0.]
    ...
    [4. 4. 0.]
    [5. 4. 0.]
    [6. 4. 0.]]
    '''
    objp = np.zeros((h * w, 3), np.float32)
    objp[:, :2] = np.mgrid[0:h, 0:w].T.reshape(-1, 2)

    obj_points = []
    img_points = []
  
    for image_path in image_path_list:
        img = cv2.imread(image_path)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        size = gray.shape[::-1]
        ret, corners = cv2.findChessboardCorners(gray, (h, w), None)
        print(ret)

        if ret:
            obj_points.append(objp)

            # 专门用来获取棋盘图上内角点的精确位置的, 即在原角点的基础上寻找亚像素角点
            corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria) 
            
            if [corners2]:
                img_points.append(corners2)
            else:
                img_points.append(corners)

            cv2.drawChessboardCorners(img, (h, w), corners, ret)
            cv2.imshow('img', img)
            cv2.waitKey(1000)

    print(len(img_points))
    cv2.destroyAllWindows()

    # calibration
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)

    np.set_printoptions(suppress=True)
    print("ret:", ret)
    print("mtx:\n", mtx.reshape(1,-1).tolist()) # 内参数矩阵
    print("dist:\n", dist.tolist())  # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
    # print("rvecs:\n", len(rvecs))  # 旋转向量  # 外参数
    # print("tvecs:\n", tvecs ) # 平移向量  # 外参数
    print("-----------------------------------------------------")

    # 用标定结果把空间三维坐标点映射回像素坐标系 再和 标定图片上的亚像素角点坐标 做对比
    total_error = 0
    for i in range(len(obj_points)):
        img_points2, _ = cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)
        error = cv2.norm(img_points[i],img_points2, cv2.NORM_L2)/len(img_points2)
        total_error += error
    # 单位是像素
    print("average error: ", total_error/len(img_points2))

def main():
    image_path_list = glob.glob("calibrationdata/*.jpg")
    cal(7, 5, image_path_list)

if __name__ == '__main__':
    main()

python3 a.py

我的标定板长这个样子
在这里插入图片描述

下面两个链接可能是比较详细的标定原理讲解, 第二个有和本文类似的python源码
https://blog.csdn.net/hehedadaq/article/details/105763241?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-6
https://github.com/1368069096/Calibration_ZhangZhengyou_Method

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
相机内参矩阵标定是计算机视觉中的一个重要问题,可以用于相机姿态估计、三维重建等应用。下面是一个使用 OpenCV 库进行标定的例子: 1. 准备标定板:在一个平面上粘贴黑白相间的正方形格子,保证每个格子大小相等,并且相邻两个格子颜色不同。标定板可以是任何形状,但必须包含足够的特征点。 2. 拍摄标定板:将相机对准标定板,拍摄多张照片,保证标定板的不同位置和姿态都被拍摄到。 3. 提取角点:使用 OpenCV 库中的 `findChessboardCorners()` 函数对每张照片进行角点提取。该函数会返回每张图片中角点的像素坐标。 4. 标定相机:使用 OpenCV 库中的 `calibrateCamera()` 函数进行相机标定。该函数需要提供每张照片中的角点像素坐标以及标定板的实际尺寸作为输入。函数会输出相机内参矩阵,畸变系数等信息。 下面是一个简单的 Python 代码示例: ```python import cv2 import numpy as np # 设置标定板大小 board_size = (9, 6) # 准备标定板对象 objp = np.zeros((np.prod(board_size), 3), dtype=np.float32) objp[:, :2] = np.mgrid[0:board_size[0], 0:board_size[1]].T.reshape(-1, 2) # 存储标定板角点像素坐标 img_points = [] # 存储标定板实际三维坐标 obj_points = [] # 读取标定板图片 img = cv2.imread('calibration.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 提取角点 ret, corners = cv2.findChessboardCorners(gray, board_size, None) # 如果成功提取角点 if ret: # 存储角点像素坐标 img_points.append(corners) # 存储标定板实际三维坐标 obj_points.append(objp) # 标定相机 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None) # 输出相机内参矩阵 print("Camera matrix: \n", mtx) ``` 该代码会输出相机内参矩阵。需要注意的是,标定板的大小和形状需要与实际使用的标定板保持一致。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值