比cvFindContour()更快的替代方法

9
轮廓检测是计算机视觉中占据了我大部分时间的工作,需要更快的速度。通过使用NEON指令和向量化优化了其他所有内容,但轮廓检测仍然占据着主导地位。不幸的是,我不知道如何对其进行优化。
我正在使用经典的矩形检测流程来查找基准标记,即cvFindContours(),然后从轮廓中近似出正方形。在许多标记可见的情况下(或者灾难性地,当可见的矩形网格不是标记时),仅调用cvFindContours()就可能需要超过30毫秒的时间在iPhone上。
我已经用cvFindContours()替换了非常昂贵的C++ cv::FindContours()。特别是如果传递一个vector >,C++版本花费更长的时间来分配和填充向量,比内部的cvFindContours()还要慢!
现在,我完全受制于cvFindContours中的时间,或更具体地说,受制于cvFindNextContour()的时间。cvFindNextContour内部的代码有很多分支,不太容易向量化。它还实现了一个复杂的算法,我不相信自己能在任何优化尝试中不出错。
我已经查看了cvBlobLib(为了消除歧义,我指的是这个网址:http://code.google.com/p/cvblob/),看看它是否提供了可以更快地完成相同任务的替代算法。源代码的基本下载非常缓慢,因为它将轮廓记录到std::list()中,并几乎所有时间都花在内存分配上。用预先大小为256个元素的std::vector替换该列表以消除push_back()上的初始复制仍然会使函数的运行时间比cvFindContours()长3倍,其中66%直接在cvb::cvLabel()中。因此,这种方法似乎不可行。
有没有人有任何想法可以优化检测许多矩形。我的模糊手势包括:
  1. 是否有与cvFindContour()等效的快速实现, 最好是源代码,因为我需要多平台支持?

  2. 只有“成功”的矩形是有用的,大多数轮廓都不需要,特别是它们的内部轮廓是无用的。从理论上讲,我不需要调用cvFindContours,而是可以调用cvStartFindContours / cvFindNextContour,在找到每个轮廓时进行测试,并且如果我找到所需的矩形,则不进行递归,因为子矩形保证是无用的?

  3. 是否有完全不同的矩形检测算法可以使用,而不是经典的FindContours() / ApproxPoly()方法?

  4. 有没有一种方法可以使用感兴趣的区域来"引导"cvFindContours? 例如,即使采用非常激进的阈值,FAST角点检测几乎总是返回我的基准标记角落。有没有办法使用该点集来限制检测范围? (不幸的是,对于我的应用程序中经常出现的许多标记或与标记无关的密集网格线而言,我不确定这有多大帮助。)

  5. 与上面相同的想法,由于Blob检测(如果我理解正确)可以实现为递归洪水填充,因此是否有任何快速的矢量化实现可用于从中提取有趣的Blob矩形,并从那里开始进行轮廓检测的种子?

欢迎提出任何想法!


仅就你的第5点发表一下评论。泛洪填充通常不是检测斑点最有效的方法。相反,您应该使用双通或单通算法,其中一些可以并行化。维基百科上的“连通组件标记”页面是一个很好的起点。 - Francesco Callari
1
这里有任何更新吗?有新的见解吗?我有一个类似的问题。 - Antonvh
快速AR标记检测算法不使用findContours,而是在梯度图中找到部分边缘(并行),然后将其重新组装成完整的边缘,最终形成四边形。 - Christoph Rackwitz
你能提供一张样例图片吗?你想要什么类型的检测? - sturkmen
@stukmen 或许可以参考这个链接 https://frl.nyu.edu/wp-content/uploads/2.jpg 很抱歉,我无法提供一个确切的使用案例示例。 - MrZander
@ChristophRackwitz 你的意思是霍夫直线算法吗? - MrZander
1个回答

3
由于您的目标是矩形检测而不是轮廓检测,我建议使用积分图像进行计算。可以在此处找到有关积分图像的说明:here。计算所需图像的积分图像后,可以通过三个操作计算矩形的像素和。
假设您想在每个非黑色对象周围绘制矩形,则可以使用以下方法。递归地将图像及其子图像分成4份,并丢弃像素总和低于所需阈值的矩形。您将得到许多小矩形来近似表示您的对象。合并相邻的矩形将产生快速近似您检测到的对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接