双目视觉标定实测问题小记录

Opencv python 双目视觉标定问题小节

这段时间导师让我们学一点关于双目视觉的东西,由此有了这篇文章,以来记录测试时遇到的各种问题以及如何解决。

前置知识

首先在了解视觉标定的相关基础知识时,我对视差如何计算有点不解,主要分不清xl-xr的时候用的是哪个坐标系,经过一番查找资料,最后知道了求xl-xr时其实用的是图片像素坐标,也就是图片校正完后的相关对应点的各自像素坐标相减。其实很简单的一个问题,但当时就是卡壳了以下,具体可参考此篇博客,写得相当详细:
双目测距与三维重建的OpenCV实现问题集锦

关于几大坐标系的转换以及相机相关参数的理解可参考以下博客:
模型 16个相机参数(内参、外参、畸变参数)

坐标系

具体实践

刚开始我把所有的步骤都集中在python + opencv上完成,但到了校正环节,发现遇到了与书上例子不同的情况,即校正完毕后,我的两张图片并没有行对齐,因此在这一环节卡了许久。首先我以为是自己的棋盘图片原因,因此用了官方例子上的棋盘图片,但还是不行,然后我又仔细看了一遍代码,发现也没问题,我就开始怀疑是否为python版本的opencv本身原因,想着换c版本的运行一遍,但正当我想换C时,在网上发现了这篇博客
opencv实现立体匹配
对于当时的我简直如获至宝,因为其遇到的问题跟我一样,他最后选择用matlab来获取标定数据,于是在百度云的重重网速限制下,我安装了matlab,经过尝试,果然最后能标定成功,因此得出结论为opencv自身标定方法确实有严重偏差。

未解决问题

当完成立体标定后,到了最后一步,获取视差图及深度并转换成世界坐标。老实说,这一步的函数没几个,但都令人头疼。
我用的是SGBM算法, 即opencv中的StereoSGBM这个函数,从网上找了相关运行参数,觉得挺详细的,就码了下来

SGBM_blockSize = 5  # 一个匹配块的大小,大于1的奇数
SGBM_num = 2
min_disp = 0  # 最小的视差值,通常情况下为0
num_disp = SGBM_num * 16  # 192 - min_disp #视差范围,即最大视差值和最小视差值之差,必须是16的倍数。
# blockSize = blockSize #匹配块大小(SADWindowSize),必须是大于等于1的奇数,一般为3~11
uniquenessRatio = 6  # 视差唯一性百分比, 视差窗口范围内最低代价是次低代价的(1 + uniquenessRatio/100)倍时,最低代价对应的视差值才是该像素点的视差,否则该像素点的视差为 0,通常为5~15.
speckleRange = 2  # 视差变化阈值,每个连接组件内的最大视差变化。如果你做斑点过滤,将参数设置为正值,它将被隐式乘以16.通常,1或2就足够好了
speckleWindowSize = 60  # 平滑视差区域的最大尺寸,以考虑其噪声斑点和无效。将其设置为0可禁用斑点过滤。否则,将其设置在50-200的范围内。
disp12MaxDiff = 200  # 左右视差图的最大容许差异(超过将被清零),默认为 -1,即不执行左右视差检查。
P1 = 600  # 惩罚系数,一般:P1=8*通道数*SADWindowSize*SADWindowSize,P2=4*P1
P2 = 2400  # p1控制视差平滑度,p2值越大,差异越平滑

SGBM_stereo = cv.StereoSGBM_create(
            minDisparity=min_disp,  # 最小的视差值
            numDisparities=num_disp,  # 视差范围
            blockSize=SGBM_blockSize,  # 匹配块大小(SADWindowSize)
            uniquenessRatio=uniquenessRatio,  # 视差唯一性百分比
            speckleRange=speckleRange,  # 视差变化阈值++++++
            speckleWindowSize=speckleWindowSize,
            disp12MaxDiff=disp12MaxDiff,  # 左右视差图的最大容许差异
            P1=P1,  # 惩罚系数
            P2=P2![在这里插入图片描述](https://img-blog.csdnimg.cn/2019102817164578.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nseng1NTEx,size_16,color_FFFFFF,t_70)
        )

当然还有BM算法:

num = cv.getTrackbarPos("num", "depth")
blockSize = cv.getTrackbarPos("blockSize", "depth")
if blockSize % 2 == 0:
     blockSize += 1
if blockSize < 5:
     blockSize = 5
stereo = cv.StereoBM_create(numDisparities=16 * num, blockSize=blockSize)

两个算法我都试了下,最后得出的实时视差图显示都不理想,在这里插入图片描述总之跟马赛克一样,,跟网上的例子相差许远,问了师兄,师兄说是相机问题,他也是同样的情况,换个好点的相机就好一点了,,

然后在返回世界坐标这一步,用了reprojectImageTo3D这个函数,在查看返回的坐标系时发现极其不精准,有负数的,有距离极其夸张的,甚至在获取相同点在离摄像机不同的距离的情况下其返回的坐标是不变的。
在这里插入图片描述
这一点到目前为止都不清楚是怎么回事。。

为此我简化过程根据Z = K/D 这个公式,手动测试了下不同距离下的棋盘图片两个相对的角点的距离比:
在这里插入图片描述首先根据校正所求的Q矩阵获取参数f,Tx。
后来我一想因为我只想获取对应的距离关系,所以简化公式为Z = 1/D;
在这里插入图片描述

对两组距离比为1.5的棋盘图片做了测试,结果还算满意:
在这里插入图片描述
在这里插入图片描述
确实为1.5倍的样子,同时也说明了视差就是像素坐标相减。

小结

其实就是一些简单的概念加函数使用问题,但最后的坐标转换还是未解决,先记录下,日后再说吧.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值