当前位置: 首页 > news >正文

【立体标定】圆形标定板标定python实现

1. 非对称圆形标定板

标定板生成器:calib.io
在这里插入图片描述
如上所示row = 实际行数/2 ,col = 实际列数

2. 代码

完整代码

"""
Stereo calibration (asymmetric circles grid)
"""import glob, os, cv2
import numpy as np
from tqdm import tqdm# ---------- 参数 ----------
LEFT_DIR   = r'D:\Document\Camera1'
RIGHT_DIR  = r'D:\Document\Camera2'
ROWS       = 4          # 圆点行数(短边)
COLS       = 11         # 圆点列数(长边)
SQUARE     = 15.0       # 圆心间距,单位 mm# ---------- 1. 生成物理坐标 ----------
def generate_board_points(rows, cols, dist, type_flag=1):"""生成非对称圆点标定板 3D 坐标"""pts = []if type_flag == 1:offset_x, offset_y = dist / 2.0, dist / 2.0i = k = 0for row in range(cols):if row != 0:if row % 2 == 0:k += 1else:i += 1for col in range(rows):x = col * disty = (row - (k if row % 2 == 0 else i)) * distif row % 2 != 0:x += offset_xy += offset_ypts.append((x, y, 0.0))return np.array(pts, dtype=np.float32)# ---------- 2. 查找圆点 ----------
def find_circles(images, pattern_size):"""返回 (ok, corners) 列表"""blob_params = cv2.SimpleBlobDetector.Params()blob_params.filterByArea = Falseblob_params.minArea = 20blob_params.maxArea = 1024blob_params.filterByCircularity = Trueblob_params.minCircularity = 0.7blob_params.filterByConvexity = Trueblob_params.minConvexity = 0.8blob_params.filterByInertia = Trueblob_params.minInertiaRatio = 0.5detector = cv2.SimpleBlobDetector.create(blob_params)flags = cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERINGall_corners, ok_idx = [], []for im_path in tqdm(images, desc='Detect circles'):img = cv2.imread(im_path, cv2.IMREAD_GRAYSCALE)if img is None:  # 读图失败continueok, corners = cv2.findCirclesGrid(img, pattern_size, flags=flags,blobDetector=detector)ok_idx.append(ok)if ok:corners = cv2.cornerSubPix(img, corners, (5, 5), (-1, -1),criteria=(cv2.TERM_CRITERIA_EPS +cv2.TERM_CRITERIA_MAX_ITER, 10, 0.1))all_corners.append(corners)return all_corners, ok_idx# ---------- 3. 主流程 ----------
def stereo_calibrate_main():left_imgs  = sorted(glob.glob(os.path.join(LEFT_DIR,  '*.*')))right_imgs = sorted(glob.glob(os.path.join(RIGHT_DIR, '*.*')))assert len(left_imgs) == len(right_imgs), '左右图像数量必须一致'# 3.1 准备 3D 点pattern_size = (ROWS, COLS)objp = generate_board_points(ROWS, COLS, SQUARE)objpoints = [objp] * len(left_imgs)   # 每幅图对应同一组 3D 点# 3.2 检测圆点left_corners,  ok_L = find_circles(left_imgs, pattern_size)right_corners, ok_R = find_circles(right_imgs, pattern_size)ok = np.array(ok_L) & np.array(ok_R)   # 只保留左右都检测成功的# 取最小数量,保证左右一一对应n_pairs = min(len(left_corners), len(right_corners))left_corners = left_corners[:n_pairs]right_corners = right_corners[:n_pairs]objpoints = [objp] * n_pairsprint(f'有效图像对:{n_pairs}')if len(objpoints) < 3:raise RuntimeError('有效图像对不足,无法标定')# 3.3 单目标定img_size = cv2.imread(left_imgs[0], cv2.IMREAD_GRAYSCALE).shape[::-1]retL, K1, D1, rvecsL, tvecsL = cv2.calibrateCamera(objpoints, left_corners, img_size, None, None)retR, K2, D2, rvecsR, tvecsR = cv2.calibrateCamera(objpoints, right_corners, img_size, None, None)# 3.4 双目标定flags = (cv2.CALIB_FIX_INTRINSIC |cv2.CALIB_USE_INTRINSIC_GUESS |cv2.CALIB_RATIONAL_MODEL)retS, K1, D1, K2, D2, R, T, E, F = cv2.stereoCalibrate(objpoints, left_corners, right_corners,K1, D1, K2, D2, img_size,flags=flags,criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6))# ---------- 4. 保存结果 ----------np.savez('stereo_calib.npz',K1=K1, D1=D1, K2=K2, D2=D2,R=R, T=T, E=E, F=F,img_size=img_size)# ---------- 5. 打印信息 ----------print('\n========== 双目标定结果 ==========')print(f'左重投影误差:{retL:.4f} 像素')print(f'右重投影误差:{retR:.4f} 像素')print(f'立体标定误差:{retS:.4f} 像素')print('\n左相机内参 K1:\n', K1)print('\n右相机内参 K2:\n', K2)print('\n旋转向量 R:\n', R)print('\n平移向量 T:\n', T)if __name__ == '__main__':stereo_calibrate_main()

