python opencv立体测距 立体匹配BM算法

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

标定

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

参考: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.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251996.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对于python 作用域新的理解

今天看Python习题&#xff0c;看到如下题目 def num():return [lambda x: i*x for i in range(4)] print([m(2) for m in num()])  # 求输出结果是什么 我看了半天才明白这应该是一个列表生成式&#xff0c;列表中的元素为四个匿名函数&#xff0c;我本以为每个匿名函数应该是…

Vue基础学习(一)------内部指令

一.v-if v-else v-show 指令 1.v-if v-if:是vue 的一个内部指令&#xff0c;指令用在我们的html中,用来判断是否加载html的DOM 现在举个栗子&#xff0c;判断用户的登录操作&#xff0c;用isLogin作为一个判断字段&#xff0c;登录成功&#xff0c;就显示用户的名称 代码&…

【bzoj3555】[Ctsc2014]企鹅QQ 简单哈希

传送门 题目分析 题意即求有多少对字符串只相差一个字符&#xff0c;枚举删除每个字符后的哈希&#xff0c; 看有多少相等即可。 比如有如下字符串&#xff1a;$Sd123$&#xff0c;其中S部分的哈希值为H&#xff0c;删除的是d&#xff0c;则原字符串的哈希值为$$(((H * T d) *…

StereoRectify()函数定义及用法畸变矫正与立体校正

畸变矫正是上一篇博文的遗留问题&#xff0c;当畸变系数和内外参数矩阵标定完成后&#xff0c;就应该进行畸变的矫正&#xff0c;以达到消除畸变的目的&#xff0c;此其一。 在该系列第一部分的博文中介绍的立体成像原理中提到&#xff0c;要通过两幅图像估计物点的深度信息&a…

死磕 java集合之TreeMap源码分析(三)- 内含红黑树分析全过程

2019独角兽企业重金招聘Python工程师标准>>> 欢迎关注我的公众号“彤哥读源码”&#xff0c;查看更多源码系列文章, 与彤哥一起畅游源码的海洋。 删除元素 删除元素本身比较简单&#xff0c;就是采用二叉树的删除规则。 &#xff08;1&#xff09;如果删除的位置有两…

Linux:进程实例信息(/proc)

https://blog.csdn.net/test1280/article/details/73632333 Linux:进程实例信息&#xff08;/proc&#xff09; 问几个问题&#xff1a; 1.怎么知道一个进程对应哪个可执行文件&#xff1f; 2.怎么知道一个进程的资源限制&#xff1f; 3.怎么知道一个进程所处的环境&#xff1f…

四元素理解

旋转变换_四元数 2017年03月29日 11:59:38 csxiaoshui 阅读数&#xff1a;5686 1.简介 四元数是另一种描述三维旋转的方式&#xff0c;四元数使用4个分量来描述旋转&#xff0c;四元数的描述方式如下&#xff1a; qsxiyjzk,(s,x,y,z∈ℝ&#xff09;i2j2k2ijk−1 四元数的由…

31、SAM文件中flag含义解释工具--转载

转载&#xff1a;http://www.cnblogs.com/nkwy2012/p/6362996.html SAM是Sequence Alignment/Map 的缩写。像bwa等软件序列比对结果都会输出这样的文件。samtools网站上有专门的文档介绍SAM文件。具体地址&#xff1a;http://samtools.sourceforge.net/SAM1.pdf很多人困惑SAM文…

《Head First设计模式》批注系列(一)——观察者设计模式

最近在读《Head First设计模式》一书&#xff0c;此系列会引用源书内容&#xff0c;但文章内容会更加直接&#xff0c;以及加入一些自己的理解。 观察者模式&#xff08;有时又被称为模型-视图&#xff08;View&#xff09;模式、源-收听者(Listener)模式或从属者模式&#xff…

