在做SLAM时,希望用到深度图来辅助生成场景,所以要构建立体视觉,在这里使用OpenCV的Stereo库和python来进行双目立体视觉的图像处理。

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

标定

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

由于摄像头目前是我们手动进行定位的,我们现在还不知道两张图像与世界坐标之间的耦合关系,所以下一步要进行的是标定,用来确定分别获取两个摄像头的内部参数,并且根据两个摄像头在同一个世界坐标下的标定参数来获取立体参数。注:不要使用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 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")

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

在进行标定的过程中,要注意的是在上面标定方法中没有提到的是,单个标定后,要对标定的数据进行错误分析(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 += 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图,按照上面的代码,在图上点击则可以读取到该点的距离

转载于:https://www.cnblogs.com/yxlln/p/6068985.html

关于opencv标定的一些疑问,首先声明这篇文章转载于纸异兽,由于暂时联系不到他本人,只好请教各位了。有些问题想请教,各位大神可以留下联系方式帮我解决,万分感谢...相关推荐

  1. 安装hue一直失败,请大佬帮帮忙,万分感谢!!!!!!!!

    安装hue一直失败(请大佬帮帮忙,万分感谢!!!) make apps产生的错误: 换了好几个版本都不行,make apps就有错误,然后build/env/bin/supervisor启动后进入网页 ...

  2. 酷派大神f1,酷派大神f2 无法打log的解决方法。

    我发现我的手机无法再eclipse里面输出自己打的log.i等log,一开始还以为是我手机root或刷过机的问题,在百度上找解决方法,并尝试了好久啊啊啊啊啊. 最终非常偶然找到了解决的方法: 酷派大神 ...

  3. 推荐10个关键时刻能派上大用场的神级软件,帮你解决80%的问题

    推荐10个王者级别的软件,用过一次,我就再也离不开了 1.火柴 火柴是一款PC端效率神器,可以快速打开文件.打开应用程序.局域网秒传文件.局域网聊天等等. 双击Ctrl开启火萤酱,火萤酱八大神技:秒搜 ...

  4. 6大自媒体网站,帮你解决灵感枯竭

    一个专业的自媒体运营人员,会懂得通过数据或者工具来解决这个问题.今天就和大家分享解决灵感枯竭的6大工具网站! 1.TOPYS 这个地方有着全世界最新鲜,最棒的创意资讯.不局限于一个地方,可以获得更多的 ...

  5. python怎么搜索文献_学习帖|大神是如何用Python高效解决文献搜索和数据处理!?...

    #研究生期间,你被逼得有多绝望? ◆ 写论文 一起床一睁眼:今天一定要写完这一部分 一支烟一杯茶:一个introduction写一天 一躺下一闭眼:今天都写了些什么玩意 ◆ 面对老板 交稿前脑补各种挨 ...

  6. cf登录游戏只显示服务器的字体,cf辅助灭天大神修复文件字体花样请求解决方法...

    cf冰易辅助小编解说硬盘分区魔术师解答方法 在操作体系的历程中会碰见林林总总的问题,比方最常常见文件字体花样请求的状况,许多用户都是初次遇到文件字体花样请求这类状况,所以人人都没有好的处置惩罚要领,怎 ...

  7. 【转载声明】关于文章转载到微信公众号

    本博客所有原创博文,完全授权于微信公众号 "脑补空间" (nbkj1024) ,并允许其中声明为原创.

  8. tj大神的 co库.优雅的解决 nodejs callback无限嵌套(回调地狱)问题

    github co 项目传送门 https://github.com/tj/co 个人比较喜欢的,用co库的姿势 测试用函数 function fun1(arg1,arg2,cb){//dosomth ...

  9. 管理员同志,回收站博文希望得到恢复,万分感谢

    管理员同志,你好. 今天抽空写了一篇博文,希望分享的,可是由于手误,不熟悉,删至回收站了,自己恢复不了,希望得到恢复,万分感谢.

  10. 声卡突然听不到监听_初次玩外置声卡监听与录音 遇到些问题 恳请大神帮忙解决...

    先上两张图片 是我入的外置icon声卡的前后面板图 11111_副本.jpg (83.24 KB, 下载次数: 2) 2016-5-30 12:30 上传 22222_副本.jpg (66.2 KB, ...

最新文章

  1. 即学即用的数据分析技巧
  2. 写了一个好玩的小软件, 监视鼠标以及键盘的动作, 全局钩子. HowTired
  3. pdfbox 按章节读取_2020年智慧树APP微生物与健康第五单元章节测试网课答案大学课后答案...
  4. mysql批量查询版本号最大的_mysql子查询批量找id最大的
  5. oracle 创建clob类型字段的索引,LOB字段相关概念(自动创建LOB索引段和重建索引方法)...
  6. java6 3_2018.3.6 Java web notes:
  7. .wav格式的声音文件怎么变成matlab 中的.mat文件
  8. Golang中interface{}作为函数参数和函数返回值的使用
  9. linux gdb基本概念
  10. oracle 高级用法, DECODE 排序, OVER(PARTITION BY X ORDER BY Y DESC) 开窗函数
  11. Linux复习-硬盘相关知识点
  12. 百度和bing的背景肤色图片的保存
  13. 如何对比评价TOM邮箱、QQ邮箱,Gmail邮箱以及139邮箱?
  14. Rust盒子玩家追踪、库存查询、Rust服务器数据统计功能更新
  15. Base64加解密__完整版有解释
  16. 禁止小程序输入Emoji表情符
  17. 电商网站之订单查询功能
  18. 王卫的新算盘?顺丰上线专享急件服务,从北京到上海收费上千元
  19. Java 敏感词过滤,Java 敏感词替换,Java 敏感词工具类
  20. 城市园区NB-IoT智慧井盖解决方案

热门文章

  1. RabbitMQ 交换机、队列、消息持久化
  2. Windows系列服务器上配置JSP运行环境,以及网站上线
  3. 第2期--从零开始仿制新浪微博---android
  4. SystemCenter2012SP1实践(2)部署证书服务器
  5. Android静默安装
  6. Dictionarystring,object性能之测试
  7. 06.SpringBoot的webjars和静态资源映射
  8. 分享 Android 手机屏幕录制并制作成 GIF 演示图片
  9. C++线程和Java线程的对比
  10. mysql 一台电脑多个服务_怎么在一台windows主机上安装多个mysql服务