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. PyCharm撤消/恢复

    PyCharm在撤消/重做的每个步骤之前移动插入符号,然后执行撤消/重做操作. 要撤消操作,请执行以下操作之一: 在主菜单上,选择Edit | Undo. 按Ctrl+Z. 要恢复操作,请执行以下操作 ...

  2. Linux上天之路(八)之用户和组

    主要内容. 用户创建,删除,修改 密码及密码文件 组创建,删除,修改 组密码及组配置文件 相关文件 Linux用户分类 超级管理员: UID为0 root用户拥有至高无上的命令,root用户不能改名 ...

  3. python驱动SAP完成数据导出(一)

    写在前面 我们使用Python驱动SAP时,经常会需要导出一些SAP报表数据至本地Excel文件.这个看似简单的问题背后,其实暗藏玄机,今天小爬就带各位同学好好捋捋. 以事务代码FB03(凭证清单)为 ...

  4. MASA Framework - EventBus设计

    目录 MASA Framework - 整体设计思路 MASA Framework - EventBus设计 概述 利用发布订阅模式来解耦不同架构层级,亦可用于解决隔离业务之间的交互 优点: 松耦合 ...

  5. java关于for循环的效率优化

    我们知道在实现一个功能的时候是可以使用不同的代码来实现的,那么相应的不同实现方法的性能肯定也是有差别的,所以我们在写一些对性能很敏感的模块的时候,对代码进行优化是很必要的,所以我们说一下for循环(w ...

  6. RBAC: K8s基于角色的权限控制

    文章目录 RBAC: K8s基于角色的权限控制 ServiceAccount.Role.RoleBinding Step 1:创建一个ServiceAccount,指定namespace Step 2 ...

  7. 集合框架-工具类-JDK5.0特性-函数可变参数

    1 package cn.itcast.p4.news.demo; 2 3 public class ParamterDemo { 4 5 public static void main(String ...

  8. 前端禁止使用F12、禁止右键

    打开控制台直接跳转页面 //debug调试时跳转页面 var element = new Image(); Object.defineProperty(element,'id',{get:functi ...

  9. Ventoy的UEFI模式安全启动操作说明

    Ventoy 1.0.07 版本开始支持 Secure Boot (安全启动),但是这个方案不是非常的完美,会导致在一些机器上不管BIOS里安全启动是否关闭都不能正常工作.因此从 1.0.09 版本开 ...

  10. 昔日埋雷不经意,今朝踩雷排查难:JetBrains系列IDE使用SFTP连接远程服务器报“EOF while reading packet”解决方法

    写在前面 这是一篇问题解决记录.希望能帮到遇到同样问题的读者. 强烈建议:请您先看解决步骤一节,如果您发现在下的问题和您的问题不一样,就可以及时离开本文,避免浪费时间. 正文 问题描述 在使用GoLa ...