文章目录
- readme
- issue 1 如何加快responsemap的创建?
- issue 2 请问一下是否抗缩放呢?
- issue 3 匹配准确
- 定位精度还能再提高吗?
- branch有些多了,能否写个文档介绍一下各branch的功能
- response map fusion implementation
readme
与opencv linemod 源码相比,我们从6个方面进行了改进:
- 删除深度模式,所以我们不需要虚拟函数,这可能会加快
- opencv linemod最多只能使用63个特征。现在我们可以有8191个
- 简单代码,旋转和缩放模板图像用于训练。有关示例,请参见test.cpp
- nms用于精确的边缘选择
- 单通道方向提取节省时间,对于灰度img稍微快一些
- 对于多种平台SIMD,可以使用MIPP。例如x86 SSE AVX, arm neon。为了获得更好的性能,我们将MIPP扩展到uint8_t来执行一些指令。(否则我们只能使用一半特征点来避免int8_t溢出)
- 直接旋转特征以加速模板提取;
选择分散特征会更均匀;
如果特征数不够的话,尽可能选择所有特征,而不是抛弃模板(但是features <= 4将自动丢弃)。
issue 1 如何加快responsemap的创建?
- 测试中发现整个时间,大部分用于了创建responsemap, 请问这个过程可以有办法加速么?例如我有张130万像素的图片,用了150ms创建的,有办法加快么?
有,还可以加速一个量级。
目前的速度瓶颈在opencv的filter上,我之前研究过,opencv用到的加速技巧有separeble filter, SIMD。还可以用的技巧有parallelism、kernel fusion(sobel phase pyrdown大部分都能fuse起来)。
其实这个要写的可读性好、速度最快还挺难的。不过有一帮大神有专门为这个设计了个DSL(domain specified language) halide talk, halide github,非常不错,不直接用也可以参考下思路。
-
opencv里面算高斯 sobel是用可分离卷积算的。fusion这个问题halide talk里面讲的非常好。
halide talk里讲的方法我总结一下,请你看看大致是不是这样:
1)locality。实际上和linearize的思想差不多,就是将内存的读取做成cache-friendly,并且减少重复读取。具体的做法就是用当前读取到的内存做尽可能多的计算,这应该也就是fusion的意思。
2)parallel。这个和使用cpu向量指令集和openmp是一样的,但难点在于同时要照顾到locality。
halide会通过它的方法帮我们实现locality和parallel的优化,但代价就是要使用它的语法将计算组成pipeline。
但说实话,这个代价还挺大的,因为它的资料感觉挺少的,即使是opencv中常用kernel的组合,网上都找不到现成的例子。我自己尝试了halide的官方的例子,连编译都通不过。。。
另外,opencv似乎想要实现一个叫mini-halide的东西,但还只是在draft阶段。
-
SSE优化
-
本案例对标的是halcon的find_shape_model算子
issue 2 请问一下是否抗缩放呢?
- 目的:想识别很小图的轮廓;
但是直接拿很小图的训练,好像很难拿到足够的特征;
直接使用大图训练可以拿到足够多的特征,但是不能直接使用训练的结果去识别小图,我该怎么做呢?
一般能拿到10个点左右,在不复杂的背景下也还好。如果背景复杂导致太多误匹配,可以试试把stride放小点,就是第二个参数{4, 8}改成{2, 4}之类的。这样虽然多费点时间,但是方向扩散也会变小。
当然也可以试试把小图也放大再识别。
issue 3 匹配准确
- NVlab的DOPE,跟这个算法相比,孰优孰劣?
我觉得模板匹配优点是比较可靠。深度学习这种可能不会这么稳定,虽然靠生成大量样本来提升可靠性,但比如一个零件沾了点灰,颜色变,有阴影了等等,识别不识别就不确定了。模板匹配是有理论保障的,只要能提到边缘方向就能识别。当然缺点也很明显,适用范围很窄,纹理多了,不是固定形状(比如识别个人)等等就不行。刚好工业上识别固定形状的场景比较多,所以这个算法是halcon定位模块里面比较核心的一个。
有纹理的话,SIFT之类的一般就行了。而且如果segmentation可靠的话,后面加一些处理也能很快得到pose,比如super4pcs,global registration,也可以就在mask范围内模版匹配。
定位精度还能再提高吗?
小目标当然层数少点好,我试了下,用一层也没问题呀 {4, 8} --> {4} / {2} 都行。最好不要用{1},扩散一格等于不扩散。
也不一定层数少好,一般保证最上层至少8个点左右就行,能选出candidates快速筛选。
扩散也是,用扩散的好处是能像金字塔一样降低分辨率加速,但不会像金字塔一样边缘都没了;所以扩散大小也需要tradeoff,扩散大cnadidates多,但背景不是很杂乱的话扩散大可以帮助我们快速筛掉纯色背景的位置。
一般来说,两到三层金字塔,2 / 4 / 8的扩散可以应对绝大多数情况,小目标就往小调点。
branch有些多了,能否写个文档介绍一下各branch的功能
- icp2D没用亚像素
- sbupixel是亚像素
- sim3是亚像素同时加入了尺度优化。这些没有改master里的东西,只要把icp的folder加进来就能用。
- rotate_templ已经merge到master,跟master一致;
- inv_light是把角度相差180度也纳入考虑,跑noise_test可以看到最后一种白变黑的情况没有匹配。
- fusion_by_hand是尝试用fusion加速整个过程,
response map fusion implementation
Halide的论文指出,融合可以极大地改善响应图的生成,但配置 Halide 并不是一件容易的事,而且我们的响应图也不需要 Halide 的很多特征。因此,最好实现一个简单版本的 tile-based fusion method (基于tile的融合方法)。这也是opencv4正在做的事情。
目前,一个简单的 基于tile的融合 管道被实现,gaussian/ sobel / mag / phase / hist / spread…已完成并经过测试。更多信息请参考 fusion_by_hand 。基本的想法是只实现基于tile的融合,手工完成Halide的编译工作……虽然它看起来不像Halide那么迷人,但它大大简化了工作,也很容易使用。
速度大约比使用opencv快10倍。我们将在将来使用它来创建响应映射。
更多示例请参见test_fusion.cpp。此外,欢迎任何讨论、测试或改进!
现在我们通过了所有的测试,匹配函数就可以正常使用了! 对于创建响应映射的完整管道来说,它大约快了6倍,而且不需要像以前那样将图像裁剪到16n。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)