OpenCV实现相机标定
作者:Ohayo33 发布时间:2023-11-13 00:36:45
本文实例为大家分享了OpenCV实现相机标定的具体代码,供大家参考,具体内容如下
一、相机与 * 相机模型
1.相机模型
现代科技加持下的相机已经成为制造精密设计巧妙的消费品,相机的光学结构也比诞生之初复杂了许多
典型单反相机光学结构:
在众多相机模型中, * 相机又称投影相机模型是相对简单而常用的模型。简单的说, * 相机模型就是把相机简化成单纯的小孔成像,可想而知,这种简化对于精度要求高的情况或者特殊镜头的相机是不适用的。
小孔成像原理:
2.引入透镜
单纯的小孔成像模型中没有考虑镜头,现实条件下,由一片或多片透镜组成的镜头才能让利用了小孔成像原理的相机成像清晰的同时保持画面亮度。所以我们需要向模型引入透镜。
透镜成像原理:
但是,新的问题也随之而来:虚焦、畸变
一般我们称之为径向畸变,即光线在院里透镜中的地方比靠近中心的地方更加弯曲。径向畸变又分为中短焦距、近距离的桶形畸变和长焦距、远距离会出现的枕形畸变。
二、相机参数
1.坐标系约定
我们约定三个坐标系
1、世界坐标系矩阵:X
2、摄像机坐标系:Xc,
3、图像(像素)坐标系:x
4、相机矩阵:P
2.像平面到像素平面的投影
将三维空间中一点,过该点取一平面与像素平面平行,该平面就是像平面。设该三位点P,齐次坐标为X。投影为图像点P’,平面坐标x。
* 相机模型:
在 * 相机模型中,像素坐标和像坐标之间的关系:
λx = PX
其中,λ是三位点的逆深度。P为相机矩阵,可以分解为:
P = R[K|t]
R 是描述照相机方向的旋转矩阵,t 是描述照相机中心位置的三维平移向量,内标定矩阵K 描述照相机的投影性质。标定矩阵仅和照相机自身的情况有关,通常可以写成:
焦距f是像在平面到像素平面中心的距离。s是倾斜参数,α是纵横比例参数。
在像素数组在传感器上没有偏斜且像素是正方形的时候,可以设 s = 0,α = 1。标定矩阵可以简化为:
三、相机标定
实验图片如下:
代码如下:
import cv2
import numpy as np
import glob
# 找棋盘格角点
# 阈值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盘格模板规格
w = 7 #内角点个数,内角点是和其他格子连着的点
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('picture/*.jpg')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 找到棋盘格角点
# 棋盘图像(8位灰度或彩色图像) 棋盘尺寸 存放角点的位置
ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
# 如果找到足够点对,将其存储起来
if ret == True:
# 角点精确检测
# 输入图像 角点初始坐标 搜索窗口为2*winsize+1 死区 求角点的迭代终止条件
cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
objpoints.append(objp)
imgpoints.append(corners)
# 将角点在图像上显示
cv2.drawChessboardCorners(img, (w,h), corners, ret)
cv2.imshow('findCorners',img)
cv2.waitKey(1000)
cv2.destroyAllWindows()
#标定、去畸变
# 输入:世界坐标系里的位置 像素坐标 图像的像素尺寸大小 3*3矩阵,相机内参数矩阵 畸变矩阵
# 输出:标定结果 相机的内参数矩阵 畸变系数 旋转矩阵 平移向量
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# mtx:内参数矩阵
# dist:畸变系数
# rvecs:旋转向量 (外参数)
# tvecs :平移向量 (外参数)
print (("ret:"),ret)
print (("mtx:\n"),mtx) # 内参数矩阵
print (("dist:\n"),dist) # 畸变系数 distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print (("rvecs:\n"),rvecs) # 旋转向量 # 外参数
print (("tvecs:\n"),tvecs) # 平移向量 # 外参数
# 去畸变
img2 = cv2.imread('picture/6.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,说明结果越理想。
# 通过之前计算的内参数矩阵、畸变系数、旋转矩阵和平移向量,使用cv2.projectPoints()计算三维点到二维图像的投影,
# 然后计算反投影得到的点与图像上检测到的点的误差,最后计算一个对于所有标定图像的平均误差,这个值就是反投影误差。
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))
来源:https://blog.csdn.net/Ohayo33/article/details/117135936


猜你喜欢
- Python小白一只,正在成长,程序自己设计,很多不足,算法很多地方能优化。欢迎大佬来指教。游戏效果创建设置类,储存游戏基础数据可以不使用这
- MySQL 日期时间教程 在本教程中,我将通过示例解释 MySQL DATE 和 TIME 函数。 DA
- Django的View一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。响应可以是一张
- 安装PandasPandas是构建在Python编程语言之上的一个快速、强大、灵活且易于使用的开源数据分析和操作工具。Pandas是基于Nu
- 简单版本学生信息管理系统,用python基础语法实现,基于python 3.6容错率很高的代码,做了很多异常处理功能,出错也不会丢失信息启动
- 简介ping (Packet Internet Groper)是一种因特网包探索器,用于测试网络连接量的程序 。Ping是工作在 TCP/I
- 在Python中有时会碰到需要一个一维列向量(n*1)与另一个一维列向量(n*1)的转置(1*n)相乘,得到一个n*n的矩阵的情况。但是在p
- 一、描述:以module的方式组件python代码,在磁盘文件清理上复用性更好二、达到目标: 清空过期
- 1、为什么要创建用户签名作为版本控制系统的客户端,每台客户机对版本库的所有提交操作,都需要注明操作者的身份。所以客户机首先需要进行自我身份的
- opencv 进行任意形状目标识别,供大家参考,具体内容如下工作中有一次需要在简单的图上进行目标识别,目标的形状不固定,并且存在一定程度上的
- 写在前面的话基于dlib库的模型,实现人脸识别和焦点人物的检测。最后呈现的效果为焦点人物的识别框颜色与其他人物框不一样。准备工作需要安装好p
- 不少同学一提到泰勒公式,脑海里立马浮现高大上的定义和长长的公式,令人望而生畏。实际上,泰勒公式没有那么可怕,它是用简单的多项式来逼近一个光滑
- 最近在作图时需要将输出的图片紧密排布,还要去掉坐标轴,同时设置输出图片大小。要让程序自动将图表保存到文件中,代码为:plt.savefig(
- 遇到的问题:用户批量导入数据1000条,导入不成功的问题,提示查询不到商品资料。这个场景需要依靠批量的数据,每次测试的时候需要手动生成批量的
- jupyter中显示的DataFrame过长时会自动换行(print()显示方式)或自动省略(单元格最后一行直接显示),在一些情况下看上去不
- 使用 NetBox 可以方便的将 asp 应用编译成为独立运行的执行程序,完全摆脱 iis 的束缚,在几乎所有的 Windows 版本上面直
- 在Oracle SQL的where子句中传入字符类型参数'19-11月-08',使得可以直接和日期类型比较,或者转换一下同日
- 工作时同事间几mb小文件的传输,一般使用QQ或者微信就足够了,但当传输文件几百MB或者几十G时,这种方法的效率就显得不足了。本篇就是简单说明
- SQL Server 出现Error: 1326错误我们在在使用SQL Server时都会遇到使用SQL Server Management
- 创建Dataframe主要是使用pandas中的DataFrame函数,其核心就是第一个参数:data,传入原始数据,因此我们可以据此给出六