PYPL 4 月排行:Python 最流行,Java 还行不行?

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; PYPL 发布了 4 月份的编程语言排行榜。 前五的分别是&#xff1a;Python、Java、Javascript、C# 和 PHP。可以看到&#xff0c;榜单没有什么大变化&#xff0c;但是相比去年 4 月份&#xff0c;…

两个向量的旋转矩阵与四元素

两向量的夹角 2017年06月20日 17:38:11 csxiaoshui 阅读数&#xff1a;36764 怎么计算两个向量间的夹角呢&#xff1f; 这里主要分两种情况&#xff0c;对于二维向量和三维向量来分别讨论。 1. 二维向量 二维向量的情况相对简单&#xff0c;根据向量间的点乘关系 v1⋅v2|…

顺序表

一、数据是如何在内存中存储的&#xff1f; 32位系统中char&#xff0c;int型数据在内存中的存储方式&#xff1a; char占1byte&#xff08;8bit&#xff09;int占4byte&#xff08;32bit&#xff09;假设我们有一个int类型的值&#xff0c;它从0x01开始&#xff0c;一个int占据…

Establishing SSL connection without server's identity verification is not recommended.

完全描述:Establishing SSL connection without servers identity verification is not recommended. According to MySQL 5.5.45, 5.6.26 and 5.7.6 requirements SSL connection must be established by default if explicit option isnt set. For compliance with existing …

四元素的真面目..........简单粗暴

作者&#xff1a;Yang Eninala 链接&#xff1a;https://www.zhihu.com/question/23005815/answer/33971127 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 根据我的理解&#xff0c;大多数人用汉密尔顿四元数就只…

2.自定义变量调节器

① 使用registerPlugin()方法来扩充变量调节器 该方法接收3个参数 1. 字符串modifier 2. 插件函数的名字 3. PHP回调函数 示例&#xff1a;自定义一个变量调节器&#xff0c;可以改变文字的颜色和大小 第一步&#xff1a;调用smarty对象的registerPlugin&#xff08;&#x…

SpringBoot2构建基于RBAC权限模型的驾校代理小程序后端

本项目是使用SpringBoot2构建的一套基于RBAC权限模型的后台管理系统&#xff0c;前端是微信小程序。 项目地址: github.com/fuyunwang/D… 项目的缘由 最近接了个外包,主要是针对于驾校开发一个代理小程序。目的是为了方便驾校的管理来招揽学员,同时方便维护学员和代理信息。 项…

while read line的问题

循环中的重定向或许你应该在其他脚本中见过下面的这种写法&#xff1a;while read linedo…done < file刚开始看到这种结构时&#xff0c;很难理解< file是如何与循环配合在一起工作的。因为循环内有很多条命令&#xff0c;而我们之前接触的重定向都是为一条命令工作的。…

Linemod;理解

Linemod 代码笔记 2019年03月11日 16:18:30 haithink 阅读数&#xff1a;197 最近了解到 Linemod 这个模板匹配算法&#xff0c;印象不错 准备仔细学习一下&#xff0c;先做点代码笔记&#xff0c;免得后面不好回顾 目前的笔记基本上把 核心流程都分析得比较清楚了&#xff0…

Swift3中数组创建方法

转载自&#xff1a;http://blog.csdn.net/bwf_erg/article/details/70858865 数组是由一组类型相同的元素构成的有序数据集合。数组中的集合元素是有 序的&#xff0c;而且可以重复出现。 1 数组创建 在Swift语言中&#xff0c;数组的类型格式为&#xff1a; Array<ElementT…

BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)

题意 这一天&#xff0c;\(\mathrm{Konano}\) 接到了一个任务&#xff0c;他需要给正在制作中的游戏 \(\mathrm{《IIIDX》}\) 安排曲目 的解锁顺序。游戏内共有\(n\) 首曲目&#xff0c;每首曲目都会有一个难度 \(d\) &#xff0c;游戏内第 \(i\) 首曲目会在玩家 Pass 第 \(\lf…