Camshift算法(1)
Camshift算法是Continuously Adaptive Mean Shift algorithm的简称。它是一个基于MeanSift的改进算法。它首次由Gary R.Bradski等人提出和应用在人脸的跟踪上,并取得了不错的效果。由于它是利用颜色的概率信息进行的跟踪,使得它的运行效率比较高。Camshift算法的过程由下面步骤组成:
(1)确定初始目标及其区域;
(2)计算出目标的色度(Hue)分量的直方图;
(3)利用直方图计算输入图像的反向投影图(后面做进一步的解释);
(4)利用MeanShift算法在反向投影图中迭代收索,直到其收敛或达到最大迭代次数。并保存零次矩;
(5)从第(4)步中获得收索窗口的中心位置和计算出新的窗口大小,以此为参数,进入到下一幀的目标跟踪。(即跳转到第(2)步);
几点说明:
1. 在输入图像进行反向投影图之前在HSV空间内做了一个阀值处理,用以滤掉一些噪声。
2. 反向投影图则是概率分布图,在反向投影图中某一像素点的值指的是这个点符合目标的概率分布的概率是多少,或者直接说其为目标图像像素点的像素点是多少。计算方法为:根据像素点的像素值查目标的直方图,其对应像素值的概率是多少就做为该点在反向投影图中的值。
3. Camshit算法到底是怎样自适应调整窗口的大小的。扩大:Canshift算法在计算窗口大小前,在MeanShift算出的窗口的四个方向上增大了TOLERANCE,即高和宽都增大了2TOLERANCE(此值自己调整设置),这才有可能使得窗口能够变大。缩小:在扩大的窗口内重新计算0阶矩,1阶矩和2阶矩,利用矩的值重新计算高和宽。因此Camshif算法相当于在MeanShift的结果上,再做了一个调整,从而使得跟踪的窗口大小能够随目标的大小变化。
优点:算法的效率比较高,如果能利用多少特征做出来的统计直方图,我估计实验效果会更好。
缺点:(1)只利用颜色统计做的跟踪,在背景有相似颜色时,会出现跟踪错误的情况。(2)不能做多目标跟踪。(3)由于它只在初始位置(而不是从每个像素点)开始迭代,所以有可能在初始位置错了后,收敛的位置还是原位置(即跟丢了后,可能会找不回来)。
问题:论文中有关于窗口大小调整,是根据直方图来迭代求解,不知是怎么回事?在代码中没看到实现。在此向大家请教!
下面是Camshift算法Demo的代码:
2 #pragma package <opencv>
3 #endif
4
5 #define CV_NO_BACKWARD_COMPATIBILITY
6
7 #ifndef _EiC
8 #include "cv.h"
9 #include "highgui.h"
10 #include <stdio.h>
11 #include <ctype.h>
12 #endif
13
14 IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;
15 CvHistogram *hist = 0;
16
17 int backproject_mode = 0;
18 int select_object = 0;
19 int track_object = 0;
20 int show_hist = 1;
21 CvPoint origin;
22 CvRect selection;
23 CvRect track_window;
24 CvBox2D track_box;
25 CvConnectedComp track_comp;
26 int hdims = 16;
27 float hranges_arr[] = {0,180};
28 float* hranges = hranges_arr;
29 int vmin = 10, vmax = 256, smin = 30;
30
31 void on_mouse( int event, int x, int y, int flags, void* param )
32 {
33 if( !image )
34 return;
35
36 if( image->origin )
37 y = image->height - y;
38
39 if( select_object )//表明还正在框选目标
40 {
41 selection.x = MIN(x,origin.x);
42 selection.y = MIN(y,origin.y);
43 selection.width = selection.x + CV_IABS(x - origin.x);
44 selection.height = selection.y + CV_IABS(y - origin.y);
45
46 //保证数据的有效性
47 selection.x = MAX( selection.x, 0 );
48 selection.y = MAX( selection.y, 0 );
49 selection.width = MIN( selection.width, image->width );
50 selection.height = MIN( selection.height, image->height );
51 selection.width -= selection.x;
52 selection.height -= selection.y;
53 }
54
55 switch( event )
56 {
57 case CV_EVENT_LBUTTONDOWN://框选目标
58 origin = cvPoint(x,y);
59 selection = cvRect(x,y,0,0);
60 select_object = 1;
61 break;
62 case CV_EVENT_LBUTTONUP://框选结束
63 select_object = 0;
64 if( selection.width > 0 && selection.height > 0 )
65 track_object = -1;
66 break;
67 }
68 }
69
70
71 CvScalar hsv2rgb( float hue )
72 {
73 int rgb[3], p, sector;
74 static const int sector_data[][3]=
75 {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
76 hue *= 0.033333333333333333333333333333333f;
77 sector = cvFloor(hue);
78 p = cvRound(255*(hue - sector));
79 p ^= sector & 1 ? 255 : 0;
80
81 rgb[sector_data[sector][0]] = 255;
82 rgb[sector_data[sector][1]] = 0;
83 rgb[sector_data[sector][2]] = p;
84
85 return cvScalar(rgb[2], rgb[1], rgb[0],0);
86 }
87
88 int main( int argc, char** argv )
89 {
90 CvCapture* capture = 0;
91
92 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
93 capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
94 else if( argc == 2 )
95 capture = cvCaptureFromAVI( argv[1] );
96
97 if( !capture )
98 {
99 fprintf(stderr,"Could not initialize capturing...\n");
100 return -1;
101 }
102
103 printf( "Hot keys: \n"
104 "\tESC - quit the program\n"
105 "\tc - stop the tracking\n"
106 "\tb - switch to/from backprojection view\n"
107 "\th - show/hide object histogram\n"
108 "To initialize tracking, select the object with mouse\n" );
109
110 cvNamedWindow( "Histogram", 1 );
111 cvNamedWindow( "CamShiftDemo", 1 );
112 cvSetMouseCallback( "CamShiftDemo", on_mouse, 0 );
113 cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
114 cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
115 cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );
116
117 for(;;)
118 {
119 IplImage* frame = 0;
120 int i, bin_w, c;
121
122 frame = cvQueryFrame( capture );
123 if( !frame )
124 break;
125
126 if( !image )
127 {
128 /* allocate all the buffers */
129 image = cvCreateImage( cvGetSize(frame), 8, 3 );
130 image->origin = frame->origin;
131 hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
132 hue = cvCreateImage( cvGetSize(frame), 8, 1 );
133 mask = cvCreateImage( cvGetSize(frame), 8, 1 );
134 backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
135 hist = cvCreateHist(1, &hdims, CV_HIST_ARRAY, &hranges, 1 );
136 histimg = cvCreateImage( cvSize(320,200), 8, 3 );
137 cvZero( histimg );
138 }
139
140 cvCopy( frame, image, 0 );
141 cvCvtColor( image, hsv, CV_BGR2HSV );
142
143 if( track_object )
144 {
145 int _vmin = vmin, _vmax = vmax;
146
147 cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
148 cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); //去除噪声,在此数据内的值,确定mask为1
149 cvSplit( hsv, hue, 0, 0, 0 ); //获得色调分量,并以此来做反向投影图
150
151 if( track_object < 0 )
152 {
153 float max_val = 0.f;
154 cvSetImageROI( hue, selection );
155 cvSetImageROI( mask, selection );
156 cvCalcHist( &hue, hist, 0, mask );//计算选中部分直方图
157 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
158 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
159 cvResetImageROI( hue );
160 cvResetImageROI( mask );
161 track_window = selection;
162 track_object = 1;
163
164 cvZero( histimg );
165 bin_w = histimg->width / hdims;
166 for( i = 0; i < hdims; i++ )
167 {
168 int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );//获取直方图的中每一项的高
169 CvScalar color = hsv2rgb(i*180.f/hdims);//直方图每一项的颜色是根据项数变化的
170 cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), //画直方图
171 cvPoint((i+1)*bin_w,histimg->height - val),
172 color, -1, 8, 0 );
173 }
174 }
175
176 cvCalcBackProject( &hue, backproject, hist ); //计算反向投影图backproject
177 cvAnd( backproject, mask, backproject, 0 ); //去除上下阀值外的点后的投影图
178 cvCamShift( backproject, track_window, //利用camshift搜索0-255的灰度图像
179 cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
180 &track_comp, &track_box );
181 track_window = track_comp.rect; //获得新的跟踪窗口
182
183 if( backproject_mode )
184 cvCvtColor( backproject, image, CV_GRAY2BGR );
185
186 if( !image->origin ) //如果为假,需要改变椭圆的角度
187 track_box.angle = -track_box.angle;
188 cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );//画跟踪椭圆
189 }
190
191 if( select_object && selection.width > 0 && selection.height > 0 )//在框住的时候反向显示
192 {
193 cvSetImageROI( image, selection );
194 cvXorS( image, cvScalarAll(255), image, 0 );
195 cvResetImageROI( image );
196 }
197
198 cvShowImage( "CamShiftDemo", image );
199 cvShowImage( "Histogram", histimg );
200
201 c = cvWaitKey(10);
202 if( (char) c == 27 )
203 break;
204 switch( (char) c )
205 {
206 case 'b':
207 backproject_mode ^= 1;
208 break;
209 case 'c':
210 track_object = 0;
211 cvZero( histimg );
212 break;
213 case 'h':
214 show_hist ^= 1;
215 if( !show_hist )
216 cvDestroyWindow( "Histogram" );
217 else
218 cvNamedWindow( "Histogram", 1 );
219 break;
220 default:
221 ;
222 }
223 }
224
225 cvReleaseCapture( &capture );
226 cvDestroyWindow("CamShiftDemo");
227
228 return 0;
229 }
230
231 #ifdef _EiC
232 main(1,"camshiftdemo.c");
233 #endif
234
转载于:https://www.cnblogs.com/seacode/archive/2010/09/28/1837639.html
Camshift算法(1)相关推荐
- 使用Python,OpenCV的Meanshift 和 Camshift 算法来查找和跟踪视频中的对象
使用Python,OpenCV的Meanshift 和 Camshift 算法来查找和跟踪视频中的对象 1. 效果图 2. 源码 2.1 MeanShift 2.2 Camshift(Continuo ...
- 目标跟踪:CamShift算法
1.前言 camshift利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的中心位置. ...
- OpenCV camshift算法的实例(附完整代码)
OpenCV camshift算法的实例 OpenCV camshift算法的实例 OpenCV camshift算法的实例 #include <iostream> #include &l ...
- OpenCV均值移位(Meanshift)和Camshift算法
OpenCV Meanshift和Camshift算法 Meanshift和Camshift算法 目标 均值漂移Meanshift OpenCV中的Meanshift Camshift OpenCV中 ...
- opencv python 多帧降噪算法_OpenCV-Python中用于视频跟踪的Meanshift和Camshift算法介绍...
学习目标 在本章中, 我们将学习用于跟踪视频中对象的Meanshift和Camshift算法. Meanshift Meanshift背后的直觉很简单,假设你有点的集合.(它可以是像素分布,例如直方图 ...
- 视频操作_02视频追踪:meanshift算法+Camshift算法
1.meanshift 1.1原理 meanshift算法的原理很简单.假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中. 如下图: 最开始的 ...
- OpenCV总结:目标跟踪之CamShift算法
CamShift算法全称是"Continuously Adaptive Mean-Shift"(连续的自适应MeanShift算法),是对MeanShift算法的改进算法,可以在跟 ...
- Camshift算法原理及其Opencv实现
Camshift原理 camshift利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的 ...
- pythonopencv算法_OpenCV3-Python基于Kalman和CAMShift算法应用
上一篇<OpenCV3-Python卡尔曼滤波器介绍>介绍了OpenCV中Kalman滤波器,本篇来介绍CAMShift算法结合Kalman滤波器来实现行人跟踪的方法. 应用程序遵循以下流 ...
- opencv实现camshift算法,以及代码详解
大家好哦,小编来讲程序啦,好好看哦,慢慢体会...一.说明实验介绍本次实验将使用利用 OpenCV 来实现对视频中感兴趣的动态物体的追踪. 首先我贴出我的水下追踪效果图吧 在图中我们可以看到鱼的追踪轨 ...
最新文章
- NTFRS事件ID:13568
- 和平精英清明节服务器维修时间,和平精英体验服关服维护要多久 和平精英体验服什么时候开放...
- SAP BTP Launchpad Service 打不开应用的权限问题
- .NET 6新特性试用 | 隐式using指令
- 北京市中 高英语听说计算机考,2021年北京高考首次英语听说机考时间确定,共五种题型...
- 社交大佬们的数据“大”在哪里?
- 原型即对象(以及认识这点的重要性)
- [C++]各编译器对C++11的支持比较
- iOS Coding项目片段记录(五)
- CentOS 7部署Kafka和Kafka集群
- SVProgressHUD的使用
- 中孚计算机保密玩游戏,中孚计算机保密检查
- iphone 控制 android手机,苹果手机如何远程控制安卓手机
- niceScroll
- 永久解决VSCode终端中文乱码问题
- 项目启动报错:Caused by: com.atomikos.recovery.LogException: Log already in use? tmlog in ./
- 网页视频进度条禁止拖动----解决
- 实验室管理系统[LIS],powerbuilder12.6开发,SQLSERVER2008数据库
- 动态内存分配实现冒泡排序
- Ubuntu 网络管理
热门文章
- 总结 图(有向图、无向图、权、度、存储结构、邻接矩阵、领接表 概念)
- Ubuntu 16.04 修改为几个国内更新源
- Eclipse 中最常用的快捷键大全
- 中文分词的python实现----HMM、FMM
- 2021-08-08 事务的提交,回滚
- 2021-06-14 七大参数,四种拒绝策略
- android欢迎界面的功能,Android 启动 ( 欢迎 ) 页面实现
- php5.3 本地调试,php5.3 xdebug 调试器安装配置
- python散点图数据怎么输入_python 散点图添加标签
- 区块链 以太坊 Solidity状态变量、局部变量与memory 、storage