OpenCV012:双目测距

一.摄像头标定

    1. 打印一张棋盘图,网上自己随便找,或者自己用CAD画一个。

    2.使用左右两个摄像头,分别同时拍摄不同角度的棋盘图,并保存到目标文件夹下。可参考我的博客:OpenCV011

    3.使用matlab工具箱标定:TOOLBOX_calib,标定方法百度一下,就有很多介绍

    3.编写一个摄像头参数文件,并命名为:camera_configs.py,我的摄像头参数如下:

    

# -- coding: utf-8 --
#如若程序有中文注释,将上行代码加到代码的第一行或第二行
#blog:
#https://www.cnblogs.com/zhiyishou/p/5767592.html
#Camera Matrix,distortion
#http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html
#                   fx 0 cx
#Camera Matrix=     0 fy cy
#                   0  0  1
#distortion coefficients=(k1,k2,p1,p2,k3)
#filename: camera_configs.py
import cv2
import numpy as np

left_camera_matrix = np.array([[743.75550, 0., 309.19470],
                               [0., 742.26143, 247.91394],
                               [0., 0., 1.]])
left_distortion = np.array([[0.13950, -0.45453, 0.00300, -0.00260, 0.00000]])



right_camera_matrix = np.array([[752.48868, 0., 369.93495],
                                [0., 748.39473, 234.17570],
                                [0., 0., 1.]])
right_distortion = np.array([[0.15105, -0.50820, 0.00157, 0.01659, 0.00000]])

om = np.array([-0.00573, 0.00361, 0.00487]) # 旋转关系向量
R = cv2.Rodrigues(om)[0]  # 使用Rodrigues变换将om变换为R
T = np.array([-95.74804, 2.60574, 4.01073]) # 平移关系向量

size = (640, 480) # 图像尺寸

# 进行立体更正
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)

二.双目测距实现

废话不说,直接上验证过的代码。调整两个滑块,改变算法阈值。

StereoBM在我之前的博文中有讲解 

# -- coding: utf-8 --
#如若程序有中文注释,将上行代码加到代码的第一行或第二行
#blog:
#https://www.cnblogs.com/zhiyishou/p/5767592.html
import numpy as np
import cv2
import camera_configs

cv2.namedWindow("left")
cv2.namedWindow("right")
cv2.namedWindow("depth")
cv2.moveWindow("left", 0, 0)
cv2.moveWindow("right", 600, 0)
cv2.createTrackbar("num", "depth", 0, 10, lambda x: None)
cv2.createTrackbar("blockSize", "depth", 5, 255, lambda x: None)
camera1 = cv2.VideoCapture(1)
camera2 = cv2.VideoCapture(0)

# 添加点击事件,打印当前点的距离
def callbackFunc(e, x, y, f, p):
    if e == cv2.EVENT_LBUTTONDOWN:        
        print threeD[y][x]

cv2.setMouseCallback("depth", callbackFunc, None)

while True:
    ret1, frame1 = camera1.read()
    ret2, frame2 = camera2.read()

    if not ret1 or not ret2:
        break

    # 根据更正map对图片进行重构
    img1_rectified = cv2.remap(frame1, camera_configs.left_map1, camera_configs.left_map2, cv2.INTER_LINEAR)
    img2_rectified = cv2.remap(frame2, camera_configs.right_map1, camera_configs.right_map2, cv2.INTER_LINEAR)

    # 将图片置为灰度图,为StereoBM作准备
    imgL = cv2.cvtColor(img1_rectified, cv2.COLOR_BGR2GRAY)
    imgR = cv2.cvtColor(img2_rectified, cv2.COLOR_BGR2GRAY)

    # 两个trackbar用来调节不同的参数查看效果
    num = cv2.getTrackbarPos("num", "depth")
    blockSize = cv2.getTrackbarPos("blockSize", "depth")
    if blockSize % 2 == 0:
        blockSize += 1
    if blockSize < 5:
        blockSize = 5

    # 根据Block Maching方法生成差异图(opencv里也提供了SGBM/Semi-Global Block Matching算法,有兴趣可以试试)
    stereo = cv2.StereoBM(0,16*num, blockSize)
    disparity = stereo.compute(imgL, imgR)

    disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
    # 将图片扩展至3d空间中,其z方向的值则为当前的距离
    threeD = cv2.reprojectImageTo3D(disparity.astype(np.float32)/16., camera_configs.Q)

    cv2.imshow("left", img1_rectified)
    cv2.imshow("right", img2_rectified)
    cv2.imshow("depth", disp)

    key = cv2.waitKey(1)
    if key == ord("q"):
        break
    elif key == ord("s"):
        cv2.imwrite("./snapshot/BM_left.jpg", imgL)
        cv2.imwrite("./snapshot/BM_right.jpg", imgR)
        cv2.imwrite("./snapshot/BM_depth.jpg", disp)

camera1.release()
camera2.release()
cv2.destroyAllWindows()


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值