news 2026/4/26 20:56:36

张氏相机标定,不求甚解使用篇

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
张氏相机标定,不求甚解使用篇

本文记录使用张氏标定法进行使用的全过程,并记录最终的误差成果,为什么需要标定是因为相机本身拍照之后,就存在一个畸变,所以仅靠一个比例尺来进行推算实际距离 和 像素距离之间的比例,是存在很大的偏差的,理解一下,拍完照就存在了,后面你怎么计算都会存在问题。以及标定结束之后,相机是固定的,一旦相机移动,或者焦距发生改变,就需要重新进行标定,而且标定之后,同样只是在一个平面内进行比例尺的测算才会准确,一旦,物体变为三维,到相机镜头的工作距离发生改变,那么计算之后的误差同样会变大。

1.首先需要找到对应的实验器材

硬件:相机机架,相机,直尺,以及标定板(可以自己制作)

软件:能够实现相机拍照,自己使用SDK进行二次开发,能够使用开源的opnecv 库进行计算对应的校正值,在新的程序中c++中进行使用。

2.实验步骤:

2.1.制作标定板,先去相机校准图案生成器 – calib.io ,生成对应的标定PDF,如下图

上述为本人使用的样式,然后打印为A4纸张。但是最终实际测量一个小方格的边长为13mm。需要根据实际测算的边长进行更改。然后方格数量为8 * 11 ,由此可知,角点数量为7 * 10,(角点就是实际上的两个方块相交的点)。然后将标定板固定到一个完全平滑的板子上。

2.1.拍照,在相机固定固定之后,接下来需要拍摄几张十分干净,标准的照片进行标定。特点如下

标定板清晰无模糊

角度覆盖充分但不过度

相机固定不动,最好是10张以上。

2.1.然后就是使用vs code,使用python语言来进行标定脚本的书写,运行程序,得出对应的标定结果。脚本如下,此处不在赘述,怎么去配置环境,等等

import numpy as np import cv2 import glob # 1. 准备标定板参数 chessboard_size = (7, 10) # 内角点数量 square_size = 13.0 # 毫米 # 2. 生成世界坐标系中的3D点 objp = np.zeros((chessboard_size[0]*chessboard_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) * square_size # 3. 存储对象点和图像点 objpoints = [] # 3D点 imgpoints = [] # 2D点 # 4. 读取所有标定图像 images = glob.glob('D:/DeepLearning/datasets/clibration/rect/*.png') image_size = None for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if image_size is None: image_size = gray.shape[::-1] # 查找棋盘格角点 ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None) if ret: objpoints.append(objp) # 亚像素精确化 corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) imgpoints.append(corners2) # 可视化角点 cv2.drawChessboardCorners(img, chessboard_size, corners2, ret) cv2.imshow('Corners', img) cv2.imwrite("this.png",img) cv2.waitKey(500) cv2.destroyAllWindows() # 5. 相机标定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, image_size, None, None) print("相机内参矩阵:\n", mtx) print("\n畸变系数:", dist.ravel()) # 6. 评估标定误差 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平均重投影误差: {} 像素".format(mean_error/len(objpoints))) # 7. 保存标定结果 np.savez('calibration_result.npz', mtx=mtx, dist=dist)

注意,其中参数的改写,以及对应的路径的变更

# 1. 准备标定板参数
chessboard_size = (7, 10) # 内角点数量
square_size = 13.0 # 毫米

以及文件路径。

2.2.运行得到结果如下

相机内参矩阵:
[[2.78225009e+03 0.00000000e+00 1.20301433e+03]
[0.00000000e+00 2.77841102e+03 1.00512050e+03]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]

畸变系数: [-0.2517598 0.07004305 -0.00127046 0.00606034 0.24205241]

平均重投影误差: 0.07069074329111907 像素

由此可知,标定结果还可以,主要看重投影误差,为0.07,当然其他参数一会同样需要使用。


2.3.将参数使用到对相机拍摄的照片进行校正,需要会SDK取图,并且取图之后,能够进行处理,如下,为拍摄照片之后的处理代码。

cv::Mat CFormal_DecDlg::FastUndistort(const cv::Mat& input) { static cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << 2782.25009, 0.0, 1203.01433, 0.0, 2778.41102, 1005.1205, 0.0, 0.0, 1.0); static cv::Mat distCoeffs = (cv::Mat_<double>(1, 5) << -0.2517598, 2.77841102, 0.00127046, 0.00606034, -0.24205241); static cv::Mat map1, map2; static cv::Size lastSize(0, 0); // 如果尺寸变化或第一次,计算映射 if (map1.empty() || input.size() != lastSize) { cv::Mat newCameraMatrix = cv::getOptimalNewCameraMatrix( cameraMatrix, distCoeffs, input.size(), 1.0, input.size() ); cv::initUndistortRectifyMap( cameraMatrix, distCoeffs, cv::Mat(), newCameraMatrix, input.size(), CV_32FC1, map1, map2 ); lastSize = input.size(); } cv::Mat result; cv::remap(input, result, map1, map2, cv::INTER_LINEAR); return result; }

