立体标定

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

标定

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

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

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

相关文章

if _name_ == _main_

1.作用 py文件有2种使用方法&#xff0c;第1是自己本脚本自己独立执行&#xff1b;第2是被import到其他文件脚本中执行. if _name_ " _main_" 该语句控制其他下一步的脚本是否执行。如果是自己本脚本独立执行&#xff0c;那就运行该if条件下的脚本&#xff1b;如果…

LLVM完整参考安装

文章目录 一、直接下载编译好的,见图片命令二、下载源代码自己编译安装 下面提供下载并mv完全的文件包三、安装LLVM编译器一、直接下载编译好的,见图片命令 这里使用llvm官网编译好的包, 直接解压即可用LLVM下载官网点击这里下载llvm-6.0.1 下载完成后解压tar -vxf clangllv…

微软正式释出基于 Chromium 的 Edge 预览版本

百度智能云域名服务&#xff0c;.com新用户首购仅需25元 微软基于 Chromium 的全新版本 Edge 一直吸引着开发者与用户的目光&#xff0c;当地时间 8 日&#xff0c;官方终于释出了第一个 Dev 和 Canary 频道构建版本。 Dev 与 Canary build 都是开发者预览版&#xff0c;同属…

下载和安装R、RStudio !

现如今&#xff0c;R语言是统计领域广泛使用的工具&#xff0c;是属于GNU系统的一个自由、免费、源代码开放的软件&#xff0c;是用于统计计算和统计绘图的优秀工具。而RStudio是R的集成开发环境&#xff0c;用它进行R编程的学习和实践会更加轻松和方便。下面就教大家如何下载并…

豆瓣首页话题输入框的实现

在做问答的时候&#xff0c;遇到一个需求&#xff0c;用户的问题需要限制字数&#xff0c;不仅显示计算的超出字数&#xff0c;还需在超出的内容上加一些提醒的效果&#xff0c;例如豆瓣首页的话题输入框&#xff0c;抽时间研究了下&#xff0c;需要考虑下面几个问题&#xff1…

pytorch 吸烟检测yolov5s

YOLOV5s 吸烟目标检测 参考学习 文章目录 本原创项目长期更新&#xff0c;旨在完成校园异常行为实时精检测&#xff0c;作到集成N次开发优化&#xff08;不止局限于调包&#xff09;为止&#xff0c;近期将不断更新如下模型数据标注文件教程。关注博主&#xff0c;Star 一下g…

JQuery的ajax函数执行失败,alert函数弹框一闪而过

先查看<form>标签是否有action属性&#xff0c;如果没有&#xff0c;并且最后<button>标签的type属性为submit‘时&#xff0c;默认提交位置就是当前页面 如果在页面右键检查&#xff0c;点击网络&#xff0c;会在开头发现这样的post包&#xff1a; 在右侧消息头处…

C#中Request.ServerVariables详细说明及代理

