1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【手把手教你用Matlab做双目摄像头标定】Ubuntu环境

【手把手教你用Matlab做双目摄像头标定】Ubuntu环境

时间:2022-08-28 09:32:06

相关推荐

【手把手教你用Matlab做双目摄像头标定】Ubuntu环境

【手把手教你用Matlab做双目摄像头标定】 Ubuntu20.04环境

准备工作你需要一个标定板你需要一个双目摄像头获取双目摄像头的设备号跑起来看看分割图像并完成拍照使用Matlab进行标定

准备工作

你需要一个标定板

一个高精度的标定板对我们的标定结果是至关重要的,最好的方案应该是去购买一款高精度的实物板子。不过从学习的角度出发,我们这里用一张白纸加一块纸板的方式凑活凑活。

首先你需要找一个这样的图(当然你可以考虑自己画一个,

标定板生成网站: https://calib.io/pages/camera-calibration-pattern-generator)

我们把它打印出来,然后贴在一块较为平整的纸板上(纸板你可以从快递纸箱上裁取)。

这一步就完成了,我们现在有一块炫酷的板子!

你需要一个双目摄像头

获取双目摄像头的设备号

1.Ubuntu先打开终端,执行代码,我们看到我的笔记本现在有video 2-5 四个摄像头

ls /dev/video*

2.插上双目摄像头

再次执行代码,查看摄像头设备

ls /dev/video*

我们看到多出来的video1和video6就是我们双目摄像头的设备号了

跑起来看看

from cv2 import cv2# 按设备号读取视频# 记得我们之前查看的设备号吗,我们的摄像头编号是video1和video6# 因为厂家对摄像头频率做了同步,和视频帧拼接,所以实际上只有设备号为1的能正常打开cameraCapture = cv2.VideoCapture(1)# cameraCapture = cv2.VideoCapture(6) # 运行代码发现6这个摄像头并不能打开# 摄像头厂家告诉我,我这款摄像头是2560*720的,我们调整一下大小cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH,2560)cameraCapture.set(cv2.CAP_PROP_FRAME_HEIGHT,720)#读取帧Pret,frame = cameraCapture.read()while cv2.waitKey(1) :cv2.imshow('window',frame)ret,frame = cameraCapture.read()cv2.destroyAllWindows()cameraCapture.release()

好的,接下来我们开始对图像做分割, 并分左右摄像头拍照。

分割图像并完成拍照

import osimport cv2id_image = 0 # 图片的IDcameraCapture = cv2.VideoCapture(1)# cameraCapture = cv2.VideoCapture(6)# #迭代停止模式选择(type, max_iter, epsilon)# #cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon,则停止。# #cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter,则停止。# #两者结合,满足任意一个结束。criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)# 设置高宽cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 2560)cameraCapture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)# 创建左右摄像头对应的目录dirsL = 'calibration/left/chessboard-L'dirsR = 'calibration/right/chessboard-R'if not os.path.exists(dirsL):os.makedirs(dirsL)if not os.path.exists(dirsR):os.makedirs(dirsR)while True:ret, frame = cameraCapture.read()# 这里的左右两个摄像头的图像是连在一起的,所以进行一下分割# 如果你的摄像头本来就是双设备号,直接获取两个摄像头做为frame1,frame2就好frame2 = frame[0:720, 0:1280]frame1 = frame[0:720, 1280:2560]# 转换成灰度图 棋盘格识别需要时灰度图grayR = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)grayL = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)# 查找棋盘格这个 注意到我们用的棋盘格 内角数是8*6的 用其他的要修改一下retR, cornersR = cv2.findChessboardCorners(grayR , (8, 6) , None)retL, cornersL = cv2.findChessboardCorners(grayL , (8, 6) , None)# cv2.imshow('imgR', frame1)# cv2.imshow('imgL', frame2)cv2.imshow('imgR', grayR)cv2.imshow('imgL', grayL)# 如果找到了棋盘格就显示内角点if (retR == True) & (retL == True):corners2R = cv2.cornerSubPix(grayR, cornersR, (11, 11), (-1, -1), criteria)corners2L = cv2.cornerSubPix(grayL, cornersL, (11, 11), (-1, -1), criteria)# 画出角点cv2.drawChessboardCorners(grayR, (8, 6), corners2R, retR)cv2.drawChessboardCorners(grayL, (8, 6), corners2L, retL)cv2.imshow('VideoR', grayR)cv2.imshow('VideoL', grayL)if cv2.waitKey(0) & 0xFF == ord('s'): # S 存储 C取消存储print('S PRESSESED')str_id_image = str(id_image)print('Images ' + str_id_image + ' saved for right and left cameras')# 需要提前创建好路径cv2.imwrite('calibration/right/chessboard-R' + str_id_image + '.png', frame1)cv2.imwrite('calibration/left/chessboard-L' + str_id_image + '.png', frame2)id_image = id_image + 1else:print('Images not saved')if cv2.waitKey(1) & 0xFF == ord('q'): # q 结束当前程序break# Release the CamerascameraCapture.release()cv2.destroyAllWindows()

按S保存多张图片到本地, 30张左右吧。因为后续还会剔除一些效果不好的照片。

使用Matlab进行标定

1.打开Matlab 执行指令stereoCameraCalibrator

2.点击Add Images(添加图像),选择刚才左右摄像头保存照片的路径;用直尺量得单个棋盘格长度并输入(我这里是29.5mm)

3.点击确定,等待分析结果

5.进行校准

勾选【2 Coefficients】【Skew值】【Tangential Distortion】,(标定时选择各参数的意义可参考这篇博客)然后点击Calibrate进行校准

得到结果,然后我们需要把误差大的图像删掉

6.选中删除,(弹出提示是否要删除图像并重新校准,点击是)

7.然后重复若干次,理想情况下,你应该让误差降到0.5以下。

8.完成后导出参数

9.我们的结果就在这里面

10.把结果取出来

我们可以通过逐个查看变量, 或者在命令行执行相应的指令调取参数,但是这样有点呆呆的。

我们可以把我们想要的数据都抽出来写进一个xls文件里。因为我的环境是Ubuntu,不能优雅地使用xlswrite()函数,这里我们用writetable()函数来实现我们想要的效果。输出到’out.xls’文件。

这个xls文件在你的安装目录/bin下面,你应该改成一个你用起来舒服的路径。

T3=array2table(stereoParams.CameraParameters1.IntrinsicMatrix')writetable(T3,'out.xls','Sheet',1,'range','B1:D3','WriteVariableNames',false)T4=array2table(stereoParams.CameraParameters1.RadialDistortion)writetable(T4,'out.xls','Sheet',1,'range','B4:D4','WriteVariableNames',false)T5=array2table(stereoParams.CameraParameters1.TangentialDistortion)writetable(T5,'out.xls','Sheet',1,'range','B5:D5','WriteVariableNames',false)T11=array2table([stereoParams.CameraParameters1.RadialDistortion(1:2), stereoParams.CameraParameters1.TangentialDistortion,0])% 如果你选的是3coefficient 要用这句 T11=array2table([stereoParams.CameraParameters1.RadialDistortion(1:2), stereoParams.CameraParameters1.TangentialDistortion,stereoParams.CameraParameters1.RadialDistortion(3)])writetable(T11,'out.xls','Sheet',1,'range','B6:F6','WriteVariableNames',false)T7=array2table(stereoParams.CameraParameters2.IntrinsicMatrix')writetable(T7,'out.xls','Sheet',1,'range','B7:D9','WriteVariableNames',false)T8=array2table(stereoParams.CameraParameters1.RadialDistortion)writetable(T8,'out.xls','Sheet',1,'range','B10:D10','WriteVariableNames',false)T9=array2table(stereoParams.CameraParameters1.TangentialDistortion)writetable(T9,'out.xls','Sheet',1,'range','B11:D11','WriteVariableNames',false)T12=array2table([stereoParams.CameraParameters2.RadialDistortion(1:2), stereoParams.CameraParameters2.TangentialDistortion,0])% 如果你选的是3coefficient 要用这句 T12=array2table([stereoParams.CameraParameters2.RadialDistortion(1:2), stereoParams.CameraParameters2.TangentialDistortion,stereoParams.CameraParameters2.RadialDistortion(3)])writetable(T12,'out.xls','Sheet',1,'range','B12:F12','WriteVariableNames',false)T1=array2table(stereoParams.TranslationOfCamera2)writetable(T1,'out.xls','Sheet',1,'range','B13:D13','WriteVariableNames',false)T2=array2table(stereoParams.RotationOfCamera2')writetable(T2,'out.xls','Sheet',1,'range','B14:D16','WriteVariableNames',false)TT={'相机1内参';' ';' ';'相机1径向';'相机1切向';'相机1畸变';'相机2内参';' ';' ';'相机2径向';'相机2切向';'相机2畸变';'平移矩阵';'旋转矩阵';}writecell(TT,'out.xls','Sheet',1,'range','A1:A16')% 如果你的A列没有正确输出结果,将上面的指令替换成下面的% TT={'平移矩阵';' ';'旋转矩阵';' ';' ';' ';'相机1内参';' ';' ';' ';'相机1径向';' ';'相机1切向';' ';'相机2内参';' ';' ';' ';'相机2径向';' ';'相机2切向';' ';'相机1畸变';' ';'相机2畸变'}% writecell(TT,'out.xls','Sheet',1,'range','A1:A25')

把代码贴到命令行执行

好的!没有返回消息就是最好的消息!我们接下来看看我们的结果

打开它

好的我们已经获取了我们想要的结果!

11.写入摄像头配置文件

使用脚本自动读取out.xls中的参数文件,需要注意,out.xls文件需要和我上面图中的格式严格一致

import cv2 as cvimport numpy as npimport pandas as pddf1=pd.read_excel('out.xls',header=None)left_camera_matrix=np.array(df1.iloc[0:3,1:4],dtype=np.float64)left_distortion=np.array(df1.iloc[5,1:6],dtype=np.float64).reshape(1,5)right_camera_matrix=np.array(df1.iloc[6:9,1:4],dtype=np.float64)right_distortion=np.array(df1.iloc[11,1:6],dtype=np.float64).reshape(1,5)T=np.array(df1.iloc[12,1:4],dtype=np.float64)R=np.array(df1.iloc[13:16,1:4],dtype=np.float64)# print(cameraMatrix1.head())# size=(w,h)size = (1280, 720) # 图像尺寸# 进行立体更正R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv.stereoRectify(left_camera_matrix, left_distortion,right_camera_matrix, right_distortion, size, R,T)# 计算更正mapleft_map1, left_map2 = cv.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv.CV_16SC2)right_map1, right_map2 = cv.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv.CV_16SC2)

如果你想清晰地知道发生了什么,也可以手动把参数放进去,但是不建议这样做.不优雅.

import cv2import numpy as np# 相机1内参left_camera_matrix = np.array([[840.3242628,11.98349443,720.9895252],[ 0,836.7533204,467.2355637],[0., 0, 1.0000]])# 相机1畸变参数left_distortion = np.array([[-0.036908075,0.136760373,-0.005282581,0.022916452,0]])# 相机2内参right_camera_matrix = np.array([[849.7778635,6.943897179,727.9328227],[ 0 ,842.8092963,477.808017],[0., 0,1.0000]])# 相机2畸变参数right_distortion = np.array([[-0.025533065,0.054401825,-0.003324632,0.017924097,0]])# 平移矩阵T = np.array([-115.8938089,0.071100061,-0.404734693])# 旋转矩阵R = np.matrix([[0.999914262,0.002400323,0.012872745],[-0.002236823,0.999916842,-0.012700606],[-0.01290216,0.012670723,0.99983648],])# size=(w,h)size = (1280, 720) # 图像尺寸# 进行立体更正R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion,right_camera_matrix, right_distortion, size, R,T)# 计算更正mapleft_map1, left_map2 = cv2.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2)right_map1, right_map2 = cv2.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2)

12 到这里就完成啦!

have fun~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。