Let’s create a detector.
I will train the classifier with training windows of size 50 x 42 :
where ratio is height divided by width.
The dimensions specify the smallest object size the classifier will be able to detect. Objects larger than that will be detected by the multiscale image pyramid approach.
Extracting rectangles to OpenCV format
As a best practice, I would recommend to create an executable,
extract, to extract training windows, positive ones as well as negative ones, from an annotated input of your choice :
./extract input.csv $WIDTH $(expr $WIDTH*$RATIO |bc)
The purpose of my
extract program is to create two directories that can be directly used by OpenCV cascade training algorithm :
pos -- info.dat -- img ---- xxx.png ---- yyyy.png neg -- info.dat -- img ---- zzzz.png ---- llll.png
neg/info.dat is a simple list of images
pos/info.dat contains rectangle informations
img/xxxx.png 1 x y w h img/yyyy.png 1 x y w h
pos/img/ images are full size, since the rectangle information is in the
info.dat file, whereas the
neg/img/ images are extracted.
In my case I provide many more negatives than positives to the classifier (4 times more).
I would avoid leaving OpenCV training algorithm create all the negative windows (
opencv_traincascade subsample negative image), or to do that, my
extract will create the background images at the final training size (100x20 in my example) so that it cannot subsample but only take the entire negative image as a negative.
Creating negatives from the backgrounds of the positives is much more “natural” and will give far better results, than using a wild list of background images taken from the Internet. That’s all that makes the interest of such an
I will add these negatives to negatives from this repo :
be careful: in some cases, OpenCV requires an absolute path for images in the negatives.txt (otherwise you could get an error
Train dataset for temp stage can not be filled. Branch training terminated.)
The CSV input file to the program is a list of input images with the class and coordinates of the rectangles where objects are located in the image,
The last two input parameters give the size to resize the negative windows after extraction.
OpenCV positives preprocessing
Let’s set the number of positives we take (NUMPOS) :
It is required to use an OpenCV program to convert the positive rectangles to a new required format :
cd MYPOSITIVES_FOLDER opencv_createsamples -info pos/info.dat -vec pos.vec -w $WIDTH -h $(expr $WIDTH*$RATIO/1 |bc) -num $NUMPOS
You could also augment the positive sample by rotating and distorting the images with
opencv_createsamples and merging them back into one vec with Naotoshi Seo’s
Train the classifier
Let’s the number of negatives we take per positives (FACTOR) :
and launch the training :
About the training parameters :
numPosparameter to be about 90% of the number of positive rectangles, since some positives that are too different from the the positive set can be rejected by the algorithm and if
numPosequals the number of positives, it will fail with the following message :
OpenCV Error: Bad argument (Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.
Increasing the number of positives will enable a better generalization of the model. Usually a few thousand is good.
numNeg: it is usually good to take two times more negatives than positives.
Increasing the number of negative will diminish the number of false positive detections.
numStageswill not improve anymore the model when overfitting occurs. In this case, you’ll need to add more positives and negatives to the training set.
Be careful also, the JS library
jsfeat only accept detectors in the old format (use
Use in nodeJS
Simply create a recognize.js program :
and call the detector
Well done !
A few posts : 1