基于单固定半径圆形靶标的OpenCV Python相机标定实现咨询
单个圆形靶标相机标定方案说明
内置函数可用性说明
可以直接使用OpenCV内置的cv2.calibrateCamera()标定函数完成该场景下的标定,该函数仅要求输入匹配的3D世界坐标系点位和对应的2D图像像素点位,不对靶标类型做限制。
具体实现步骤
- 采集至少15~20帧不同角度、不同距离、不同姿态的圆形靶标图像,要求所有图像中圆形完整可见,拍摄姿态尽量覆盖全视野,避免出现相近姿态的重复采样
- 对每帧图像做灰度化、高斯模糊、二值化预处理,使用
cv2.findContours()轮廓检测或cv2.HoughCircles()霍夫圆检测提取圆形区域,拟合得到图像中圆形的圆心像素坐标和成像半径 - 构造3D-2D匹配点对:将靶标平面设为世界坐标系的Z=0平面,圆心设为世界坐标系原点,根据已知的真实半径生成圆心以及圆周均匀采样点的3D坐标;对应2D坐标为检测到的图像圆心和拟合圆周上相同角度的像素坐标
- 将所有帧的3D点集合、2D点集合、相机图像分辨率输入
cv2.calibrateCamera(),即可解算得到相机内参矩阵、畸变系数以及每帧靶标对应的外参矩阵
注意事项
- 需保证靶标平面的平整度,避免平面变形带来的系统误差
- 若要提升标定精度,可对检测到的圆形轮廓做亚像素拟合,替代霍夫圆检测直接输出的整数坐标,降低2D点检测误差
- 采集图像时要尽量保证姿态差异足够大,避免出现退化位姿导致标定结果精度不足
核心实现代码片段
import cv2 import numpy as np # 预设标定参数 REAL_CIRCLE_RADIUS = 0.05 # 圆形靶标的真实半径,单位为米 CIRCUMFERENCE_SAMPLE_COUNT = 16 # 圆周采样点数量 CAMERA_RESOLUTION = (1280, 720) # 相机输出图像的分辨率 # 构造固定的3D世界坐标点(靶标平面为Z=0平面) objp = np.zeros((CIRCUMFERENCE_SAMPLE_COUNT + 1, 3), np.float32) objp[0] = [0, 0, 0] # 圆心对应3D坐标 for i in range(CIRCUMFERENCE_SAMPLE_COUNT): theta = 2 * np.pi * i / CIRCUMFERENCE_SAMPLE_COUNT objp[i+1] = [REAL_CIRCLE_RADIUS * np.cos(theta), REAL_CIRCLE_RADIUS * np.sin(theta), 0] # 存储所有帧的匹配点对 obj_points = [] # 存储3D世界坐标 img_points = [] # 存储对应2D图像坐标 # 替换为你自己的标定图像路径列表 calib_image_paths = ["img1.jpg", "img2.jpg", "img3.jpg"] for img_path in calib_image_paths: img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 霍夫圆检测提取圆形靶标 circles = cv2.HoughCircles( gray, cv2.HOUGH_GRADIENT, dp=1.2, minDist=200, param1=50, param2=30, minRadius=10, maxRadius=300 ) if circles is not None: circles = np.uint16(np.around(circles))[0][0] cx, cy, r = circles[0], circles[1], circles[2] # 构造对应2D坐标点 imgp = np.zeros((CIRCUMFERENCE_SAMPLE_COUNT + 1, 2), np.float32) imgp[0] = [cx, cy] for i in range(CIRCUMFERENCE_SAMPLE_COUNT): theta = 2 * np.pi * i / CIRCUMFERENCE_SAMPLE_COUNT imgp[i+1] = [cx + r * np.cos(theta), cy + r * np.sin(theta)] obj_points.append(objp) img_points.append(imgp) # 执行相机标定 ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera( obj_points, img_points, CAMERA_RESOLUTION, None, None )
内容的提问来源于stack exchange,提问作者Shuvo Imrul
相关产品推荐
相关产品推荐

