Active Contours 也称作 Snake,通过定义封闭区域曲线的能量函数,并使其最小化得到最终曲线。

Active Contours 被用作物体边界精确定位上,opencv 给出了一个实现,首先给出物体大致边界的外包围曲线作为初始曲线,然后通过迭代方式寻找邻域最小值,直到能量函数收敛或达到迭代次数停止。

由于能量函数不是严格的凸函数,故使用迭代方式可能无法收敛到正确位置。同时,该能量函数在平滑区域上迭代效果像气球一样不断缩小,直到遇到边缘区域才会产生反作用力,所以初始轮廓必须包围真实轮廓或者允许在真实轮廓内部且靠近真实轮廓。

首先给出能量函数的基本定义:

1)根据上图,在 xy 平面上定义曲线 C,使用参数 q 进行参数化

2)将曲线 C 分解为  与  函数,两个函数具有相同的定义域,其区域大致形状如上图;

3)根据上图,给出一些函数:

a. 

b. 

c. 

d. 

4)定义一个关于图像梯度的单调递减函数 ,在图像平滑区域  趋近无穷大,在边缘区域  趋近零;

5)给出边缘能量函数 ,解释如下:

a.  为不同积分分量的系数,该系数可以是一个固定值,也可以是一个与参数 q 相关的函数;

b. 第1项积分控制曲线的曲率,使曲线收缩为直线段;第2项积分控制曲线光滑度,避免曲线突变角点;前两项积分称作内部能量;

第3项积分使曲线项边缘方向靠近,该项积分称作外部能量;

6)给定初始曲线,在初始曲线的一个邻域内搜索最小能量值,并使用该最小能量值曲线作为新的搜索曲线,直到达到收敛条件为止;

opencv 中函数 CvSnakeImage 给出了实现,函数原型如下:

void cvSnakeImage( const IplImage* src, CvPoint* points, int length,

    float *alpha, float *beta, float *gamma, int coeffUsage, CvSize win, CvTermCriteria criteria, int calc_gradient CV_DEFAULT(1) );

    参数 :src 为原图像,

points 为Active Contours 的初始控制点,length 为控制点个数,

                alpha, beta, gamma 为积分项对应的系数,可以是一个固定值或者关于参数 p 的函数,coeffUsage 表示参数类型(固定值或者参数 p 的函数),

win 表示迭代窗口尺寸,

criteria 表示停止条件,可以设置迭代次数与迭代精度,

calc_gradient  表示使用梯度还是使用灰度作为第3项积分输入;

以下给出实验代码及结果:

 1 void UsingCvSnakeImage()
