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

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

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

标定

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

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

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

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

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

在进行标定的过程中,要注意的是在上面标定方法中没有提到的是,单个标定后,要对标定的数据进行错误分析(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 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,这些参数都将应用于下面的转换成深度图中

转换成深度图

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图,按照上面的代码,在图上点击则可以读取到该点的距离

时间: 2024-07-29 10:43:21

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

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

我发现我的手机无法再eclipse里面输出自己打的log.i等log,一开始还以为是我手机root或刷过机的问题,在百度上找解决方法,并尝试了好久啊啊啊啊啊. 最终非常偶然找到了解决的方法: 酷派大神f1,f2在出厂时将log的级别做了限制. 解除限制的方法是:拨号盘输入*20121220# -> 选择日志输出级别 -> 选择Java log level -> 选择LOGD即可. .....真真是万万没想到解决方法居然如此简单! 或许酷派别的手机也做了这样的log等级限制,如果发现别的酷

帮用户解决以往消费中的例如信息不透明、使用不便捷、无法按照服务质量付费等痛点(转)

在所有还算得上成功的互联网公司中,大众点评一直是一个异类. 它既不会像其它公司那样像坠落凡间的天使,只需要短短几年的修复,迅速克隆一个“美国公司”,就立马可以腾云驾雾,再次回到天堂:也不像那些泯然众人的公司那样,似乎永远不在舆论的中心,但一直默默在赚钱,只是在某一个瞬间,纳斯达克的钟声将人们唤醒,“哦,原来它这么厉害”! O2O 2.0 的演变 7 月 22 日,久不露面的大众点评 CEO 张涛出现在了成立丽人事业部的发布会上,除了为其新拓展的丽人事业部站台之外,张涛对外纰漏了大众点评未来的发展

辛星彻底帮您解决CSS中的浮动问题

浮动,是CSS布局中必须经过的一道坎,如果不熟悉浮动,那么CSS的布局就如同空中楼阁,而谈到浮动,更多的是和div相结合,div是一个块级元素,这个我前面的博文有介绍,如果大家喜欢我的风格,可以搜索下. 下面我们进入正题,所谓浮动,可以用css的属性float来定义,比如float:left就是向左浮动,float:right就是向右浮动,我们先看一个不浮动的例子把,首先是这个html文件,这个文件我们是一直都不会动它了,它的内容如下: <html> <head> <link

opencv标定程序

资源下载见:http://download.csdn.net/detail/zhouyelihua/7726907 在Vs2012中只要直接按f5就可以直接对资源中采集的图像进行标定. 而我们将最后的结果以.xml的形式存储下来.这个在工程文件下可以直接找到的 其中外参数,中旋转矩阵存在rotation.xml 位移向量存在translation.xml 内参数:内部矩阵存在Intrinsics.xml 畸变系数存在Distortion.xml 具体程序如下:(改自于<learning open

涂料消泡剂彻底帮你解决泡沫烦恼

众所周知涂料使用时最忌讳气泡针孔的出现,一单出现这种问题,如果不及时解决就可能导致一件产品的失败.气泡和针孔的产生主要有两个方面:一在使用过程中使用不规范导致气泡和针孔的出现,这样可以通过正确的指导消除,二生产工艺不完善,这个可以在生产过程中加入涂料消泡剂就能解决.中联邦生产的涂料消泡剂彻底帮你解决泡沫烦恼. 涂料消泡剂是有机聚醚酯化物.矿物油.醇复合型产品,经过特殊工艺精制而成.具有自乳化.易分散.通用性强.抑泡持久等性能.不会产生表面缺陷或影响成膜性,对水性涂料体系有特别效果. 涂料消泡剂主

Nacos 帮我们解决什么问题?(配置管理篇)

Nacos 是阿里巴巴今年7月份开源的项目,如其名, Naming Configuration Service ,专注于服务发现和配置管理领域.本系列文章,将从 5W1H(What.Where.When.Who.Why.How)全面剖析 Nacos,给大家安利一下 Nacos.本文作为 Nacos 系列文章的开篇,也就从 "What" 开始.我们开始关注一个开源项目的时候,通常最先冒出的 2 个问题是: 它是什么? 它帮我们解决什么问题? Nacos 是什么?上面已经大概介绍了,更多详

Zookeeper 到底能帮我们解决哪些问题?

Zookeeper 从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应,从而实现集群中类似 Master/Slave 管理模式,关于 Zookeeper 的详细架构等内部细节可以阅读 Zookeeper 的源码 下面详细介绍这些典型的应用场景,也就是 Zookeeper 到底能帮我们解决哪些问题?下面将给出

[转] Win10插入U盘后双击无法打开,无法访问,显示设备未就绪;驱动哥帮你解决

说起U盘,相信大家都不陌生. 这个不起眼的小东西在我们日常生活息息相关,一旦损坏可能就会造成一些不必要的麻烦. 最近驱动哥就收到了一大批用户关于U盘问题的相关咨询,一起来看看到底是什么情况吧! 据其中的一位用户反馈,他的电脑是win10系统在插入U盘后却打不开,但是在其他电脑上却可以正常使用,这是什么情况? 下面大家就和驱动哥一起来看看到底是什么情况! 当用户将U盘插入电脑后,电脑上里面及弹出一个[设备未就绪,无法访问]的提示. 遇到这种情况,当然是需要打开驱动人生进行检查啦. 驱动哥指导用户将

求大神帮我解决下webuploader另外添加参数的问题,我知道是formData添加额外参数给后台

如图所示: 我点击开始上传的时候.会有3个请求,等于是他会返回我3次action,我在后台添加了额外的2个参数dkName,Moneys. 求大神可以帮我看看如何改写下:我需要他每一个请求只会带上图下当前的点卡名称和点卡金额,如果有大神大牛乐意帮助下我,可以加我QQ79612086或者在下面回复,我会及时收看,谢谢!!