6

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

问题是蛇不能很好地贴合鼻子、嘴巴和嘴巴下方(如下图所示)。

//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)点组成。

输入图像: 输入图像 - 阈值

输出蛇:

  • 蓝色:手动设置的点

  • 绿色:输出蛇

输出蛇

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

4

4 回答 4

11

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

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

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

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

在此处输入图像描述 剩下

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

于 2014-03-06T00:43:54.513 回答
5

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

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

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

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

我希望它可以帮助你。祝你好运!

于 2013-08-26T06:40:40.113 回答
0

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

于 2018-11-15T04:19:16.123 回答
-2

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

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

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

如果你是一个有兴趣的博士或博士后——我求你找点别的。我保证会带来令人震惊的结果。尽管那里似乎有很好的轮廓模型,但源代码从未提供过——例如水平集中的广义 gvf。

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

于 2015-05-11T22:35:18.010 回答