-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcamshift_wrapper.c
152 lines (110 loc) · 3.69 KB
/
camshift_wrapper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//Developed By Yash Shah
//camshift_wrapper.c
#include "cv.h"
#include <stdio.h>
#include "camshift_wrapper.h"
// Parameters
int nHistBins = 30; // number of histogram bins
float rangesArr[] = {0,180}; // histogram range
int vmin = 65, vmax = 256, smin = 55; // limits for calculating hue
// File-level variables
IplImage * pHSVImg = 0; // the input image converted to HSV color mode
IplImage * pHueImg = 0; // the Hue channel of the HSV image
IplImage * pMask = 0; // this image is used for masking pixels
IplImage * pProbImg = 0; // the face probability estimates for each pixel
CvHistogram * pHist = 0; // histogram of hue in the original face image
CvRect prevFaceRect; // location of face in previous frame
CvBox2D faceBox; // current face-location estimate
int nFrames = 0;
// Declarations for internal functions
void updateHueImage(const IplImage * pImg);
//////////////////////////////////
// createTracker()
//
int createTracker(const IplImage * pImg)
{
// Allocate the main data structures ahead of time
float * pRanges = rangesArr;
pHSVImg = cvCreateImage( cvGetSize(pImg), 8, 3 );
pHueImg = cvCreateImage( cvGetSize(pImg), 8, 1 );
pMask = cvCreateImage( cvGetSize(pImg), 8, 1 );
pProbImg = cvCreateImage( cvGetSize(pImg), 8, 1 );
pHist = cvCreateHist( 1, &nHistBins, CV_HIST_ARRAY, &pRanges, 1 );
return 1;
}
//////////////////////////////////
// releaseTracker()
//
void releaseTracker()
{
// Release all tracker resources
cvReleaseImage( &pHSVImg );
cvReleaseImage( &pHueImg );
cvReleaseImage( &pMask );
cvReleaseImage( &pProbImg );
cvReleaseHist( &pHist );
}
//////////////////////////////////
// startTracking()
//
void startTracking(IplImage * pImg, CvRect * pFaceRect)
{
float maxVal = 0.f;
// Make sure internal data structures have been allocated
if( !pHist ) createTracker(pImg);
// Create a new hue image
updateHueImage(pImg);
// Create a histogram representation for the face
cvSetImageROI( pHueImg, *pFaceRect );
cvSetImageROI( pMask, *pFaceRect );
cvCalcHist( &pHueImg, pHist, 0, pMask );
cvGetMinMaxHistValue( pHist, 0, &maxVal, 0, 0 );
cvConvertScale( pHist->bins, pHist->bins, maxVal? 255.0/maxVal : 0, 0 );
cvResetImageROI( pHueImg );
cvResetImageROI( pMask );
// Store the previous face location
prevFaceRect = *pFaceRect;
}
//////////////////////////////////
// track()
//
CvBox2D track(IplImage * pImg)
{
CvConnectedComp components;
// Create a new hue image
updateHueImage(pImg);
// Create a probability image based on the face histogram
cvCalcBackProject( &pHueImg, pProbImg, pHist );
cvAnd( pProbImg, pMask, pProbImg, 0 );
// Use CamShift to find the center of the new face probability
cvCamShift( pProbImg, prevFaceRect,
cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
&components, &faceBox );
// Update face location and angle
prevFaceRect = components.rect;
faceBox.angle = -faceBox.angle;
return faceBox;
}
//////////////////////////////////
// updateHueImage()
//
void updateHueImage(const IplImage * pImg)
{
// Convert to HSV color model
cvCvtColor( pImg, pHSVImg, CV_BGR2HSV );
// Mask out-of-range values
cvInRangeS( pHSVImg, cvScalar(0, smin, MIN(vmin,vmax), 0),
cvScalar(180, 256, MAX(vmin,vmax) ,0), pMask );
// Extract the hue channel
cvSplit( pHSVImg, pHueImg, 0, 0, 0 );
}
//////////////////////////////////
// setVmin()
//
void setVmin(int _vmin)
{ vmin = _vmin; }
//////////////////////////////////
// setSmin()
//
void setSmin(int _smin)
{ smin = _smin; }