import os
2.编写函数
本次主要有两个比较麻烦的要解决,其一,批量读取,第二,真实坐标的写入。我使用os编写的读取文件函数,比较垃圾,大佬请用glob或者其他的。真实坐标主要是标定板上内点的真实相片坐标,通过参考其他大佬总结的出
def getImageList(img_dir):
# 获取图片文件夹位置,方便opencv读取
# 参数:照片文件路径
# 返回值:数组,每一个元素表示一张照片的绝对路径
imgPath = []
if os.path.exists(img_dir) is False:
print('error dir')
else:
for parent, dirNames, fileNames in os.walk(img_dir):
for fileName in fileNames:
imgPath.append(os.path.join(parent, fileName))
return imgPath
def getObjectPoints(m, n, k):
# 计算真实坐标
# 参数:内点行数,内点列, 标定板大小
# 返回值:数组,(m*n行,3列),真实内点坐标
objP = np.zeros(shape=(m * n, 3), dtype=np.float32)
for i in range(m * n):
objP[i][0] = i % m
objP[i][1] = int(i / m)
return objP * k
3.主程序
# 相机标定参数设定(单目,双目)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
criteria_stereo = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 计算标定板真实坐标,标定板内点9*6,大小10mm*10mm
objPoint = getObjectPoints(9, 6, 10)
objPoints = []
imgPointsL = []
imgPointsR = []
# 相片路径,自行修改
imgPathL = 'D:/SA/2021.3/6.1/l/'
imgPathR = 'D:/SA/2021.3/6.1/r/'
filePathL = getImageList(imgPathL)
filePathR = getImageList(imgPathR)
for i in range(len(filePathL)):
# 分别读取每张图片并转化为灰度图
imgL = cv2.imread(filePathL[i])
imgR = cv2.imread(filePathR[i])
grayL = cv2.cvtColor(imgL, cv2.COLOR_BGR2GRAY)
grayR = cv2.cvtColor(imgR, cv2.COLOR_BGR2GRAY)
# opencv寻找角点
retL, cornersL = cv2.findChessboardCorners(grayL, (9, 6), None)
retR, cornersR = cv2.findChessboardCorners(grayR, (9, 6), None)
if (retL & retR) is True:
# opencv对真实坐标格式要求,vector<vector<Point3f>>类型
objPoints.append(objPoint)
# 角点细化
cornersL2 = cv2.cornerSubPix(grayL, cornersL, (5, 5), (-1, -1), criteria)
cornersR2 = cv2.cornerSubPix(grayR, cornersR, (5, 5), (-1, -1), criteria)
imgPointsL.append(cornersL2)
imgPointsR.append(cornersR2)
# 对左右相机分别进行单目相机标定(复制时格式可能有点问题,用pycharm自动格式化)
retL, cameraMatrixL, distMatrixL, RL, TL = cv2.calibrateCamera(objPoints, imgPointsL, (640, 480), None, None)
retR, cameraMatrixR, distMatrixR, RR, TR = cv2.calibrateCamera(objPoints, imgPointsR, (640, 480), None, None)
# 双目相机校正
retS, mLS, dLS, mRS, dRS, R, T, E, F = cv2.stereoCalibrate(objPoints, imgPointsL,
imgPointsR, cameraMatrixL,
distMatrixL, cameraMatrixR,
distMatrixR, (640, 480),
criteria_stereo, flags=cv2.CALIB_USE_INTRINSIC_GUESS)
# 标定结束,结果输出,cameraMatrixL,cameraMatrixR分别为左右相机内参数矩阵
# R, T为相机2与相机1旋转平移矩阵
print(cameraMatrixL)
print('*' * 20)
print(cameraMatrixR)
print('*' * 20)
print(R)
print('*' * 20)
print(T)
4.其他一些问题
1.关于真实坐标。这个是以标定板为平面z=0的内点真实坐标,单独输出就是这样的。是标定板由左上内点开始,然后是右侧点,接着下面的点:(是这个顺序)。
其次,仔细看opencv图片可以发现内点9*6和6*9是一样的,你可以自己试试,我试过了,一样的
a = getObjectPoints(9, 6, 10)
print(a)
[[ 0. 0. 0.]
[10. 0. 0.]
[20. 0. 0.]
[30. 0. 0.]
[40. 0. 0.]
[50. 0. 0.]
[60. 0. 0.]
[70. 0. 0.]
[80. 0. 0.]
[ 0. 10. 0.]
[10. 10. 0.]
[20. 10. 0.]
[30. 10. 0.]
[40. 10. 0.]
[50. 10. 0.]
[60. 10. 0.]
[70. 10. 0.]
[80. 10. 0.]
[ 0. 20. 0.]
[10. 20. 0.]
[20. 20. 0.]
[30. 20. 0.]
[40. 20. 0.]
[50. 20. 0.]
[60. 20. 0.]
[70. 20. 0.]
[80. 20. 0.]
[ 0. 30. 0.]
[10. 30. 0.]
[20. 30. 0.]
[30. 30. 0.]
[40. 30. 0.]
[50. 30. 0.]
[60. 30. 0.]
[70. 30. 0.]
[80. 30. 0.]
[ 0. 40. 0.]
[10. 40. 0.]
[20. 40. 0.]
[30. 40. 0.]
[40. 40. 0.]
[50. 40. 0.]
[60. 40. 0.]
[70. 40. 0.]
[80. 40. 0.]
[ 0. 50. 0.]
[10. 50. 0.]
[20. 50. 0.]
[30. 50. 0.]
[40. 50. 0.]
[50. 50. 0.]
[60. 50. 0.]
[70. 50. 0.]
[80. 50. 0.]]
2.opencv+Python和matlab和opencv+C++的结果都不一样,但是主要部分都是大致相同的(比如说焦距都是533, 旋转矩阵对角线值差不多,平移矩阵大致为-33左右)。这就造成了计算三维坐标的不统一。emm,再想想解决办法吧
前言:基于Python版本的相机校正,并且校正结果与官方对比主要差值较小。话不多说,直接上代码。1.导入库包括opencv, numpy和文件操作库osimport cv2import numpy as npimport os2.编写函数本次主要有两个比较麻烦的要解决,其一,批量读取,第二,真实坐标的写入。我使用os编写的读取文件函数,比较垃圾,大佬请用glob或者其他的。真实坐标主要是标定板上内点的真实相片坐标,通过参考其他大佬总结的出def getImageList(im
各标定步骤实现方法
1 计算标靶平面与图像平面之间的映射矩阵
计算标靶平面与图像平面之间的映射矩阵,计算映射矩阵时不考虑摄像机的成像模型,只是根据平面标靶坐标点和对应的图像坐标点的数据,利用最小二乘方法计算得到[ [ix] ]
.2 求解摄像机参数矩阵
由计算得到的标靶平面和图像平面的映射矩阵得到与摄像机内部参数相关的基本方程关系,求解方程得到摄像机内部参数,考虑镜头的畸变模型,将上述解方程获
得的内部参数作为初值,进行非线性优化搜索,从而计算出所有参数的准确值 [[x] ]
.3 求解左右两摄像机之间的相对位置关系
设
双目
视觉系统左右摄像机的外部参数分别为Rl, Tl,与Rr, Tr,,即Rl, Tl表示左摄像机与世界坐标系的相对位置,Rr, Tr表示右摄像机与世界坐标系的相对位置 [[xi] ]。因此,对于空间任意一点,如果在世界坐标系、左摄像机坐标系和右摄像机坐标系中的坐标分别为Xw,, Xl , Xr,则有:Xl=RlXw+Tl ;Xr=RrXw+Tr .因此,两台摄像机之间的相对几何关系可以由下式表示R=RrRl-1 ;T=Tr- RrRl-1Tl
在实际标定过程中,由标定靶对两台摄像机同时进行摄像标定,以分别获得两台摄像机的内、外参数,从而不仅可以标定出摄像机的内部参数,还可以同时标定出
双目
视觉系统的结构参数 [xii] 。由单摄像机标定过程可以知道,标定靶每变换一个位置就可以得到一组摄像机外参数:Rr,Tr,与Rl, Tl,因此,由公式R=RrRl-1 ;T=Tr- RrRl-1Tl,可以得到一组结构参数R和T
由于本人水平有限,以下单
双目
代码是我自己花时间搜集、整理并加以修改的单
双目
标定的
python
代码,希望能帮到和我一样半路出家的只会
python
的小白。
文中标定过程中用到的相关函数在我另外一篇博客里都有介绍。
1、
双目
拍照
#coding:utf-8
import cv2
import time
left_camera = cv2.VideoCapture(0)
left_camera....
本博客将实现
Python
版本的
双目
三维重建系统,项目代码实现包含:`
双目
标定`,`立体校正(含消除畸变)`,`立体匹配`,`视差计算`和`深度距离计算/3D坐标计算` 的知识点。限于篇幅,本博客不会过多赘述算法原理,而是手把手教你,如果搭建一套属于自己的
双目
三维重建的系统。该系统包含:
支持双USB连接线的
双目
摄像头
支持单USB连接线的
双目
摄像头(左右摄像头被拼接在同一个视频中显示)
支持
单目
相机标定
:mono_camera_calibration.py
支持
双目
相机标定
:stereo_camera
立体标定函数stereoCalibrate()
stereoCalibrate()是用来标定一个立体摄像头的,也就是同时标定两个摄像头。标定的结果除了能够求出两个摄像头的内外参数矩阵,跟能够得出两个摄像头的位置关系R,T。
double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePo...