opencv笔记--Active contours
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的更多相关文章
- OpenCV笔记大集锦(转载)
整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址: ...
- opencv笔记6:角点检测
time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...
- opencv笔记5:频域和空域的一点理解
time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决 ...
- opencv笔记4:模板运算和常见滤波操作
time:2015年10月04日 星期日 00时00分27秒 # opencv笔记4:模板运算和常见滤波操作 这一篇主要是学习模板运算,了解各种模板运算的运算过程和分类,理论方面主要参考<图像工 ...
- opencv笔记3:trackbar简单使用
time:2015年 10月 03日 星期六 13:54:17 CST # opencv笔记3:trackbar简单使用 当需要测试某变量的一系列取值取值会产生什么结果时,适合用trackbar.看起 ...
- opencv笔记2:图像ROI
time:2015年 10月 03日 星期六 12:03:45 CST # opencv笔记2:图像ROI ROI ROI意思是Region Of Interests,感兴趣区域,是一个图中的一个子区 ...
- opencv笔记1:opencv的基本模块,以及环境搭建
opencv笔记1:opencv的基本模块,以及环境搭建 安装系统 使用fedora22-workstation-x86_64 安装opencv sudo dnf install opencv-dev ...
- opencv笔记---contours
一 Contour Finding Contours使用 STL-style vector<> 表示,如 vector<cv::Point>, vector<cv::Po ...
- 查找并绘制轮廓[OpenCV 笔记XX]
好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...
随机推荐
- Python 元类实现ORM
ORM概念 ORM(Object Ralational Mapping,对象关系映射)用来把对象模型表示的对象映射到基于 SQL 的关系模型数据库结构中去.这样,我们在具体的操作实体对象的时候,就不 ...
- Jeesite富文本编辑框ckeditor显示错误
Jeesite富文本编辑框ckeditor显示错误 原文链接:https://www.toutiao.com/i6485135618190869005/ Jeesite中Control都会继承一个Ba ...
- Static 静态+this
(一):静态 1.Static修饰的都是静态的,都是类相关的,不需要new对象,直接采用类名.的方式访问 2.当一个属性是类级别的,所有对象的这个属性都是一样的,直接定义为静态 类=属性+方法 属性描 ...
- 【刷题-LeetCode】207. Course Schedule
Course Schedule There are a total of numCourses courses you have to take, labeled from 0 to numCours ...
- 146_LRU cache | LRU缓存设计
题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...
- gin源码解读1-net/http的大概流程
gin框架预览 router.Run()的源码: func (engine *Engine) Run(addr ...string) (err error) { defer func() { debu ...
- 使用 Dapr 缩短软件开发周期
Microsoft DevOps 文档里的文章(https://docs.microsoft.com/zh-cn/azure/devops/report/dashboards/cycle-time-a ...
- 日志模块详细介绍 hashlib模块 动态加盐
目录 一:hashlib模块 二:logging 一:hashlib模块 加密: 将明文数据通过一系列算法变成密文数据(目的就是为了数据的安全) 能够做文件一系列校验 python的hashlib提供 ...
- Spring中的单例模式
Spring中的单例模式 单例模式的介绍 1.1 简介 保证整个应用中某个实例有且只有一个 1.2作用 保证一个类仅有一个实例,并且提供一个访问它的全局访问点. 单例模式的优点和缺点 单例模式的优 ...
- Docker常用命令速查
docker pull ${CONTAINER NAME} #拉取镜像 docker images #查看本地所有镜像 docker ps #查看所有正在运行的容器,加-q返回id docker ps ...