对称圆形标定板同理,替换cv2.findCirclesGrid 的参数flags=cv2.CALIB_CB_SYMMETRIC_GRID即可。

若是检测不到,可以在第一步添加下面代码观察圆形点是否被检出。

img = cv2.resize(img, (640, 480))
# 检测斑点
keypoints = detector.detect(img)
# 在图像上绘制检测到的斑点
image_with_keypoints = cv2.drawKeypoints(img, keypoints, None, color=(0, 255, 0),flags=cv2.DrawMatchesFlags_DRAW_RICH_KEYPOINTS)
# 显示结果
cv2.imshow("Blob Detection", image_with_keypoints)
cv2.waitKey(0)
http://www.dtcms.com/a/309353.html

相关文章:

  • MySQL学习从零开始--第六部分
  • PyTorch 分布式训练全解析:从原理到实践
  • 数据仓库、数据湖与湖仓一体技术笔记
  • 第三章 网络安全基础(一)
  • OPENGLPG第九版学习 - 纹理与帧缓存 part2
  • linux中posix消息队列的使用记录
  • Java与Kotlin中“==“、“====“区别
  • 解锁 Grok-4 —— 技术架构、核心能力与API获取指南
  • 梯度下降的基本原理
  • 如何改变Jupyter的默认保存路径?
  • 电子邮箱域名解析原理
  • Scene as Occupancy
  • 深入剖析Spring IOC容器——原理、源码与实践全解析
  • Charles中文版抓包工具详解 实现API调试提效与流量分析优化
  • 肖特基二极管MBR0540T1G 安森美ON 低电压 高频率 集成电路IC 芯片
  • Linux 系统监控脚本实战:磁盘空间预警、Web 服务与访问测试全流程
  • 嵌入式 Linux 深度解析:架构、原理与工程实践(增强版)
  • 60 GHz DreamHAT+ 雷达已被正式批准为“Powered by Raspberry Pi”产品
  • 浏览器【详解】requestIdleCallback(浏览器空闲时执行)
  • CS224n:Word Vectors and Word Senses(二)
  • LOVON——面向足式Open-Vocabulary的VLN导航:LLM做任务分解、YOLO11做目标检测,最后L2MM将指令和视觉映射为动作,且解决动态模糊
  • 九联UNT403HS_海思MV320处理器_安卓9-优盘强刷刷机包
  • 从内部保护你的网络
  • Android ConstraintLayout 使用详解
  • CAN总线协议
  • 【机器学习与数据挖掘实战 | 医疗】案例20:基于交叉验证和LightGBM算法的糖尿病遗传风险预测
  • FastDDS (SharedMemory)
  • Mysql监控数据库
  • synchronized 深度剖析:从语法到锁升级的完整演进
  • VSCode:通义灵码插件安装使用 -- 免费AI编程工具