• 立体标定
  • 应用标定数据
  • 转换成深度图

标定

在开始之前,需要准备的当然是两个摄相头,根据你的需求将两个摄像头进行相对位置的固定,我是按平行来进行固定的(如果为了追求两个双目图像更高的生命度,也可以将其按一定钝角固定,这样做又限制了场景深度的扩展,根据实际需求选择)

参考:https://www.cnblogs.com/zhiyishou/p/5767592.html

由于摄像头目前是我们手动进行定位的,我们现在还不知道两张图像与世界坐标之间的耦合关系,所以下一步要进行的是标定,用来确定分别获取两个摄像头的内部参数,并且根据两个摄像头在同一个世界坐标下的标定参数来获取立体参数。注:不要使用OpenCV自带的自动calbration,其对棋盘的识别率极低,使用Matlab的Camera Calibration Toolbox更为有效,具体细节请看:摄

同时从两个摄像头获取图片

import cv2
import timeAUTO = True  # 自动拍照,或手动按s键拍照
INTERVAL = 2 # 自动拍照间隔cv2.namedWindow("left")
cv2.namedWindow("right")
cv2.moveWindow("left", 0, 0)
cv2.moveWindow("right", 400, 0)
left_camera = cv2.VideoCapture(0)
right_camera = cv2.VideoCapture(1)counter = 0
utc = time.time()
pattern = (12, 8) # 棋盘格尺寸
folder = "./snapshot/" # 拍照文件目录def shot(pos, frame):global counterpath = folder + pos + "_" + str(counter) + ".jpg"cv2.imwrite(path, frame)print("snapshot saved into: " + path)while True:ret, left_frame = left_camera.read()ret, right_frame = right_camera.read()cv2.imshow("left", left_frame)cv2.imshow("right", right_frame)now = time.time()if AUTO and now - utc >= INTERVAL:shot("left", left_frame)shot("right", right_frame)counter += 1utc = nowkey = cv2.waitKey(1)if key == ord("q"):breakelif key == ord("s"):shot("left", left_frame)shot("right", right_frame)counter += 1left_camera.release()
right_camera.release()
cv2.destroyWindow("left")
cv2.destroyWindow("right")

下面是我拍摄的样本之一,可以肉眼看出来这两个摄像头成像都不是水平的,这更是需要标定的存在的意义

在进行标定的过程中,要注意的是在上面标定方法中没有提到的是,单个标定后,要对标定的数据进行错误分析(Analyse Error),如左图,是我对左摄像头的标定结果分析。图中天蓝色点明显与大部分点不聚敛,所以有可能是标定时对这个图片标定出现的错误,要重新标定,在该点上点击并获取其图片名称索引,对其重新标定后,右图的结果看起来还是比较满意的

在进行完立体标定后,我们将得到如下的数据:

Stereo calibration parameters after optimization:Intrinsic parameters of left camera:Focal Length:          fc_left = [ 824.93564   825.93598 ]  [ 8.21112   8.53492 ]
Principal point:       cc_left = [ 251.64723   286.58058 ]  [ 13.92642   9.11583 ]
Skew:             alpha_c_left = [ 0.00000 ]  [ 0.00000  ]   => angle of pixel axes = 90.00000  0.00000 degrees
Distortion:            kc_left = [ 0.23233   -0.99375   0.00160   0.00145  0.00000 ]  [ 0.05659   0.30408   0.00472   0.00925  0.00000 ]Intrinsic parameters of right camera:Focal Length:          fc_right = [ 853.66485   852.95574 ]  [ 8.76773   9.19051 ]
Principal point:       cc_right = [ 217.00856   269.37140 ]  [ 10.40940   9.47786 ]
Skew:             alpha_c_right = [ 0.00000 ]  [ 0.00000  ]   => angle of pixel axes = 90.00000  0.00000 degrees
Distortion:            kc_right = [ 0.30829   -1.61541   0.01495   -0.00758  0.00000 ]  [ 0.06567   0.55294   0.00547   0.00641  0.00000 ]Extrinsic parameters (position of right camera wrt left camera):Rotation vector:             om = [ 0.01911   0.03125  -0.00960 ]  [ 0.01261   0.01739  0.00112 ]
Translation vector:           T = [ -70.59612   -2.60704  18.87635 ]  [ 0.95533   0.79030  5.25024 ]

应用标定数据

我们使用如下的代码来将其配置到python中,上面的参数都是手动填写至下面的内容中的,这样免去保存成文件再去读取,在托运填写的时候要注意数据的对应位置

# filename: camera_configs.py
import cv2
import numpy as npleft_camera_matrix = np.array([[824.93564, 0., 251.64723],[0., 825.93598, 286.58058],[0., 0., 1.]])
left_distortion = np.array([[0.23233, -0.99375, 0.00160, 0.00145, 0.00000]])right_camera_matrix = np.array([[853.66485, 0., 217.00856],[0., 852.95574, 269.37140],[0., 0., 1.]])
right_distortion = np.array([[0.30829, -1.61541, 0.01495, -0.00758, 0.00000]])om = np.array([0.01911, 0.03125, -0.00960]) # 旋转关系向量
R = cv2.Rodrigues(om)[0]  # 使用Rodrigues变换将om变换为R
T = np.array([-70.59612, -2.60704, 18.87635]) # 平移关系向量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)

这样,我们得到了左右摄像头的两个map,并得到了立体的Q,这些参数都将应用于下面的转换成深度图中

