在作SLAM时,但愿用到深度图来辅助生成场景,因此要构创建体视觉,在这里使用OpenCV的Stereo库和python来进行双目立体视觉的图像处理。python

立体标定

应用标定数据

转换成深度图

标定

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

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

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

import cv2

import time

AUTO = 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 counter

path = 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 += 1

utc = now

key = cv2.waitKey(1)

if key == ord("q"):

break

elif key == ord("s"):

shot("left", left_frame)

shot("right", right_frame)

counter += 1

left_camera.release()

right_camera.release()

cv2.destroyWindow("left")

cv2.destroyWindow("right")

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

.net

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

在进行完立体标定后,咱们将获得以下的数据:code

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中,上面的参数都是手动填写至下面的内容中的,这样免去保存成文件再去读取,在托运填写的时候要注意数据的对应位置。orm

# filename: camera_configs.py

import cv2

import numpy as np

left_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,这些参数都将应用于下面的转换成深度图中blog

转换成深度图

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(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 += 1

if 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"):

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()

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

索引

Have fun.

python opencv双目测距_使用OpenCV/python进行双目测距相关推荐

  1. python opencv 图像切割_【OpenCV+Python】图像的基本操作与算术运算

    图像的基本操作 在上个教程中,我们介绍了使用鼠标画笔的功能.本次教程,我们将要谈及OpenCV图像处理的基本操作. 本次教程的所有操作基本上都和Numpy相关,而不是与OpenCV相关.要使用Open ...

  2. python人脸识别理论_使用OpenCV和Python进行人脸识别

    介绍 人脸识别是什么?或识别是什么?当你看到一个苹果时,你的大脑会立刻告诉你这是一个苹果.在这个过程中,你的大脑告诉你这是一个苹果水果,用简单的语言来说就是识别.那么什么是人脸识别呢?我肯定你猜对了. ...

  3. opencv 检测几何图形_使用OpenCV + ConvNets检测几何形状

    opencv 检测几何图形 A simple yet powerful pipeline for detecting shapes in scanned documents 一个简单而强大的管道,用于 ...

  4. opencv物品定位_使用OpenCV获取零件位置的学习笔记

    最近公司接到一个案子,使用移动机械臂抓取圆盘上下料,目前我们的移动机器人定位精度在两厘米左右,因此需要视觉辅助定位来提高夹取的精度. 这个项目本身不是我做,出于对是视觉的兴趣,学习了一下如何使用Ope ...

  5. python一键安装神器_一键安装python

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 去年有出一个python整的lamp自动安装,不过比较傻,直接调用的yum 去安 ...

  6. python cmap_Python cmap包_程序模块 - PyPI - Python中文网

    cmapy 在python中使用matplotlib colormaps和opencv. matplotlib提供了很多nice colormaps.cmapy将这些颜色映射公开为颜色列表,这些颜色列 ...

  7. python变量定义大全_详解python变量与数据类型

    这篇文章我们学习 Python 变量与数据类型 变量 变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念,变量可以通过变量名访问.在 Python 中 变量命名规定,必须是大小写英文,数字 ...

  8. python积木式编程_实例讲解python函数式编程

    函数式编程是使用一系列函数去解决问题,按照一般编程思维,面对问题时我们的思考方式是"怎么干",而函数函数式编程的思考方式是我要"干什么". 至于函数式编程的特点 ...

  9. python怎么求指数_求指数 python

    softmax用于多分类过程中最后一层,将多个神经元的输出,映射到(0, 1)区间内,可以看成概率来理解,从而来进行多分类! softmax函数如下: 更形象的如下图表示: softmax 直白来说就 ...

  10. python实现数据可视化_使用Matplotib python实现数据可视化

    python实现数据可视化 I Feel: 我觉得: In today's digital world data has become as important as air. Machines &a ...

最新文章

  1. install openstack on single host
  2. 推荐一套开源通用后台管理系统(附源码)
  3. chart.js 饼图显示百分比_Python怎么画饼图?Matplotlib数据可视化004:饼图
  4. 黑马程序员-异常介绍与处理
  5. cocos2D(四)---- CCSprite
  6. 使用V8和node轻松profile分析nodejs应用程序
  7. 五一假期期间 全国快递包裹揽投量同比增长约四成
  8. 达梦数据charindex_更新日志 · dotnetcore/FreeSql Wiki · GitHub
  9. Ubuntu 安装 Clang 编译器
  10. 从数据库获取数据到Servlet.
  11. python if else格式_Python进阶之路 3.4.2 条件语句(if、else和elif)
  12. HCI实验图常见类型
  13. 超级SIM卡 SEID号读取 手机NFC门禁刷卡模块方案
  14. 【人工智能】人工智能二——遗传算法的基本概念遗传算法的基本算法(编码群体设定适应度函数选择交叉变异遗传算法步骤)解决带约束的函数优化问题多目标的遗传算法遗传算法的改进算法
  15. 星际争霸2Beta版单机使用方法
  16. xml引入xml_XML Watch,蠕虫的哔哔声
  17. 使用IR2101半桥驱动电机的案例
  18. 英特尔酷睿处理器后面的数字和字母含义
  19. 边沿触发是什么意思_epoll边缘触发模式
  20. MySQL如何同时删除主外键关联的两张表中的数据

热门文章

  1. 系统架构图 云架构案例
  2. 网页媒体播放利器 - JW Player使用心得
  3. PBR 六 材质参数
  4. php检测是否存在敏感词,用于检测敏感词的 PHP 扩展
  5. 软件测试用例设计包括哪些类型?
  6. 分布式任务调度框架设计与实现解读(1)
  7. 磁滞回线与软磁材料和硬磁材料的关系
  8. 计算机采取二进制的原因,计算机为什么采用二进制
  9. 【Proteus仿真】自动量程(范围<10V)切换数字电压表
  10. Mac修改hosts文件