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. solr -window 安装与启动

    1.下载 官网路径   https://solr.apache.org/downloads.html 为了稳定,我用 5.4.1 版本的 ,   这是下载地址 https://archive.apac ...

  2. Linux下Tomcat启动、停止、重新启动

    在Linux系统下,重启Tomcat使用命令操作的! 1.首先,进入Tomcat下的bin目录,${CATALINA_HOME}代表tomcat的安装路径 进入Tomcat安装目录: cd ${CAT ...

  3. winform控件拖动

    示例代码 using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Form ...

  4. 触发器中获取sql

    CREATE trigger 触发器名 on 表名 for update,delete as set nocount on create table #t(EvebtType varchar(60), ...

  5. Typecho 如何安装主题和插件

    Typecho的主题和插件都安装在Typecho的usr目录下,这个不是主机根目录的usr,是Typecho本身文件夹根目录下的usr. 里面有两个文件夹,plugins存放插件,themes存放主题 ...

  6. 字符串工具类ToStringBuilder常用方法介绍

    一.简介与引入   1.ToStringBuilder.HashCodeBuilder.EqualsBuilder.ToStringStyle.ReflectionToStringBuilder.Co ...

  7. sort排序出现安卓与苹果系统排序不一致问题

    sort排序出现安卓与苹果系统排序不一致问题

  8. gin框架中的路由拆分与注册

    基本的路由注册 下面最基础的gin路由注册方式,适用于路由条目比较少的简单项目或者项目demo. package main import ( "net/http" "gi ...

  9. AOP操作-AspectJ注解

    AOP操作(AspectJ注解) 1,创建类,在类里面定义方法 2,创建增强类(编写增强逻辑) (1)在增强类里面,创建方法,让不同方法代表不同通知类型 3,进行通知的配置 (1)在spring配置文 ...

  10. 如何通俗地理解docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...