蛇算法 - opencv 活动轮廓 - 效果不佳

Posted

技术标签:

【中文标题】蛇算法 - opencv 活动轮廓 - 效果不佳【英文标题】:Snake Algorithm - opencv active contour - not working so well 【发布时间】:2013-07-09 01:06:11 【问题描述】:

我实际上正在研究头部的轮廓检测。由于图片是在白墙前拍摄的,所以我决定对经过阈值处理的图片运行snake(主动轮廓模型算法)。

问题是蛇不适合鼻子、嘴巴和嘴巴下方(如下图所示)。

//load file from disk and apply threshold
IplImage* img = cvLoadImage (file.c_str (), 0);
cvThreshold(img, img, 170, 255, CV_THRESH_BINARY);

float alpha = 0.1; // Weight of continuity energy
float beta = 0.5; // Weight of curvature energy
float gamma = 0.4; // Weight of image energy

CvSize size; // Size of neighborhood of every point used to search the minimumm have to be odd
size.width = 5;
size.height = 5;

CvTermCriteria criteria;
criteria.type = CV_TERMCRIT_ITER;  // terminate processing after X iteration
criteria.max_iter = 10000; 
criteria.epsilon = 0.1;

// snake is an array of cpt=40 points, read from a file, set by hand
cvSnakeImage(img, snake, cpt, &alpha, &beta, &gamma, CV_VALUE, size, criteria, 0);

我尝试更改 alpha/beta/gamma 参数或迭代次数,但没有找到比下面显示的输出更好的结果。我不明白为什么鼻子被割掉,脸不适合嘴巴。我猜我有足够的曲率点,但仍有一些线由几个 (>2) 点组成。

输入图片:

输出蛇:

蓝色:手动设置的点

绿色:输出蛇

任何帮助或想法将不胜感激。 谢谢!

【问题讨论】:

您能否发布有关您正在使用哪种活性轮廓配方的信息? @nav 我不太了解活动轮廓的公式或实现,我使用的是 OpenCV 的蛇算法。我听说,这个实现不是最好的,我想我会自己实现它,也许是理解算法的最好方法...... 【参考方案1】:

典型的蛇形或主动轮廓算法会在 3 种成本函数之间进行权衡:边缘强度/距离(数据项)、间距和平滑度(先验项)。立即,您可能会注意到与您的“鼻子问题”有关 - 鼻子有很高的曲率。你的蛇也很难进入凹面区域,因为与凸包相比,这肯定会增加它的曲率。

解决方案: A. 由于您的蛇性能并不优于凸包之一,因此作为一种补救措施,我将继续使用更简单的凸包算法,然后在其倒置残差上重新运行它。它会得到一个正确的鼻子,然后凹面将变成残差中的凸面。或者您可以使用 openCV 的凸性缺陷函数而不是使用 convexHull。

B.另一种解决方法是减少蛇曲率参数,使其在鼻子周围急剧弯曲。由于您几乎没有噪音,而且您实际上可以稍微清理一下,我认为执行一些约束而不是进行“更软”的权衡是没有问题的。也许头部轮廓先验模型也可以在这里提供帮助。

下面我尝试使用各种距离变换和距离参数的权重编写自己的蛇形算法。结论 - 参数比距离度量更重要,并且确实有一些影响(左图使用的参数比右图更小,因此更能削减鼻子)。与等高线的距离(红色)用灰色表示,蛇用绿色表示。

C.由于您的背景几乎是纯色的,因此请花一点时间来清理一些残余噪声(使用形态学运算或连接组件),并且只需 findContrours() 清理轮廓。我在下面实现了最后一个解决方案:第一张图像删除了噪声,第二张图像只是来自 openCV 的轮廓函数。

【讨论】:

【参考方案2】:

如果你想自己实现,我推荐 Jim Ivins 和 John Porrill 撰写的论文“你一直想知道的关于蛇的一切(但不敢问)”。

关于OpenCV的实现,我不是很了解,但是建议你:

降低beta,这样曲率可能会更强

检查图像能量。也许函数(方案)的最后一个参数是错误的。有两个可能的值:_CV_SNAKE_IMAGE 和 _CV_SNAKE_GRAD。如果我没记错的话,你将它设置为 0,我认为 0 表示 _CV_SNAKE_IMAGE。因此,该函数将假设输入图像是能量图像。同样,我不确定 OpenCV 如何实现此功能,但我认为当您使用 _CV_SNAKE_IMAGE 时,该功能假定输入图像是渐变模块图像。在您的情况下,它可以使蛇避开黑色区域(解释为低梯度模块)并寻找明亮区域。因此,请尝试使用 _CV_SNAKE_GRAD 作为最后一个参数。

希望对你有帮助。祝你好运!

【讨论】:

我认为蛇的预处理阶段将输入转换为表示梯度场的距离变换图像,而不是强度梯度,在图像中的每个点都定义为到某个边界的距离。这使得蛇对到边界的距离敏感,而无需物理连接。【参考方案3】:

自从我研究活动轮廓的 OpenCV 实现以来已经有一段时间了,但如果我没记错的话,它使用了一种贪婪算法来最小化能量(Williams 等人?)。此外,外力有一些改进,通常是改善蛇收敛的边缘信息,例如梯度向量流场蛇(GVF)。 GVF 外力被建模为液体扩散过程,以允许 snaxels(蛇元素)在曲率较高和向内凹入的区域中流向图像边缘。当主动轮廓绘制时,我会推荐一种从粗到细的方法,也就是说,通常一个高级过程(人类或其他分割过程)将作为初始 snaxel 位置的种子,然后,蛇形变形过程将起作用作为描绘 ROI 边界的好方法。在医学图像分析等应用中,这种方法是可以接受的,甚至是可取的。另一个类似于水平集的好蛇算法是没有边缘模型的 Chan-Vese 活动轮廓,绝对值得一试,并且在 Matlab 中有几个它在互联网上流传的例子。

【讨论】:

【参考方案4】:

活动轮廓很糟糕 - 时期。看起来 max flow min cut 可以轻松解决这个图像分割问题。

我知道这是前一段时间有人问过的,但我对一般的活动轮廓感到愤怒。此页面是 Google 上的热门页面之一,我认为很多人会阅读这篇文章,希望有人可以通过 pdes 对轮廓演化做一些有用的事情。

事实是,主动轮廓需要大量的人工干预,并且只有在边缘强度不自然或对比度非常高的情况下才有效。

如果您的博士或博士后感兴趣 - 我恳求您寻找其他东西。我保证会带来令人震惊的结果。尽管那里似乎有很好的轮廓模型,但源代码从未提供过——例如水平集中的广义 gvf。

所有(二元)分割问题都可以分解为有向图 - 您未来的雇主和考官会感谢我。我敦促您不要在活动轮廓上浪费时间。

【讨论】:

嗨。感谢您的反馈意见。你似乎不喜欢 ACM,但你可能是对的,snake 可能不是最好的轮廓提取算法。我的问题已解决,所以我现在不需要更好的解决方案,但我会看看其他解决方案,就像你建议的那样。我不是博士,但总是对新算法感兴趣。

以上是关于蛇算法 - opencv 活动轮廓 - 效果不佳的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenCV 检测图像中的十字

OpenCV 图像轮廓

OpenCV轮廓检测,计算物体旋转角度

opencv实战——图像矫正算法深入探讨

youcans 的 OpenCV 例程200篇183.基于轮廓标记的分水岭算法

opencv实战——复杂背景下寻找物体轮廓(底帽)