-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain_objectTracker.cpp
More file actions
308 lines (264 loc) · 11.6 KB
/
main_objectTracker.cpp
File metadata and controls
308 lines (264 loc) · 11.6 KB
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#include <opencv2/opencv.hpp>
#include <opencv2/opencv_lib.hpp>
#include <iostream>
#include "ObjectTracker.h"
#include "predictor.h"
using namespace std;
CvPoint VertexOne,VertexThree;//長方形的左上點和右下點
enum state{
BOTTOM,
BOTTOM_TO_TOP,
TOP,
TOP_TO_BOTTOM
};
void onMouse(int event,int x,int y,int flag,void* param){
if(event==CV_EVENT_LBUTTONDOWN||event==CV_EVENT_RBUTTONDOWN){//得到左上角座標
VertexOne=cvPoint(x,y);
cout <<"set point one at " << x << " " << y << endl;
}
if(event==CV_EVENT_LBUTTONUP||event==CV_EVENT_RBUTTONUP){//得到右下角座標
VertexThree=cvPoint(x,y);
cout <<"set point three at " << x << " " << y << endl;
}
}
using namespace cv;
using namespace std;
int main()
{
VideoCapture cap("aus2.avi");
//VideoCapture cap("australia.avi");
if ( !cap.isOpened() ) // if not success, exit program
{
cout << "Cannot open the video file" << endl;
getchar();
return -1;
}
cap.set(CV_CAP_PROP_POS_MSEC, 3700); //start the video at 300ms
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
cout << "Frame per seconds : " << fps << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
//namedWindow("MyVideo2",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
/*get initial pos by clicking mouse*/
VertexOne=cvPoint(0,0);
VertexThree=cvPoint(0,0);
cvSetMouseCallback("MyVideo",onMouse);//設定滑鼠callback函式
/*background substractor*/
Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
Ptr< BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
pMOG2 = new BackgroundSubtractorMOG2(100,625);
Mat firstFrame;
if(!cap.read(firstFrame))
{
cout << "Cannot read the frame from video file" << endl;
return 0;
}
pMOG2->operator()(firstFrame, fgMaskMOG2,0.5);
cap.read(firstFrame);
pMOG2->operator()(firstFrame, fgMaskMOG2,0.5);
Mat cropTarget = fgMaskMOG2;
CObjectTracker *m_pObjectTracker = new CObjectTracker(firstFrame.cols,firstFrame.rows,IMAGE_TYPE(0));
/*get first object*/
imshow("MyVideo", firstFrame); //show the frame in "MyVideo" window
waitKey(0);
cout << "object1 detected" << endl;
int iCenterX = (VertexThree.x+VertexOne.x)/2;
int iCentery = (VertexThree.y+VertexOne.y)/2;
int iWidth1 = VertexThree.x-VertexOne.x;
int iHeight1 = VertexThree.y-VertexOne.y;
m_pObjectTracker->ObjectTrackerInitObjectParameters(iCenterX,iCentery,iWidth1,iHeight1);
rectangle(firstFrame,VertexOne,VertexThree,cv::Scalar( 0, 0, 255 ));
imshow("MyVideo", firstFrame);
/*get second object*/
waitKey(0);
cout << "object2 detected" << endl;
iCenterX = (VertexThree.x+VertexOne.x)/2;
iCentery = (VertexThree.y+VertexOne.y)/2;
int iWidth2 = VertexThree.x-VertexOne.x;
int iHeight2 = VertexThree.y-VertexOne.y;
m_pObjectTracker->ObjectTrackerInitObjectParameters(iCenterX,iCentery,iWidth2,iHeight2);
rectangle(firstFrame,VertexOne,VertexThree,cv::Scalar( 0, 255, 0 ));
imshow("MyVideo", firstFrame);
waitKey(500);
/*get ball*/
waitKey(0);
cout << "ball detected" << endl;
iCenterX = (VertexThree.x+VertexOne.x)/2;
iCentery = (VertexThree.y+VertexOne.y)/2;
int iWidth = VertexThree.x-VertexOne.x;
int iHeight = VertexThree.y-VertexOne.y;
rectangle(firstFrame,VertexOne,VertexThree,cv::Scalar( 255, 0, 0 ));
imshow("MyVideo", firstFrame);
waitKey(500);
Point prevBall = VertexOne;
Point prevVec = Point(0,0);
Rect myROI(VertexOne.x, VertexOne.y, VertexThree.x - VertexOne.x, VertexThree.y - VertexOne.y);
Mat croppedImage = cropTarget(myROI);
waitKey(0);
cout << "field detected" << endl;
rectangle(firstFrame,VertexOne,VertexThree,cv::Scalar( 255, 255, 255 ));
imshow("MyVideo", firstFrame);
waitKey(500);
Rect field(VertexOne.x, VertexOne.y, VertexThree.x - VertexOne.x, VertexThree.y - VertexOne.y);
m_pObjectTracker->ObjeckTrackerHandlerByUser(firstFrame.data);
state ball_state = BOTTOM;
Point lastOpponentPos,lastBallPos,lastPlayerPos;
predictor playerPredictor;
/*saving video frames*/
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
cout << "Frame Size = " << dWidth << "x" << dHeight << endl;
Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));
VideoWriter oVideoWriter("D:/MyVideo.avi", CV_FOURCC('P','I','M','1'), fps, frameSize, true); //initialize the VideoWriter object
if ( !oVideoWriter.isOpened() ) //if not initialize the VideoWriter successfully, exit the program
{
cout << "ERROR: Failed to write the video" << endl;
return -1;
}
while(1)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
pMOG2->operator()(frame, fgMaskMOG2, 0.5);
m_pObjectTracker->ObjeckTrackerHandlerByUser(frame.data);
// double dUserSize = 2;
// int iUser1X = m_pObjectTracker->getTrackerCenter(0).x - iWidth1*dUserSize/2;
// int iUser1Y = m_pObjectTracker->getTrackerCenter(0).y - iHeight1*dUserSize/2 ;
// int iUser2X = m_pObjectTracker->getTrackerCenter(1).x - iWidth2*dUserSize/2;
// int iUser2Y = m_pObjectTracker->getTrackerCenter(1).y - iHeight2*dUserSize/2;
//
// Mat user1 = fgMaskMOG2(Rect(iUser1X,iUser1Y,iWidth1*dUserSize,iHeight1*dUserSize));
// user1.setTo(0);
// Mat user2 = fgMaskMOG2(Rect(iUser2X,iUser2Y,iWidth2*dUserSize,iHeight2*dUserSize));
// user2.setTo(0);
Mat result;
matchTemplate(fgMaskMOG2, croppedImage, result, CV_TM_SQDIFF);
double min_val;
double max_val;
Point min_loc;
Point max_loc;
Mat roiResult = result(field);
minMaxLoc(roiResult, &min_val, &max_val, &min_loc, &max_loc);
max_loc.x += field.x;
max_loc.y += field.y;
if(max_val < 5000){
max_loc = prevBall;
}
prevBall = max_loc;
//imshow("result", result);
imshow("target", fgMaskMOG2);
int threshold = 5;
switch(ball_state){
case BOTTOM:
if(abs(max_loc.y-(field.y+field.height)) > threshold){
ball_state = BOTTOM_TO_TOP;
}
break;
case BOTTOM_TO_TOP:
rectangle(frame, max_loc, Point(max_loc.x + iWidth, max_loc.y + iHeight), 255);
if(abs(max_loc.y-field.y) < threshold){
ball_state = TOP;
// calculate angle
double angle;
if(max_loc.x == lastBallPos.x) angle = 3.14159265/2.0;
else angle = (double)atan((float)(abs(lastBallPos.y - max_loc.y))/abs(max_loc.x-lastBallPos.x));
cerr << "Current Info:\n";
cerr << "Last position: " << lastBallPos.x << "\t" << lastBallPos.y << endl;
cerr << "Current position: " << max_loc.x << "\t" << max_loc.y << endl;
angle = angle*180/3.14159265;
if(max_loc.x > lastBallPos.x) angle = 180 - angle;
cerr << angle << endl;
//cin.get();
// feed info
objectInfo player(lastPlayerPos.x , lastPlayerPos.y);
objectInfo opponent(lastOpponentPos.x , lastOpponentPos.y);
objectInfo ball(max_loc.x , max_loc.y);
playerPredictor.feedInformation(ball,opponent,player,angle);
// playerPredictor.showLearningStatus();
// cin.get();
}
break;
case TOP:
if(abs(max_loc.y - field.y)>threshold){
ball_state = TOP_TO_BOTTOM;
}
break;
case TOP_TO_BOTTOM:
rectangle(frame, max_loc, Point(max_loc.x + iWidth, max_loc.y + iHeight), 255);
if(abs(max_loc.y - (field.y+field.height)) < threshold){
ball_state = BOTTOM;
// record opponent, ball, player position
lastPlayerPos = m_pObjectTracker->getTrackerCenter(0);
lastOpponentPos = m_pObjectTracker->getTrackerCenter(1);
lastBallPos = max_loc;
// predict
objectInfo player(lastPlayerPos.x , lastPlayerPos.y);
objectInfo opponent(lastOpponentPos.x , lastOpponentPos.y);
objectInfo ball(max_loc.x , max_loc.y);
double prob;
int angle;
// draw predicted lines
playerPredictor.predictNthBestDirections(ball,opponent,player,0,prob,angle);
cerr << "Predict angle: " << angle << " prob: " << prob << endl;
int scalar = 100;
Point p1 = Point(lastPlayerPos.x - scalar*prob*cos(angle*3.14/180),lastPlayerPos.y - scalar*prob*sin(angle*3.14/180));
line(frame, lastPlayerPos, p1, cv::Scalar( 255, 0, 0 ),5);
//
// playerPredictor.predictNthBestDirections(ball,opponent,player,1,prob,angle);
// //cerr << "Predict angle: " << angle << " prob: " << prob << endl;
//
// Point p2 = Point(lastPlayerPos.x - scalar*prob*cos(angle*3.14/180),lastPlayerPos.y - scalar*prob*sin(angle*3.14/180));
// line(frame, lastPlayerPos, p2, cv::Scalar( 0, 255, 0 ),4);
//
// playerPredictor.predictNthBestDirections(ball,opponent,player,0,prob,angle);
// //cerr << "Predict angle: " << angle << " prob: " << prob << endl;
//
// Point p3 = Point(lastPlayerPos.x - scalar*prob*cos(angle*3.14/180),lastPlayerPos.y - scalar*prob*sin(angle*3.14/180));
// line(frame, lastPlayerPos, p3, cv::Scalar( 0, 0, 255 ),3);
int stop_frame_count = 50;
while(stop_frame_count--)
{
oVideoWriter.write(frame);
}
//waitKey(0);
}
break;
default:
break;
}
/*isAtBottom = (max_loc.y == field.y+field.height);
if(isAtBottom){
// record opponent, ball, player position
lastPlayerPos = m_pObjectTracker->getTrackerCenter(0);
lastOpponentPos = m_pObjectTracker->getTrackerCenter(1);
lastBallPos = max_loc;
// predict
}
isAtTop = (max_loc.y == field.y);
if(isAtTop){
// calculate angle
double angle = (double)atan((float)(abs(lastBallPos.y - max_loc.y))/(abs(lastBallPos.x - max_loc.x)));
cerr << angle << endl;
cin.get();
// feed info
}*/
//show the frame in "MyVideo" window
// tracker1Center_pre = tracker1Center_current;
// tracker1Center_current = m_pObjectTracker->getTrackerCenter(0);
// line(frame, tracker1Center_current, tracker1Center_pre, cv::Scalar( 0, 0, 255 ));
oVideoWriter.write(frame); //writer the frame into the file
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if(waitKey(5) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
//waitKey(0);
}
delete m_pObjectTracker, m_pObjectTracker = 0;
return 0;
}