C++ Snake算法-opencv活动轮廓-工作不太好

C++ Snake算法-opencv活动轮廓-工作不太好,c++,algorithm,opencv,C++,Algorithm,Opencv,我正在做头部侧面的轮廓检测。由于图片是在白墙前拍摄的,我决定对经过阈值处理的图片运行一个(活动轮廓模型算法) 问题是蛇的鼻子、嘴巴和嘴下面的部位不太合适(如下图所示) 我试图更改alpha/beta/gamma参数或迭代次数,但没有找到比下面显示的输出更好的结果。我不明白为什么鼻子被割破了,脸也不适合嘴巴。我猜曲率有足够的点,但是仍然有一些线由几个(>2)点组成 输入图像: 输出蛇: 蓝色:手工设定的点数 绿色:输出蛇 任何帮助或想法都将不胜感激。 谢谢 如果你想自己实现,我推荐吉姆·伊

我正在做头部侧面的轮廓检测。由于图片是在白墙前拍摄的,我决定对经过阈值处理的图片运行一个(活动轮廓模型算法)

问题是蛇的鼻子、嘴巴和嘴下面的部位不太合适(如下图所示)

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

输入图像:

输出蛇:

  • 蓝色:手工设定的点数

  • 绿色:输出蛇

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

如果你想自己实现,我推荐吉姆·伊文斯(Jim Ivins)和约翰·波里尔(John Porrill)的论文《你一直想知道的关于蛇的一切(但不敢问)》

关于OpenCV实现,我不太了解,但我建议您:

  • 减小β,使曲率可能更强

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


我希望它能帮助你。祝你好运

典型的snake或活动轮廓算法在3种代价函数之间进行权衡时收敛:边缘强度/距离(数据项)、间距和平滑度(先验项)。立刻,你可能会注意到与你的“鼻子问题”有关的一个问题——鼻子有很高的弯曲度。您的蛇也有麻烦进入凹区域,因为这肯定会增加其曲率相比,凸壳

解决方案:
答:由于您的snake性能并不比凸包的性能好,作为补救措施之一,我将继续使用一个更简单的凸包算法,然后在其反向残差上重新运行它。它将得到一个正确的鼻子,然后在残差中凹面将变成凸面。或者您可以使用openCV的凸度缺陷函数,而不是使用

B.另一个修复方法是减少蛇形曲率参数,使其能够围绕鼻子急剧弯曲。因为你几乎没有噪音,而且你实际上可以把它清理干净一点,我认为实施一些约束而不是做出“更柔和”的权衡是没有问题的。也许先前的头部轮廓模型在这方面也有帮助

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

C.由于你的背景几乎是纯色的,所以花点时间清理一些残留的噪音(使用形态学操作或连接的组件)和干净的轮廓。我在下面实现了最后一个解决方案:第一个图像删除了噪声,第二个只是openCV中的一个轮廓函数。

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

我知道前一段时间有人问过这个问题,但我对活动轮廓总的来说很恼火。这是谷歌最热门的网页之一,我想很多人会读到这篇文章,希望有人能通过PDE对轮廓进化做些有用的事情

事实上,活动轮廓需要大量的人工干预,只有当你有不自然的边缘强度或非常高的对比度时,它才会起作用

如果你有兴趣读博士或博士后,我请求你找点别的。我保证会有令人震惊的结果。尽管表面上有很好的轮廓模型,但源代码从来都不可用——例如,在一个级别集内的通用gvf


所有(二进制)分段问题都可以分解成一个有向图——你未来的雇主和考官会感谢我的。我劝你不要在活动轮廓上浪费时间。

我已经有一段时间没有研究活动轮廓的OpenCV实现了,但是如果我没记错的话,那就是使用贪婪算法来最小化能量(Williams等人?)。此外,对外力(通常是边缘信息)进行了一些改进,以提高snake收敛性,例如梯度矢量流场snake(GVF)。GVF外力被建模为液体扩散过程,以允许蛇形素(蛇形元素)在曲率较高和向内凹陷的区域流向图像边缘。在活动轮廓绘制时,我建议采用从粗到精的方法,即通常高级别过程(人类或其他分割过程)将作为初始snaxel位置的种子,然后,蛇变形过程将作为描绘ROI边界的精细方法。在医学图像分析等应用中,这种方法是可以接受的,甚至是可取的。另一个很好的snake算法是一个类似于水平集的Chan-Vese活动轮廓无边模型,绝对值得一看,在M
//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);