-
Notifications
You must be signed in to change notification settings - Fork 134
/
car_detect.cpp
282 lines (187 loc) · 7.48 KB
/
car_detect.cpp
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
/*
* @file car_detect.cpp
* @author Abhishek Kumar Annamraju
This code provides faster car detection.
Also for the first time multiple cascade files are used to detect objects,with a benefit that no two objects
are detected twice.
Ever car detected in an image goes through a two stage testing.
The number of checkcascades are set to 1.It is desirable not to change this number.
USAGE: ./car_detect IMAGE.EXTENTION checkcas.xml cas1.xml cas2.xml cas3.xml cas4.xml ..........upto n number of main cascade xml files
ckeckcas.xml is the one trained with smallest size parameters and the rest are the main cascades
*/
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <iterator>
using namespace std;
using namespace cv;
void help()
{
cout << endl << "USAGE: ./car_detect IMAGE.EXTENTION checkcas.xml cas1.xml cas2.xml cas3.xml cas4.xml ..........upto n number of main cascade xml files" << endl;
cout << endl << "ckeckcas.xml is the one trained with smallest size parameters and the rest are the main cascades" << endl;
}
class cars //main class
{
public: //variables kept public but precaution taken all over the code
Mat image_input; //main input image
Mat image_main_result; //the final result
Mat storage; //introduced to stop detection of same car more than once
CascadeClassifier cascade; //the main cascade classifier
CascadeClassifier checkcascade; //a test classifier,car detected by both main and test is stated as car
int num;
void getimage(Mat src) //getting the input image
{
if(! src.data )
{
cout << "src not filled" << endl ;
}
else
{
image_input = src.clone();
storage = src.clone(); //initialising storage
image_main_result = src.clone(); //initialising result
cout << "got image" <<endl;
}
}
void cascade_load(string cascade_string) //loading the main cascade
{
cascade.load(cascade_string);
if( !cascade.load(cascade_string) )
{
cout << endl << "Could not load classifier cascade" << endl;
}
else
{
cout << "cascade : " << cascade_string << " loaded" << endl;
}
}
void checkcascade_load(string checkcascade_string) //loading the test/check cascade
{
checkcascade.load(checkcascade_string);
if( !checkcascade.load(checkcascade_string) )
{
cout << endl << "Could not load classifier checkcascade" << endl;
}
else
{
cout<< "checkcascade : " << checkcascade_string << " loaded" << endl;
}
}
void display_input() // function to display input
{
namedWindow("display_input");
imshow("display_input",image_input);
waitKey(0);
}
void display_output() //function to display output
{
if(!image_main_result.empty() )
{
namedWindow("display_output");
imshow("display_output",image_main_result);
waitKey(0);
}
}
void setnum()
{
num = 0;
}
void findcars() //main function
{
int i = 0;
Mat img = storage.clone();
Mat temp; //for region of interest.If a car is detected(after testing) by one classifier,then it will not be available for other one
if(img.empty() )
{
cout << endl << "detect not successful" << endl;
}
int cen_x;
int cen_y;
vector<Rect> cars;
const static Scalar colors[] = { CV_RGB(0,0,255),CV_RGB(0,255,0),CV_RGB(255,0,0),CV_RGB(255,255,0),CV_RGB(255,0,255),CV_RGB(0,255,255),CV_RGB(255,255,255),CV_RGB(128,0,0),CV_RGB(0,128,0),CV_RGB(0,0,128),CV_RGB(128,128,128),CV_RGB(0,0,0)};
Mat gray;
cvtColor( img, gray, CV_BGR2GRAY );
Mat resize_image(cvRound (img.rows), cvRound(img.cols), CV_8UC1 );
resize( gray, resize_image, resize_image.size(), 0, 0, INTER_LINEAR );
equalizeHist( resize_image, resize_image );
cascade.detectMultiScale( resize_image, cars,1.1,2,0,Size(10,10)); //detection using main classifier
for( vector<Rect>::const_iterator main = cars.begin(); main != cars.end(); main++, i++ )
{
Mat resize_image_reg_of_interest;
vector<Rect> nestedcars;
Point center;
Scalar color = colors[i%8];
//getting points for bouding a rectangle over the car detected by main
int x0 = cvRound(main->x);
int y0 = cvRound(main->y);
int x1 = cvRound((main->x + main->width-1));
int y1 = cvRound((main->y + main->height-1));
if( checkcascade.empty() )
continue;
resize_image_reg_of_interest = resize_image(*main);
checkcascade.detectMultiScale( resize_image_reg_of_interest, nestedcars,1.1,2,0,Size(30,30));
for( vector<Rect>::const_iterator sub = nestedcars.begin(); sub != nestedcars.end(); sub++ ) //testing the detected car by main using checkcascade
{
center.x = cvRound((main->x + sub->x + sub->width*0.5)); //getting center points for bouding a circle over the car detected by checkcascade
cen_x = center.x;
center.y = cvRound((main->y + sub->y + sub->height*0.5));
cen_y = center.y;
if(cen_x>(x0+15) && cen_x<(x1-15) && cen_y>(y0+15) && cen_y<(y1-15)) //if centre of bounding circle is inside the rectangle boundary over a threshold the the car is certified
{
rectangle( image_main_result, cvPoint(x0,y0),
cvPoint(x1,y1),
color, 3, 8, 0); //detecting boundary rectangle over the final result
//masking the detected car to detect second car if present
Rect region_of_interest = Rect(x0, y0, x1-x0, y1-y0);
temp = storage(region_of_interest);
temp = Scalar(255,255,255);
num = num+1; //num if number of cars detected
}
}
}
if(image_main_result.empty() )
{
cout << endl << "result storage not successful" << endl;
}
}
};
int main( int argc, const char** argv )
{
double t = 0;
t = (double)cvGetTickCount(); //starting timer
Mat image1 = imread(argv[1],1);
Mat image;
resize(image1,image,Size(300,150),0,0,INTER_LINEAR); //resizing image to get best experimental results
cars detectcars; //creating a object
string checkcas = argv[2];
detectcars.getimage(image); //get the image
detectcars.setnum(); //set number of cars detected as 0
detectcars.checkcascade_load(checkcas); //load the test cascade
//Applying various cascades for a finer search.
if(argc > 3)
{
for(int i = 3;i<argc;i++)
{
string cas = argv[i];
detectcars.cascade_load(cas);
detectcars.findcars();
}
}
else
{
help();
cout << endl << "Please provide atleast one main cascade xml file" << endl;
}
t = (double)cvGetTickCount() - t; //stopping the timer
if(detectcars.num!=0)
{
cout << endl << detectcars.num << " cars got detected in = " << t/((double)cvGetTickFrequency()*1000.) << " ms" << endl << endl;
}
else
{
cout << endl << "cars not found" << endl;
}
detectcars.display_output(); //displaying the final result
return 0;
}