2 {
3 // Object
4 cv::Mat obj = cv::Mat::zeros(256, 256, CV_8UC1);
5 for (int y = 128 - 40; y < 128 + 40; ++y)
6 {
7 uchar *data = obj.ptr<uchar>(y);
8 for (int x = 128 - 40; x < 128 + 40; ++x)
9 data[x] = 128;
10 }
11
12 cv::imwrite("snake_1_obj.bmp", obj);
13
14 // initial contours
15 cv::Mat contour = cv::Mat::zeros(256, 256, CV_8UC1);
16 for (int y = 0; y < contour.rows; ++y)
17 {
18 int dy = (y - 98) * (y - 98);
19 uchar *data = contour.ptr<uchar>(y);
20 for (int x = 0; x < contour.cols; ++x)
21 {
22 int dx = (x - 128) * (x - 128);
23 if (dx + dy < 70 * 70)
24 data[x] = 255;
25 }
26 }
27
28 vector<vector<cv::Point>> contours;
29 cv::findContours(contour, contours, CV_RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
30
31 cv::Mat obj_cpy;
32 obj.copyTo(obj_cpy);
33 contour.rowRange(0, contour.rows) = 0;
34 for (int i = 0; i < contours[0].size(); ++i)
35 {
36 cv::Point pt = contours[0][i];
37 contour.ptr<uchar>(pt.y)[pt.x] = 255;
38 obj_cpy.ptr<uchar>(pt.y)[pt.x] = 255;
39 }
40
41 cv::imwrite("snake_2_contour.bmp", obj_cpy);
42
43 // prepare parameters
44 IplImage *ipl_img = &obj.operator IplImage();
45 CvPoint *ipl_pts = new CvPoint[contours[0].size()];
46 for (int i = 0; i < contours[0].size(); ++i)
47 {
48 ipl_pts[i].x = contours[0][i].x;
49 ipl_pts[i].y = contours[0][i].y;
50 }
51
52 float alpha = .2;
53 float beta = .2;
54 float gamma = 1.;
55
56 CvSize ipl_sz;
57 ipl_sz.width = 5;
58 ipl_sz.height = 5;
59
60 CvTermCriteria ipl_criteria;
61 ipl_criteria.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
62 ipl_criteria.max_iter = 1000;
63 ipl_criteria.epsilon = .1;
64
65 cvSnakeImage(ipl_img, ipl_pts, contours[0].size(), &alpha, &beta, &gamma, CV_VALUE, ipl_sz, ipl_criteria, 1);
66
67 // final contours
68 for (int i = 0; i < contours[0].size(); ++i)
69 {
70 if (i == 0)
71 cv::line(obj, cv::Point(ipl_pts[i].x, ipl_pts[i].y),
72 cv::Point(ipl_pts[contours[0].size() - 1].x, ipl_pts[contours[0].size() - 1].y), cv::Scalar(255), 2);
73 else
74 cv::line(obj, cv::Point(ipl_pts[i - 1].x, ipl_pts[i - 1].y),
75 cv::Point(ipl_pts[i].x, ipl_pts[i].y), cv::Scalar(255), 2);
76 }
77
78 cv::imwrite("snake_3_contour.bmp", obj);
79
80 delete[]ipl_pts;
81 }

  

参考资料 Active Contours: A Brief Review  Serdar Kemal Balcı and Burak Acar

opencv笔记--Active contours的更多相关文章

  1. OpenCV笔记大集锦(转载)

    整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址: ...

  2. opencv笔记6:角点检测

    time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...

  3. opencv笔记5:频域和空域的一点理解

    time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决 ...

  4. opencv笔记4:模板运算和常见滤波操作

    time:2015年10月04日 星期日 00时00分27秒 # opencv笔记4:模板运算和常见滤波操作 这一篇主要是学习模板运算,了解各种模板运算的运算过程和分类,理论方面主要参考<图像工 ...

  5. opencv笔记3:trackbar简单使用

    time:2015年 10月 03日 星期六 13:54:17 CST # opencv笔记3:trackbar简单使用 当需要测试某变量的一系列取值取值会产生什么结果时,适合用trackbar.看起 ...

  6. opencv笔记2:图像ROI

    time:2015年 10月 03日 星期六 12:03:45 CST # opencv笔记2:图像ROI ROI ROI意思是Region Of Interests,感兴趣区域,是一个图中的一个子区 ...

  7. opencv笔记1:opencv的基本模块,以及环境搭建

    opencv笔记1:opencv的基本模块,以及环境搭建 安装系统 使用fedora22-workstation-x86_64 安装opencv sudo dnf install opencv-dev ...

  8. opencv笔记---contours

    一 Contour Finding Contours使用 STL-style vector<> 表示,如 vector<cv::Point>, vector<cv::Po ...

  9. 查找并绘制轮廓[OpenCV 笔记XX]

    好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...

随机推荐

  1. linux7,一台物理机上使用VM装多个虚拟机,始终只有一个虚拟机网络正常,其他虚拟机报错Error: Connection activation failed: No suitable device found for this connection.

    今天在VM新装了一个虚拟机,结果发现原来的虚拟机连不上了,重启网络服务后报错 Error: Connection activation failed: No suitable device found ...

  2. tomcat启动卡在了 At least one JAR was scanned for TLDs yet contained no TLDs 的根本原因与解决办法

    1.前言 有时候服务器开启时启动不了,卡在了 org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned fo ...

  3. 理解闭包--js面向对象编程

    什么是闭包? 先看一段代码: function a(){ var n = 0; function inc() { n++; console.log(n); } inc(); inc(); } a(); ...

  4. 如何使用Github搭建自己的博客

    1.前期准备 sudo apt-get install npm sudo npm install hexo -g 首先使用如下命令创建项目,name是你要创建的博客的名字: hexo init {na ...

  5. 在Rainbond上使用Locust进行压力测试

    Locust简介 Locust 是一种易于使用.可编写脚本且可扩展的性能测试工具.并且有一个用户友好的 Web 界面,可以实时显示测试进度.甚至可以在测试运行时更改负载.它也可以在没有 UI 的情况下 ...

  6. 【VictoriaMetrics】vm单机版和vm-storage的查询功能的对比

    1.vm-storage源码调用表 文件 行号 函数 说明 app/vmstorage/main.go 53 main 入口94行调用srv.RunVMSelect() app/vmstorage/t ...

  7. java有四种访问权限

    Java面向对象的封装性是通过对成员变量和方法进行访问控制实现的,访问控制分为4个等级:私有.默认.保护和公有,具体规则如下表:

  8. vue学习15-自定义组件model使用

    <!DOCTYPE html> <html lang='en'> <head> <meta charset='UTF-8'> <meta http ...

  9. TeXstudio在右边显示预览

    打开预览界面后: 点击查看(View) 选择最后一个:窗口/内嵌(Windowed/Embedded) 就可以了

  10. qt 简单登录界面(一)

    widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include<QLineEdit> class ...