1
#ifdef _CH_
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