We detect cars from videos recorded by dash cameras situated in cars. This type of camera is dynamic so we decided to train and use Haar Cascade Classifier. The classifier itself returns a lot of false positive results. So we improved classifier by removing false positive results using road detection.
Functions used: cvtColor, split, Rect, inRange, equalizeHist, detectMultiScale, rectangle, bitwise_and
1st part – training haar cascade classifier
Collect a set of positive samples and negative samples. Make a list file of both (positives.dat and negatives.dat). Then use opencv_createsamples function with parameters to make a single .vec file with all positive samples.
opencv_createsamples -info positives.dat -vec samples.vec -num 500 -w 20 -h 20
Now train a cascade classifier using HAAR features
opencv_traincascade -data classifier -featureType HAAR -vec samples.vec -bg negatives.dat -numPos 500 -numNeg 850 -numStages 15 -precalcValBufSize 1000 -precalcIdxBufSize 1000 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -mode ALL -w 20 -h 20
Output of this procedure is trained classifier – xml file.
2nd part – using classifier in C++ code to detect cars, improved by road detection
Open video file using VideoCapture. For every video frame do:
- Convert actual video frame to HSV color model
cvtColor(frame, frame_hsv, CV_BGR2HSV);
- Make sum of H S V in captured road sample. Calculate average Hue Saturation and Value of captured road sample.
int averageHue = sumHue / (rectangle_hsv_channels.rows*rectangle_hsv_channels.cols); int averageSat = sumSat / (rectangle_hsv_channels.rows*rectangle_hsv_channels.cols); int averageVal = sumVal / (rectangle_hsv_channels.rows*rectangle_hsv_channels.cols);
- Use inRange function to make a binary result – road is white colored, other is black colored
inRange(frame_hsv, cv::Scalar(averageHue - 180, averageSat - 15, averageVal - 20), cv::Scalar(averageHue + 180, averageSat + 15, averageVal + 20), final);
- Convert actual video frame to grayscale
cvtColor(frame, image_gray, CV_BGR2GRAY);
- Create an instance of CascadeClassifier
String car_cascade_file = "classifier.xml"; CascadeClassifier car_classifier; car_classifier.load(car_cascade_file);
- Detect cars in grayscale video frame using classifier
car_classifier.detectMultiScale(image_gray, cars, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(20, 20));
Result have a lot of false positives
- Make a black image with white squares at locations returned by cascade classifier. Make logical and between it and image with detected road
- Accept only squares which have at least 20% of pixels white.
- Cascade classifier trained only with 560 positive and 860 negative samples – detect cars only from near distance
- Road detection fails when some object (car, road line) comes to blue rectangle (supposed to be road sample)
- Dirt have a similar saturation as road – detected as road