python计算机视觉 相机标定--张正友棋盘格标定法
目录
前言
环境
一、实验原理
1.1 相机标定简介
1.2 算法流程
1.3 计算单应性矩阵H
1.4 计算内参数矩阵
1.5 计算外参数矩阵
1.6 最大似然估计
二、代码实现
三、实验结果与分析
3.1 数据集
3.2 实验结果
总结
前言
此次实验将用张正友棋盘格标定法对相机参数进行标定。”张正友标定法”是指张正友教授1998年提出的单平面棋盘格的摄像机标定方法。文中提出的方法介于传统标定法和自标定法之间,但克服了传统标定法需要的高精度标定物的缺点。相对于自标定而言,提高了精度,便于操作。因此张正友标定法被广泛应用于计算机视觉方面。
环境
win10,python3.8.5,opencv4.5.3,pycharm,用于标定的手机型号:荣耀20
一、实验原理
1.1 相机标定简介
在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型参数就是相机参数。在大多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之为相机标定(或摄像机标定)。无论是在图像测量或者机器视觉应用中,相机参数的标定都是非常关键的环节,其标定结果的精度及算法的稳定性直接影响相机工作产生结果的准确性。
1.2 算法流程
(1)打印一张棋盘方格图并贴在一个平面上
(2)从不同角度拍摄若干张模板图像
(3)检测出图像中的特征点
(4)由检测到的特征点计算出每幅图像中的平面投影矩阵H
(5)确定出摄像机的参数
1.3 计算单应性矩阵H
单应性:在计算机视觉中被定义为一个平面到另一个平面的投影映射。首先确定,图像平面与标定物棋盘格平面的单应性。
设三维世界坐标的点为 ,二维相机平面像素坐标为,所以标定用的棋盘格平面到图像平面的单应性关系为: (其中,K为相机的内参矩阵,R为外部参数矩阵(旋转矩阵),T为平移向量。令:
设棋盘格位于Z=0的平面,定义旋转矩阵R的第i列为 ri, 则有:
于是空间到图像的映射可改为:H=λK[r1 r2 t]
其中H 是描述Homographic矩阵,可通过最小二乘,从角点世界坐标到图像坐标的关系求解。
1.4 计算内参数矩阵
内参矩阵:
其中,fx,fy为焦距,一般情况下,二者相等,u0、v0为主点坐标(相对于成像平面),s为坐标轴倾斜参数,理想情况下为0。
根据步骤1中的式子,令 H 为 H = [h1 h2 h3],则 [h1 h2 h3]=λK[r1 r2 t],再根据正交和归一化的约束可以得到等式:
即每个单应性矩阵能提供两个方程,而内参数矩阵包含5个参数,要求解,至少需要3个单应性矩阵。为了得到三个不同的单应性矩阵,我们使用至少三幅棋盘格平面的图片进行标定。通过改变相机与标定板之间的相对位置来得到三个不同的图片。为了方便计算,我们定义:
B 中的未知量可表示为6D 向量 b,
设H中的第i列为 hi,,根据b的定义,可以推导出公式,,
最后推导出:
通过上式,我们可知当观测平面 n ≥ 3 时,即至少3幅棋盘格图像,可以得到b的唯一解,求得相机内参数矩阵K。
1.5 计算外参数矩阵
外部参数可通过Homography求解,由 H = [h1 h2 h3] = λA[r1 r2 t],可推出
1.6 最大似然估计
上述的推导结果是基于理想情况下而言,但由于可能存在一些其他干扰,所以使用最大似然估计进行优化。假设拍摄了n张棋盘格图像,每张图像有m个角点。最终获得的最大似然估计公式为:
二、代码实现
import cv2
import numpy as np
import glob# 找棋盘格角点
# 棋盘格模板规格(内角点个数,内角点是和其他格子连着的点,如10 X 7)
w = 10
h = 7# 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵
objp = np.zeros((w * h, 3), np.float32)
objp[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)# 储存棋盘格角点的世界坐标和图像坐标对
objpoints = [] # 在世界坐标系中的三维点
imgpoints = [] # 在图像平面的二维点# 标定所用图像(路径不能有中文)
images = glob.glob('D:\\python\\RRJ\\pycharmproject\\img_qipan\\*.jpg') size = tuple()
for fname in images:img = cv2.imread(fname)# 修改图像尺寸,参数依次为:输出图像,尺寸,沿x轴,y轴的缩放系数,INTER_AREA在缩小图像时效果较好# img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转灰度size = gray.shape[::-1] # 矩阵转置# 找到棋盘格角点# 棋盘图像(8位灰度或彩色图像) 棋盘尺寸 存放角点的位置ret, corners = cv2.findChessboardCorners(gray, (w, h), None)# 角点精确检测# criteria:角点精准化迭代过程的终止条件(阈值)criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)# 执行亚像素级角点检测corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)objpoints.append(objp)imgpoints.append(corners2)# 将角点在图像上显示cv2.drawChessboardCorners(img, (w, h), corners2, ret)cv2.imshow('findCorners', img)cv2.waitKey(1000)"""
标定、去畸变:
输入:世界坐标系里的位置 像素坐标 图像的像素尺寸大小 3*3矩阵,相机内参数矩阵 畸变矩阵
输出:标定结果 相机的内参数矩阵 畸变系数 旋转矩阵 平移向量
"""ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, size, None, None)# mtx:内参数矩阵
# dist:畸变系数
# rvecs:旋转向量 (外参数)
# tvecs :平移向量 (外参数)
print("ret:", ret)
print("内参数矩阵:\n", mtx,'\n')
print("畸变系数:\n", dist,'\n')
print("旋转向量(外参数):\n", rvecs,'\n')
print("平移向量(外参数):\n", tvecs,'\n')# 去畸变
img2 = cv2.imread('D:\\python\\RRJ\\pycharmproject\\img_qipan\\03.jpg')
h, w = img2.shape[:2]# 我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,
# 通过设定自由自由比例因子alpha。当alpha设为0的时候,
# 将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数;
# 当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0, (w, h)) # 自由比例参数dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根据前面ROI区域裁剪图片
x, y, w, h = roi
dst = dst[y:y + h, x:x + w]
cv2.imwrite('calibresult.jpg', dst)# 反投影误差
# 通过反投影误差,我们可以来评估结果的好坏。越接近0,说明结果越理想。
total_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)total_error += error
print("total error: ", total_error / len(objpoints))
三、实验结果与分析
3.1 数据集
使用手机相机一共拍摄16张棋盘格图片,图片统一尺寸为640 X 480,纸张大小为a4,棋盘格大小为11X8个格子,每个格子大小为20X20mm,使用数据集的时候没有取到边缘,所取内角点(内角点是和其他格子连着的点)维数为10X7。
注:可以自定义生成棋盘格的网站:Camera Calibration Pattern Generator – calib.io
3.2 实验结果
角点检测结果:
内参矩阵:
畸变矫正系数:
外参矩阵:
旋转向量(外参数):(array([[-0.13574861],[ 0.05697355],[ 3.13350596]]), array([[ 0.09763508],[-0.58204812],[ 3.06407074]]), array([[ 0.6371049 ],[-0.03960999],[ 3.06533588]]), array([[-0.18596374],[-0.84234494],[-3.02464722]]), array([[-0.41352155],[ 0.04807884],[ 3.09358438]]), array([[-0.2764872 ],[-0.50110721],[-2.28204581]]), array([[-0.87573537],[-0.87595743],[-1.37465394]]), array([[-0.99317253],[-0.65794883],[-1.45562632]]), array([[-0.34444459],[ 0.21117631],[ 1.49004618]]), array([[-0.23725349],[-0.01588308],[ 3.12446843]]), array([[ 0.01333567],[ 0.4444543 ],[-2.73788549]]), array([[-0.09230451],[-0.67340521],[-2.62675435]]), array([[-0.83846876],[-0.70618338],[-1.39987785]]), array([[-0.70346773],[-1.0445802 ],[-1.66009963]]), array([[-0.76233494],[-0.79819236],[-1.46212885]]), array([[-0.92014765],[-0.6573154 ],[-1.30348693]]))
平移向量(外参数):(array([[ 4.33992147],[ 3.20461266],[25.50518027]]), array([[ 4.83495684],[ 4.30085856],[36.95686148]]), array([[ 4.38643528],[ 3.32200755],[38.92063105]]), array([[ 4.80858473],[-0.59025077],[38.33614799]]), array([[ 6.58349275],[ 3.80278574],[41.33467124]]), array([[ 2.40987231],[ 4.346225 ],[38.21224958]]), array([[-3.09262496],[ 1.53775077],[21.28916175]]), array([[-5.01874752],[ 2.42168125],[26.88383921]]), array([[ 2.0347435 ],[-5.05948588],[38.91132325]]), array([[ 4.86833702],[ 3.1391252 ],[24.09973994]]), array([[ 3.53867938],[ 4.7001667 ],[34.05130555]]), array([[ 3.45738916],[ 3.96954972],[31.61499944]]), array([[-3.64065316],[ 2.26176972],[16.30708336]]), array([[-1.80330323],[ 2.0031509 ],[19.49963915]]), array([[-3.50827638],[ 2.30841025],[22.32331089]]), array([[-3.1779834 ],[ 1.74494483],[20.73884832]]))
total error:
从实验结果来看,,归一化焦距fx=1.14788404e+03(e+03表示10的3次方.),fy=1.14707472e+03,像主点(光心)的坐标cx=3.15039178e+02,cy=2.31846558e+02,相机标定的误差在0.31,基本可以接受,还需进一步改进;从角点的检测结果来看,正确率还是很高的,可以很好的识别出黑白棋盘格上的角点,几乎没有错误。
接着通过MATLAB自带的工具箱进行相机标定得到相机参数表进行对照,在应用程序中找到Camera Calibrator,然后Add Images添加图片文件,在弹框内修改自己的棋盘格尺寸(图片尺寸大小要统一),Calibrate标定就可以了。具体操作指南见:(1条消息) 相机标定(Camera calibration)原理、步骤_AI人工智能科学的博客-CSDN博客_cmos相机标定
角点检测:
参数结果:
在命令窗口输入以下命令即可获得内参矩阵和径向畸变:
内参矩阵命令:cameraParams.IntrinsicMatrix
径向畸变命令:cameraParams.RadialDistortion
Matlab得到的是内参矩阵的转置矩阵,归一化焦距fx=1.1019e+03,fy=1.0963e+03。
可以看出误差还是挺大的,普遍认为Matlab得到的是内参矩阵更为可靠。
修改图片大小为(1080 X 810)再次测试:
可以看到图像不压缩的情况下 fx 之间的误差有微量较少,但是反投影误差却会增大。因此尽量保持图像压缩较小的情况下会得到比较好的结果。
总结
参考文章
(1)(1条消息) python计算机视觉-图像处理基础之相机标定_我超爱Debug的博客-CSDN博客_python相机标定
(2)(1条消息) 【计算机视觉】张正友棋盘格标定法_Rolla_的博客-CSDN博客_棋盘格标定
python计算机视觉 相机标定--张正友棋盘格标定法相关推荐
- 相机标定——张正友棋盘格标定法
目录 为什么需要相机标定? 相机标定可以做什么? 相机标定后可以得到什么? 什么情况下需要借助相机标定的方法? 相机标定的原理 实现相机标定的方法 为什么需要相机标定? 一个是由于每个镜头的在生产和组 ...
- 【计算机视觉】张正友棋盘格标定法
目录 前言 环境 (一)实验原理/步骤 1.计算单应性矩阵H 2.计算内参数矩阵 3.计算外参数矩阵 4.最大似然估计 (二)实验代码 (三)实验结果分析 (四)实验总结 前言 "张正友标定 ...
- 计算机视觉——张正友棋盘格标定法
文章目录 环境 前言 一.实验原理 1.相机标定 2.张正友标定法 3.步骤 二.实验过程 1.实验步骤 2.结果展示 3.分析 三.问题和总结 环境 win10,64位,python2.7,编译器: ...
- python实现张正友棋盘格标定法
文章目录 1.原理 1.1相机的内参数 1.2张氏标定法 1.3切向畸变与径向畸变 2.环境与代码 2.1棋盘环境 2.2图片选取 2.3代码 3.实验结果与分析 3.1角点检测结果 3.2内参结果截 ...
- python棋盘格_python实现张正友棋盘格标定法
文章目录1.原理1.1相机的内参数1.2张氏标定法1.3切向畸变与径向畸变2.环境与代码2.1棋盘环境2.2图片选取2.3代码3.实验结果与分析3.1角点检测结果3.2内参结果截图3.3外参结果截图3 ...
- 计算机视觉——python3实现张正友棋盘相机标定图像
照相机标定 前言:相机标定是我们相机拍摄的物体都处于三维世界坐标系中,而相机拍摄成像时把三维相机坐标系向二维图像坐标系转换.不同镜头成像时的转换矩阵不同可能引入失真,标定的作用是近似地估算出转换矩阵和 ...
- [毕设系列] 一、张正友相机标定
张正友相机标定 预备知识 0.1 刚体.仿射.线性.旋转变换 0.2 什么是标定? 0.3 为什么要进行标定? 0.4 什么是畸变? 一.张正友标定法 1.1 简介 1.2 流程 1.3 畸变公式 二 ...
- 基于python的opencv相机标定(采用黑白棋盘格标定板)
基于python的相机标定(采用黑白棋盘格图片) 系列文章目录 [第一章 基于python的相机标定(采用黑白棋盘格图片)](https://blog.csdn.net/HWHXXX/article/ ...
- python 倒数两列_相机标定之张正友标定法数学原理详解(含python源码)
一.相机标定的目的 我们首先要明白两个问题:1.相机是如何成像的?2.相机标定的目的是什么? 1.相机是如何成像的呢? 相机成像系统中,共包含四个坐标系:世界坐标系.相机坐标系.图像坐标系.像素坐标系 ...
- 【计算机视觉】张正友标定法相机标定
目录 一.相机标定 二.张正友标定法 2.1 张正友标定法概述 2.2 张正友标定法原理 2.2.1 坐标系 2.2.2 内参矩阵计算 2.2.3 外参矩阵计算 2.2.4 极大似然估计 2.2.5 ...
最新文章
- 微信小程序,时间戳和日期格式互相转化
- python中怎么计数_浅谈python中统计计数的几种方法和Counter详解
- HDFS上传文件报错java.lang.InterruptedException
- IO模型(epoll)--详解-01
- flash绘制荷花多个图层_Flash鼠绘入门第八课:绘制脱俗荷花
- linux怎么判断全局符号,Linux下全局符号覆盖有关问题
- JDBC_ResultSet类_结果集对象
- webpack文件系统缓存
- 文件名lin.php是什么,Linsexu程序安装PHP详细软件教程
- Sqoop Java API 导入应用案例
- 计组_IEEE754_练习题
- AWS携手光环云助力2019第三届“中信建投证券杯”世界智能围棋公开赛
- 贪心算法之猴子吃香蕉(Monkeys and Bananas)
- 家用计算机常见故障及解决方式,常见电脑故障及处理办法 计算机常见故障原因及解决方法...
- 杂牌蓝牙在2003系统使用新驱动的破解方法!
- 体验管理,猪飞不起来的风口
- 关于JS中的内存溢出与内存泄漏
- 学人工智能必备的数学课,再也不怕学AI了
- 仿起点中文网的小说网站——JavaEE大作业
- 【webpack浅析】webpack之深入浅出
热门文章
- 腾讯会议 .wemta 文件如何转码成 mp4 文件
- 【转】java将excel文件转换成txt格式文件
- 聊聊测试覆盖率的六大门派
- 转:企业数字化的本质,其实就这3条
- 自动驾驶公司如何打造产品市场体系
- IP摄像头实现远程目标检测(rtsp)
- css3做的好看的小便签,纯CSS3 便签条折角效果
- Table is marked as crashed and should be repaire (
- YAPI自动生成接口文档,解放测试人生产力...
- GPU Pro 7——实时体积云(翻译,附Unity工程)