转换成深度图

import numpy as np
import cv2
import camera_configscv2.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(0)
camera2 = cv2.VideoCapture(1)# 添加点击事件,打印当前点的距离
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 += 1if blockSize < 5:blockSize = 5# 根据Block Maching方法生成差异图(opencv里也提供了SGBM/Semi-Global Block Matching算法,有兴趣可以试试)stereo = cv2.StereoBM_create(numDisparities=16*num, blockSize=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"):breakelif 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()

下面则是一附成像图,最右侧的为生成的disparity图,按照上面的代码,在图上点击则可以读取到该点的距离

Have fun.

python opencv立体测距 立体匹配BM算法相关推荐

  1. OpenCV双目稠密匹配BM算法源代码详细解析

    点击上方"视学算法",选择"星标" 干货第一时间送达 本文由知乎作者David LEE授权转载,不得擅自二次转载.原文链接:https://zhuanlan.z ...

  2. python opencv入门 Meanshift 和 Camshift 算法(40)

    内容来自OpenCV-Python Tutorials 自己翻译整理 目标: 在本章,学习Meanshift算法和Camshift算法来寻找和追踪视频中的目标物体. Meanshift算法: mean ...

  3. (自己编写函数)Python + Opencv 图像边缘检测(模糊算法【老师给的ppt中原理是这样的,但是还有很多不明白,有很多参数老师没说怎么算,只说了每张图片不一样】)

    实验原理 1.首先,用重心法模糊推理图像中任意一像素点的边缘隶属方向,取其最大隶属度的方向为边缘隶属方向. 2.然后,在边缘隶属方向上根据像素点附近灰度分布的特点模糊推理该点的边缘隶属度,进而实现边缘 ...

  4. python opencv 实现Reinhard颜色迁移算法

    https://www.cnblogs.com/likethanlove/p/6003677.html Reinhard颜色迁移算法的过程很简单,流程如下,细节部分见原文,题目为color trans ...

  5. python+opencv多进程实现识别魔方颜色,通过kociemba算法得出算法字符串并画图(附毕设完整视频)

    完整毕设成果视频如下: 本科毕业设计转魔方(声音略大) python+opencv本科毕业设计转魔方(声音略大) 上一篇博客已经给大家讲了鼠标hsv获取魔方颜色阈值方法,具体见 python+open ...

  6. 立体匹配成像算法BM,SGBM,GC,SAD一览

    本文转自|新机器视觉 在深度相机的主流技术方案Structure Light,ToF,Stereo Dual)中,主动双目成像方案可以基于低成本的硬件,获得高分辨率.高精度的深度图像,但是立体匹配算法 ...

  7. opencv双目测距(BM 与SGBM匹配)

    1.引言 在一年之前小编写了一篇双目测距的博文,引入了大量的童鞋阅读,其博文介绍了详细的相机标定与双目测距过程和代码 https://blog.csdn.net/xiao__run/article/d ...

  8. 双目相机标定以及立体测距原理及OpenCV实现

    转载 双目相机标定以及立体测距原理及OpenCV实现 http://blog.csdn.net/dcrmg/article/details/52986522?locationNum=15&fp ...

  9. 双目相机标定以及立体测距原理及OpenCV实现(下)

    前篇:双目相机标定以及立体测距原理及实现(上) 双目相机标定后,可以看到左右相机对应匹配点基本上已经水平对齐. 之后在该程序基础上运行stereo_match.cpp,求左右相机的视差. 注:下边Op ...

最新文章

  1. 【TensorFlow2.0】(3) 索引与切片操作
  2. Linux后台开发必看!
  3. windows下安装Python virtualenvwrapper-win
  4. 利用Docker设置Node.js
  5. 算法题——Cantor表
  6. java 服务端客户端数据传输出现乱码
  7. 3月更新来了!Windows 11正式版22000.556发布
  8. 界面设计方法 (1) — 3. 字典功能的设计
  9. linux使用中的问题 --- (Unable to establish SSL connection)
  10. 2_用keras训练一个神经网络及不同优化和初始化对性能的影响分析
  11. java超市管理系统增删改查,超市管理系统java程序设计报告(图文完整)
  12. ofd文件怎么编辑文字
  13. 谷歌浏览器怎么长截图怎么截_Google浏览器如何截取网页长图 - 里维斯社
  14. 【浏览器兼容性】如何隐藏微软的ie和edge浏览器密码输入框的小眼睛
  15. 单片机长时间程序跑飞_单片机程序跑飞的三种现象、原因及解决方法
  16. 有手机去视频水印的app下载 迅雷下载
  17. CISCO ASA思科防火墙常用命令
  18. c# char unsigned_关于C ++:将unsigned char *复制到unsigned char *
  19. PAData:FCoin潜在受害者或超2000人,人均损失或超25 BTC
  20. 炼铁技术有哪些?普锐特冶金技术告诉你!

热门文章

  1. FPFH+ICP点云配准
  2. 谈论Java原子变量和同步的效率 -- 颠覆你的生活
  3. Hadoop伪分布配置与基于Eclipse开发环境搭建
  4. xshell使用指南
  5. UVa202Repeating Decimals (循环小数)
  6. 前端解析返回的对象时json显示$ref问题的解决
  7. BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)
  8. MSSQL-to-MySQL v5.3, 从MSSQL迁移到mySQL的最佳工具
  9. iOS 将16进制颜色转换成UIColor
  10. C#获取程序集的版本号和最后编译时间