Request.ServerVariables("Url") 返回服务器地址Request.ServerVariables("Path_Info") 客户端提供的路径信息Request.ServerVariables("Appl_Physical_Path") 与应用程序元数据库路径相应的物理路径Request.ServerVariables("Path_Transla…

coco与voc相互转化

把LabelImg标注的YOLO格式标签转化为VOC格式标签 和 把VOC格式标签转化为YOLO格式标签 点亮&#xff5e;黑夜 2020-07-07 11:08:24 3537 已收藏 90 分类专栏&#xff1a; 19—目标检测 文章标签&#xff1a; voc yolo 版权 把LabelImg标注的YOLO格式标签转化为VOC格式标签 和…

angular中封装fancyBox(图片预览)

首先在官网下载最新版的fancyBox(一定要去最新网站&#xff0c;以前依赖的jquery版本偏低)&#xff0c;附上链接&#xff1a;http://fancyapps.com/fancybox/3/ 然后在项目中引用jquery&#xff0c;然后在引用jquery.fancybox.min.css和jquery.fancybox.min.js。 如果需要动画和…

十二省联考题解 - JLOI2019 题解

十二省联考题解 - JLOI2019 题解 两个T3的难度较大 平均代码量远大于去年省选 套路题考查居多 A 难度等级 1 $n^2$暴力可以拿到$60$分的优秀成绩 然后可以想到把区间异或转化为前缀两点异或 可以想到使用二分答案的方法可持久化Trie解决&#xff0c;但是时间复杂度为$n\log^2 (…

前端vue的get和post请求

vue的get和post需要两个文件vue.js和vue-resource.js 以下是实现的代码&#xff0c;可以参考一下&#xff0c;需要注意的接口的请求需要考虑跨域的问题&#xff0c;其次就是访问页面需要在tomcat下访问&#xff0c;否则也会报跨域的问题 <!DOCTYPE html> <html lang&q…

[Vijos 1143]三取方格数

Description 设有N*N的方格图&#xff0c;我们将其中的某些方格填入正整数&#xff0c; 而其他的方格中放入0。 某人从图得左上角出发&#xff0c;可以向下走&#xff0c;也可以向右走&#xff0c;直到到达右下角。 在走过的路上&#xff0c;他取走了方格中的数。&#xff08;取…

线扫相机相关规格说明

工业线阵相机与面阵相机特点分析 点滴成海~ 2018-06-29 13:50:38 12184 收藏 29 分类专栏&#xff1a; intership 文章标签&#xff1a; 视觉元件分析 版权 最近在公司实习&#xff0c;实习中的项目是使用的是微视的一款线阵相机&#xff08;Microview MVC1024DLM-GE35&…

postgresql 不同数据库不同模式下的数据迁移

编写不容易,转载请注明出处谢谢, 数据迁移 因为之前爬虫的时候&#xff0c;一部分数据并没有上传到服务器&#xff0c;在本地。本来用的就是postgresql&#xff0c;也没用多久&#xff0c;数据迁移的时候&#xff0c;也遇到了很多问题&#xff0c;第一次使pg_dump xx > file…

Oracle中主键自增长

最近在学习Oracle和MySql&#xff0c;MySql有自动配置主键自增长auto_increment&#xff0c;这样在输入数据的时候可以不考虑主键的添加&#xff0c;方便对数据库的操作。 在Oracle中设置自增长首先用到sequence序列&#xff1b; 以创建学生表为例&#xff1a; create table St…

3.单例模式

public class Singleton {//定义私有的静态变量 private static Singleton singleton;//私有化构造函数private Singleton(){}//获取实例public static Singleton getInstance(){//同步前判断避免同步的性能损耗if(nullsingleton){//预防多线程问题synchronized(Singleton.clas…

docker与mmdetection

这里不再介绍 mmdetection 的安装和配置&#xff0c;使用 mmdetection 较简单的方法是使用已安装 mmdetection 的 docker 容器。这样直接省去了安装 mmdetection 的过程&#xff0c;让重心放在模型训练上&#xff01; 如果你对 docker 和 mmdetection 还不是很熟悉&#xff0c…

互联网平台掘金三四五线城市,你需要知道的9.9个真相

互联网上半场结束&#xff0c;一二线城市流量红利消失&#xff0c;许多互联网平台、投资机构一度经历至黑之夜。融资失败、公司倒闭、大裁员迭出。对比鲜明的是&#xff0c;深耕三四五线城市的互联网平台正在迅猛崛起。春节期间&#xff0c;小部分敏锐的业者注意到互联网产品在…

平滑重启更新(GR机制)

平滑重启更新&#xff08;GR机制&#xff09; 什么是平滑启动机制 是一种在协议重启时保证转发业务不中断的机制。什么时候用到平滑重启 平滑重启一般应用于业务更新或者版本发布过程中&#xff0c;能够避免因为代码发布重启服务导致的暂时性服务不可用的影响。ngnix 平滑重启和…