OpenCV4入门158:基于连续自适应均值迁移的对象移动分析

索引地址:系列索引

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// CAMSHIFT TRACKER

#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <ctype.h>

using namespace cv;
using namespace std;

Mat image;
Point originPoint;
Rect selectedRect;
bool selectRegion = false;
int trackingFlag = 0;

// Function to track the mouse events
void onMouse(int event, int x, int y, int, void*)
{
if(selectRegion)
{
selectedRect.x = MIN(x, originPoint.x);
selectedRect.y = MIN(y, originPoint.y);
selectedRect.width = std::abs(x - originPoint.x);
selectedRect.height = std::abs(y - originPoint.y);

selectedRect &= Rect(0, 0, image.cols, image.rows);
}

switch(event)
{
case CV_EVENT_LBUTTONDOWN:
originPoint = Point(x,y);
selectedRect = Rect(x,y,0,0);
selectRegion = true;
break;

case CV_EVENT_LBUTTONUP:
selectRegion = false;
if( selectedRect.width > 0 && selectedRect.height > 0 )
{
trackingFlag = -1;
}
break;
}
}

int main(int argc, char* argv[])
{
// Create the capture object
// 0 -> input arg that specifies it should take the input from the webcam
VideoCapture cap(0);

if(!cap.isOpened())
{
cerr << "Unable to open the webcam. Exiting!" << endl;
return -1;
}

char ch;
Rect trackingRect;

// range of values for the 'H' channel in HSV ('H' stands for Hue)
float hueRanges[] = {0,180};
const float* histRanges = hueRanges;

// min value for the 'S' channel in HSV ('S' stands for Saturation)
int minSaturation = 40;

// min and max values for the 'V' channel in HSV ('V' stands for Value)
int minValue = 20, maxValue = 245;

// size of the histogram bin
int histSize = 8;

string windowName = "CAMShift Tracker";
namedWindow(windowName, 0);
setMouseCallback(windowName, onMouse, 0);

Mat frame, hsvImage, hueImage, mask, hist, backproj;

// Image size scaling factor for the input frames from the webcam
float scalingFactor = 0.75;

// Iterate until the user presses the Esc key
while(true)
{
// Capture the current frame
cap >> frame;

// Check if 'frame' is empty
if(frame.empty())
break;

// Resize the frame
resize(frame, frame, Size(), scalingFactor, scalingFactor, INTER_AREA);

// Clone the input frame
frame.copyTo(image);

// Convert to HSV colorspace
cvtColor(image, hsvImage, COLOR_BGR2HSV);

if(trackingFlag)
{
// Check for all the values in 'hsvimage' that are within the specified range
// and put the result in 'mask'
inRange(hsvImage, Scalar(0, minSaturation, minValue), Scalar(180, 256, maxValue), mask);

// Mix the specified channels
int channels[] = {0, 0};
hueImage.create(hsvImage.size(), hsvImage.depth());
mixChannels(&hsvImage, 1, &hueImage, 1, channels, 1);

if(trackingFlag < 0)
{
// Create images based on selected regions of interest
Mat roi(hueImage, selectedRect), maskroi(mask, selectedRect);

// Compute the histogram and normalize it
calcHist(&roi, 1, 0, maskroi, hist, 1, &histSize, &histRanges);
normalize(hist, hist, 0, 255, CV_MINMAX);

trackingRect = selectedRect;
trackingFlag = 1;
}

// Compute the histogram back projection
calcBackProject(&hueImage, 1, 0, hist, backproj, &histRanges);
backproj &= mask;
RotatedRect rotatedTrackingRect = CamShift(backproj, trackingRect, TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1));

// Check if the area of trackingRect is too small
if(trackingRect.area() <= 1)
{
// Use an offset value to make sure the trackingRect has a minimum size
int cols = backproj.cols, rows = backproj.rows;
int offset = MIN(rows, cols) + 1;
trackingRect = Rect(trackingRect.x - offset, trackingRect.y - offset, trackingRect.x + offset, trackingRect.y + offset) & Rect(0, 0, cols, rows);
}

// Draw the ellipse on top of the image
ellipse(image, rotatedTrackingRect, Scalar(0,255,0), 3, CV_AA);
}

// Apply the 'negative' effect on the selected region of interest
if(selectRegion && selectedRect.width > 0 && selectedRect.height > 0)
{
Mat roi(image, selectedRect);
bitwise_not(roi, roi);
}

// Display the output image
imshow(windowName, image);

// Get the keyboard input and check if it's 'Esc'
// 27 -> ASCII value of 'Esc' key
ch = waitKey(30);
if (ch == 27) {
break;
}
}

return 0;
}