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

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

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

准备工作

你需要一个标定板

一个高精度的标定板对我们的标定结果是至关重要的,最好的方案应该是去购买一款高精度的实物板子。不过从学习的角度出发,我们这里用一张白纸加一块纸板的方式凑活凑活。
首先你需要找一个这样的图(当然你可以考虑自己画一个,
标定板生成网站: https://calib.io/pages/camera-calibration-pattern-generator)
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第1张图片
我们把它打印出来,然后贴在一块较为平整的纸板上(纸板你可以从快递纸箱上裁取)。
这一步就完成了,我们现在有一块炫酷的板子!

你需要一个双目摄像头

获取双目摄像头的设备号

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)

#读取帧P
ret,frame = cameraCapture.read()
while cv2.waitKey(1) :
    cv2.imshow('window',frame)
    ret,frame = cameraCapture.read()

cv2.destroyAllWindows()
cameraCapture.release()

【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第2张图片
好的,接下来我们开始对图像做分割, 并分左右摄像头拍照。

分割图像并完成拍照

import os
import cv2


id_image = 0 # 图片的ID
cameraCapture = 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)

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)

        # 第一次运行需要创建路径
        os.makedirs('calibration/left/chessboard-L')
        os.makedirs('calibration/right/chessboard-R')

        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 + 1
        else:
            print('Images not saved')


    if cv2.waitKey(1) & 0xFF == ord('q'):  # q 结束当前程序
        break

# Release the Cameras
cameraCapture.release()
cv2.destroyAllWindows()

按S保存多张图片到本地, 30张左右吧。因为后续还会剔除一些效果不好的照片。
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第3张图片

使用Matlab进行标定

1.打开Matlab 执行指令stereoCameraCalibrator
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第4张图片
2.点击Add Images(添加图像),选择刚才左右摄像头保存照片的路径;用直尺量得单个棋盘格长度并输入(我这里是29.5mm)
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第5张图片
3.点击确定,等待分析结果
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第6张图片
5.进行校准
勾选【2 Coefficients】【Skew值】【Tangential Distortion】,(标定时选择各参数的意义可参考这篇博客)然后点击Calibrate进行校准

得到结果,然后我们需要把误差大的图像删掉
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第7张图片

6.选中删除,(弹出提示是否要删除图像并重新校准,点击是)
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第8张图片
7.然后重复若干次,理想情况下,你应该让误差降到0.5以下。
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第9张图片
8.完成后导出参数
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第10张图片
9.我们的结果就在这里面
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第11张图片
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切向';' ';'相机2内参';' ';' ';' ';'相机2径向';' ';'相机2切向';' ';'相机1畸变';' ';'相机2畸变'}
writecell(TT,'out.xls','Sheet',1,'range','A1:A25')

把代码贴到命令行执行
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第12张图片
好的!没有返回消息就是最好的消息!我们接下来看看我们的结果
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第13张图片
打开它
【手把手教你用Matlab做双目摄像头标定】Ubuntu环境_第14张图片
好的我们已经获取了我们想要的结果!
11.写入摄像头配置文件

import cv2
import 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 = (1280, 720) # 图像尺寸

# 进行立体更正
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion,
                                                                  right_camera_matrix, right_distortion, size, R,
                                                                  T)
# 计算更正map
left_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完成啦!

你可能感兴趣的:(计算机视觉,python,matlab,ubuntu,计算机视觉)