,对图像进行处理之后,会得到下述样式的图像,即校正之后的图像。

,本人随机取出中间的两个点(590,1069) (718.1074),进过转换如下

首先,提取并整理你的相机参数:

  • 相机内参矩阵 (K):

    text

    fx = 2782.25009 # 图像x轴方向焦距 fy = 2778.41102 # 图像y轴方向焦距 cx = 1203.01433 # 图像主点坐标x cy = 1005.12050 # 图像主点坐标y
  • 畸变系数 (D):[-0.2517598, 0.07004305, -0.00127046, 0.00606034, 0.24205241]

  • 工作距离 (Z): 285 mm

  • 图像点:

    • 点 A:(590, 1069)

    • 点 B:(718, 1074)

计算步骤如下:

  1. 校正畸变:由于畸变会改变像素点的理想位置,计算前需先去除畸变影响。

    • 点 A 校正后:(588.31, 1068.75)

    • 点 B 校正后:(716.08, 1073.85)

  2. 像素坐标转归一化相机坐标
    公式为:
    X_normal = (x_corrected - cx) / fx
    Y_normal = (y_corrected - cy) / fy

    • 点 A 归一化坐标:(-0.2209, 0.0229)

    • 点 B 归一化坐标:(-0.1751, 0.0247)

  3. 归一化坐标转实际三维坐标
    已知实际工作距离(Z = 285 mm),通过相似三角形计算:
    X_real = X_normal * Z
    Y_real = Y_normal * Z

    • 点 A 实际坐标:(-62.95 mm, 6.53 mm, 285.00 mm)

    • 点 B 实际坐标:(-49.89 mm, 7.05 mm, 285.00 mm)

  4. 计算三维空间距离
    利用三维空间两点间距离公式计算:
    最终距离 D = √((X_B - X_A)² + (Y_B - Y_A)² + (Z_B - Z_A)²) = 13.09 mm

结果为13.09,即实际距离为13.09,是校正之后,进行计算的结果。跟13mm十分的接近,说明标定方法是可以的。

除开上述的反投影法计算实际距离之外,还存在另外的方法,计算比例尺

  • 原理:在焦距f(像素) 和工作距离Z(毫米) 已知时,图像传感器上一个像素对应的实际尺寸是固定的。

  • 计算:比例尺S(毫米/像素) =Z / f

    • 在X方向:S_x = Z / fx = 285 / 2782.25009 ≈ 0.10245 mm/像素

    • 在Y方向:S_y = Z / fy = 285 / 2778.41102 ≈ 0.10256 mm/像素

  • 距离:两点像素坐标差Δx = 718 - 590 = 128 像素Δy = 1074 - 1069 = 5 像素

  • 实际距离D = √((Δx * S_x)² + (Δy * S_y)²) = √((128*0.10245)² + (5*0.10256)²) ≈ √(172.14 + 0.263) ≈ √172.40 ≈ 13.13 mm

同样误差很小,一般可以投入实际使用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 16:53:19

ssm489外婆家网上订餐平台--论文

目录具体实现截图摘要系统所用技术介绍写作提纲源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 摘要 随着互联网技术的快速发展和移动设备的普及&#xff0c;线上订餐平台已成为餐饮行业数字化转型的重要组成部分。本文以…

作者头像 李华
网站建设 2026/4/25 18:55:36

ssm497医院预约挂号系统--论文

目录具体实现截图摘要系统所用技术介绍写作提纲源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 摘要 随着信息技术的快速发展&#xff0c;传统医院挂号方式已无法满足患者高效、便捷的医疗需求。为提高医院挂号效率&…

作者头像 李华
网站建设 2026/4/25 8:41:17

day138—快慢指针—删除链表的倒数第N个结点(LeetCode-19)

题目描述给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。示例 1&#xff1a;输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a;输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#xf…

作者头像 李华
网站建设 2026/4/23 18:55:22

【计算机毕业设计案例】基于springboot的宠物医院中小型宠物医院、连锁宠物诊疗机构管理系统的设计与实现(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/25 10:22:05

Android设备与Mac/Docker全连接指南:有线到无线的完整方案

Android设备与Mac/Docker全连接指南&#xff1a;有线到无线&#x1f4ca; 连接方式对比表&#x1f50c; 方式一&#xff1a;USB有线连接&#xff08;基础方式&#xff09;适用场景操作步骤&#x1f4e1; 方式二&#xff1a;WiFi无线连接2.1 Android 10及以下版本&#xff08;需…

作者头像 李华
网站建设 2026/4/26 18:05:01

解码WIFI模块与IoT云平台

WIFI模块原理与应用 引言 随着物联网技术快速发展&#xff0c;越来越多的智能设备需要通过无线方式接入互联网。在众多无线通信方案中&#xff0c;**WIFI模组&#xff08;ESP8266/ESP32系列&#xff09;**因其成熟的生态和广泛的应用&#xff0c;成为实现远程控制、数据采集等…

作者头像 李华