基于金字塔和TOPN模型的SGM优化
代码
https://gitee.com/WN90/pyrsgm-sgm-pyramid-optimization
重要
x86_64上视差范围小的时候没有opencv中的SGBM快,后者使用simd加速了, 仅是个人研究的记录。如果opencv的结果不是很好,可以适当增加uniquenessRatio和 speckleWindowSize。
原理和思路
SGM算法的聚合方案是一个很伟大的方案,然而在亲自实现了之后才发现,速度很慢,占内存很大,图片大一点或深度大一点就要很久,严格来说,这是一个实现的问题,并不是算法的问题。
通过金字塔缩放的方式是一个降低计算量的比较好的方式,但是大尺度会比缩放的精度更高,如果通过小尺度的结果作为暗示,降低大尺度视差的搜索范围,那么可以降低内存占用和计算量。但是这样视差范围是不确定的,也就是不能直接分配一个固定大小的数组了,那么空间分配多少呢,不确定,所以很自然的考虑到分配N个,然后使用TOPN模型,保存N个代价最小的结果。
实现细节
缩放,对于通常的缩放,人眼看着不错,但是笔者认为,对于精准的两个图像匹配,期待的缩放方式应该是平均来看每个点都有均等的贡献,并且如果对应到最初始的图像,感受野应该是一个圆,越靠近圆心贡献越大。经过比较两种方案,最终选择了4x4方案。缩放比例为2。
# step = 2
0 1 1 0
1 2 2 1
1 2 2 1
0 1 1 0# step = 21 2 12 4 21 2 1
经比较,前者在贡献比例大的部分近似的贡献比例等值线近似于一个圆,贡献比例小的地方和多边形更接近,而后者在贡献比例大的地方更方,比例小的地方更圆。
小图像到大图像的对应关系为 2i+k, 2j+l, 如果是4x4的kernel,k和l取值范围为0 1 2 3, 3x3则为 0 1 2。
比较代码如下
import cv2
import numpy as npm = np.zeros((600, 600), dtype=np.float32)
# 4x4 step = 2
kernel = np.array([[0,1,1,0], [1,2,2,1], [1,2,2,1], [0,1,1,0]], dtype = np.float32)# 3x3 step =2
#kernel = np.array([[1,2,1], [2,4,2], [1,2,1]], dtype = np.float32)m[1, 1] = 1
#n = np.zeros((800, 800), dtype=np.uint8)#上采样,根据数字看所占比例
def map_up(low):up = np.zeros((1200, 1200), dtype=np.float32)for i, row in enumerate(low):for j, col in enumerate(row):if low[i,j] != 0:k = 0while k < len(kernel):l = 0while l < len(kernel[0]):#print(i,j,k,l," =======", 2*i+k, 2*j+l, "===========", low[i][j] * kernel[k][l])up[2*i+k, 2*j+l] += low[i][j] * kernel[k][l]l+=1k+=1return upm = map_up(m)
m = map_up(m)
m = map_up(m)
m = map_up(m)
m = map_up(m)
m = map_up(m)
m = map_up(m)
m = m/m.max() * 255
m = cv2.convertScaleAbs(m)#看等值线分布是不是一个圆形
n = cv2.inRange(m, 50, 240)
cv2.imshow("m", n)
cv2.waitKey()
cv2.destroyAllWindows()
4x4的结果:
3x3的结果
可见连续缩放之后的一个点,在最初始的图像上的贡献比例,4x4最中间(比例最大)更圆。上面是等值线构成的范围,对于4x4,真实的比例如下(亮度代表贡献比例):
假设缩放前高度H,缩放后高度h,则h = (H-4)/2 + 1,如果H-4不能被2整除,上侧跳过一个,宽度类似。一共有12个点对缩放之后的一个点做贡献,不考虑边界,每一个点对三个缩放之后的点做贡献。如果宽度上不整除的时候左右图都在左侧空一个不缩放,那么缩放前后视差不用做偏移,仅仅进行2倍放大就可以了。
这样缩放之后的一个点包含了多个点的信息,视差匹配的结果也代表了多个点的综合结果,如果这些点的视差差别很小,那么缩放之后的结果是准确的,然而这些点的视差可能差别比较大,这时可能就是不准的, 有两种方案,一种是upscale之后发现不准就舍弃,以upscale之后的为准,一种是考虑多种可能的匹配,而不是一个最佳的,在多种可能的匹配上确定一个最大值和最小值作为upscale之后的搜索范围,还有一种方案,在NxN范围内确定一个最大和最小(tSGM),最终确定的方案是第一种,简洁。
然而在小尺度没有匹配的情况下,不是使用最大视差范围,而是左右搜索,考虑在没有遮挡,并且正确匹配的情况下,左侧三个点 Al Bl Cl
,x坐标X(Al) < X(Bl) < X(Cl)
其中Al Cl
和右图Ar Cr
对应X(Ar) < X(Cr)
, 那么Br
一定是在[Ar Cr]
范围之内的,如果不是这样还望指正,根据这个约束,对于左图一个点X, 和左右两侧的点 Xl Xr,它们的视差分别为 D, Dl, Dr,满足如下关系
Xl - Dl <= X-D <= Xr-Dr
Dr + X - Xr <= D <= Dl + X - Xl
所以根据这个关系在一个lower层没有传递过来视差的点,可以左右搜索一定数量的点,就可以确定视差的范围了,为了避免碰到一片遮挡,以一定间隔的跳跃。
TOPN使用了大顶堆来实现,排除较大的代价。
效果
5层金字塔的时候,使用代码的data下面的图片得到的视差转换成彩色图如下
1层金字塔的时候,即不使用金字塔优化。
其中过滤小连通区域使用了
cv::filterSpeckles(result, 0, 50, 1);
传参
./pyrstereo ../data/*.png 0 170
代价计算使用了census(3 way) + 灰度值代价/4
当level >= 1的时候,无法选择正确匹配使用lower层的结果。
其他参数,P1, P2等使用代码中的默认参数。
在笔者的电脑上,整个进程执行的总时间,(包括读取换转换最终结果为彩色图片等操作),分别为1.548和2.613
如果不指定视差范围,时间分别为1.671和6.447,视差的彩色图(按顺序5层和1层金字塔)如下
注意不同层之间的颜色不能互相比较,因为是在一个图像上归一化之后的同一图像上的相对数值转换成彩色的结果。
不同参数,不同的惩罚计算方式,不同的代价计算,乃至代码中的upscale的方式,range获取的微小改动,都会对结果有很大影响,笔者调了好几天,也没找到一个足够理想的结果。理论上,缩放之后对抗有界的无纹理区域会比缩放前更好,但是要兼顾所有情况都能比较好就不太容易了。
总结和体会
最开始的时候看了一个金字塔优化的论文,tSGM,作者说在7x7的窗口内寻找最小和最大的视差,作为搜索范围,不清楚为什么,自己实现了之后,经过不停的思考,终于明白了,在lower层的结果扩大到upper层之后,不准的地方是视差变化的地方,尤其突变的地方,采用一定大小的窗口可以同时覆盖两边的部分,这时的最大最小一定是把正确的视差涵盖在内,不过暂时没有实现这种方案,以后有空还是要尝试一下。
在嵌入式设备上不依赖于GPU实时高精度双目匹配的目标还没有实现,还需继续努力,下一步打算使用倾斜平面的方案继续改进。
如果发现有错误,欢迎指正,欢迎有共同兴趣的朋友一起交流。
参考文献
SGM算法
H. Hirschmuller, "Stereo Processing by Semiglobal Matching and Mutual Information," in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 30, no. 2, pp. 328-341, Feb. 2008, doi: 10.1109/TPAMI.2007.1166.
一个使用金字塔优化改进的SGM
Rothermel, Mathias & Wenzel, Konrad & Fritsch, Dieter & Haala, Norbert. (2012). SURE: Photogrammetric Surface Reconstruction From Imagery.
Census扩展
Stein, Fridtjof. (2004). Efficient Computation of Optical Flow Using the Census Transform. DAGM-Symposium. 3175. 79-86. 10.1007/978-3-540-28649-3_10.
一个基于深度学习的,采用了金字塔思想的双目深度估计算法
Y. Wang et al., "Anytime Stereo Image Depth Estimation on Mobile Devices," 2019 International Conference on Robotics and Automation (ICRA), 2019, pp. 5893-5900, doi: 10.1109/ICRA.2019.8794003.
Middleburry数据集
D. Scharstein, H. Hirschmüller, Y. Kitajima, G. Krathwohl, N. Nesic, X. Wang, and P. Westling. High-resolution stereo datasets with subpixel-accurate ground truth. In German Conference on Pattern Recognition (GCPR 2014), Münster, Germany, September 2014.
EthanLi的SGM教学及代码
[https://ethanli.blog.csdn.net/](https://ethanli.blog.csdn.net/)
[https://github.com/ethan-li-coding/SemiGlobalMatching](https://github.com/ethan-li-coding/SemiGlobalMatching)
感谢SGM作者带来这么好的聚合方式,和EthanLi博客的详细讲解,感谢Middleburry数据集作者提供的高清的带有groundtruth的立体图片。
基于金字塔和TOPN模型的SGM优化相关推荐
- 阿里 NIPS 2017 Workshop 论文:基于 TensorFlow 的深度模型训练 GPU 显存优化
NIPS 2017 在美国长滩举办,场面非常热烈.阿里巴巴一篇介绍深度模型训练 GPU 显存优化的论文<Training Deeper Models by GPU Memory Optimiza ...
- 计算机软件模型改进,基于改进Kano模型的服务优化研究_樊根耀.docx 计算机软件及应用...
第34卷第5期重庆理工大学学报(自然科学)2020年5月Vol. 34 No. 5Journal of Chongqing University of Technology (Natural Scie ...
- 基于深度学习实现语义识别和问答判断模型及算法优化-制造业-CSDN公开课-专题视频课程...
基于深度学习实现语义识别和问答判断模型及算法优化-制造业-1685人已学习 课程介绍 本次课程,邀请IBM研究院讲师就制造业语义识别及判断模型搭建.QA模型.词向量.句子量化.POWE ...
- 基于粒子群算法的微电网优化调度应用研究(四、基于粒子群算法的调度模型)
基于粒子群算法的调度模型 4.1 目标函数 离网型的微电网包含各种分布式发电,如风力发电机组.光伏电池等,光伏和风力发电受自然资源的影响,输出功率不受控制,很难人工调度,其一次设备成本高,而微电网完全 ...
- 【CVPR2018】PSMNet:一个基于金字塔的端到端立体匹配网络
PSMNet:一个基于金字塔的端到端双目立体匹配网络 1.简介 在本研究中,我们提出了一种新的金字塔立体匹配网络(PSMNet)来利用立体匹配中的全局上下文信息.空间金字塔池(SPP)和扩张卷积用 ...
- PANet:基于金字塔注意力网络的图像超分辨率重建(Pytorch实现)
PANet:基于金字塔注意力网络的图像超分辨率重建 [!] 为了提高代码的可读性,本文模型的具体实现与原文具有一定区别,因此会造成性能上的差异 文章目录 PANet:基于金字塔注意力网络的图像超分辨率 ...
- 基于SVD++隐语义模型的信任网络推荐算法
点击上方蓝字关注我们 基于SVD++隐语义模型的信任网络推荐算法 陈佩武1, 束方兴2 1 平安科技(深圳)有限公司,广东 深圳 518031 2 北京大学互联网研究院(深圳),广东 深圳 51805 ...
- CUDA上的量化深度学习模型的自动化优化
CUDA上的量化深度学习模型的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参 ...
- 基于C++的PyTorch模型部署
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 引言 PyTorch作为一款端到端的深度学习框架,在1.0版本之后 ...
最新文章
- LaTeX技巧006:使用pdfLaTeX时,添加PDF文件属性的方法
- 【译】权益证明的设计理念
- QT的QDesignerWidgetBoxInterface类的使用
- 读书笔记(06) - 语法基础 - JavaScript高级程序设计
- 完整机器学习项目的流程
- 内存耗尽后,Redis会发生什么?
- 非华为电脑配对华为手机(RMB+5899¥)
- 学习-【前端】-angularjs基本框架以及向服务器发送请求的方法
- 美图秀秀丰胸一秒变身D罩杯图片美容处理软件
- 花花公子推荐伤感qq日志:乖不哭,我拜你
- 微信小程序实现多图片下载
- QQ的常用快捷键大全
- 测试自动化风险或成功的条款
- solid works旋转、抽壳的应用
- jar启动出错:Failed to get nested archive for entry BOOT-INF/lib/activiti-core-common-dependencies-7.1.0
- 跑深度模型的显卡_近乎白嫖!我的深度学习云GPU平台!便宜、好用、速来!
- 人民币大写与数字互转
- 高德地图看各省分界线_从高德采集最新的省市区三级坐标和行政区域边界,用js在浏览器中运行...
- 微量元素可增加宝宝食欲
- python pyserial 使用大全
热门文章
- 在本地利用服务器显卡跑代码
- 固体或粘性液体,取决于分子量,FMOC-PEG-COOH,芴甲氧羰基-聚乙二醇-羧基,acid-PEG-FMOC,取用一定要干燥,避免频繁的溶解和冻干
- 全国车辆违章查询数据接口文档及demo
- appium连接夜游模拟器失败的解决办法,即在dos命令中输入adb devices查不到设备的解决办法(只针对夜游模拟器)
- iOS Info.plist
- 计算机机房ups供电时间多少,机房ups电源供电时间及要求有哪些?
- 使用ssh公钥私钥登陆服务器并配置Sublime的SFTP通过私钥登陆
- 记一次AOP+反射动态修改注解值成功后注解没有生效
- 2019 AI算法岗求职攻略
- RocketMQ源码(十)—Broker 消息刷盘服务GroupCommitService、FlushRealTimeService、CommitRealTimeService源码深度解析