I am attempting to train a cascade classifier to detect deer in images. The problem is that my classifier always returns exactly one positive hit, in the direct center of the input image. This is true for a test image, a training image from the positive set, and a training image from the negative set.
For my positive training set, I am using the deer image set from the CIFAR-10 dataset (http://www.cs.toronto.edu/~kriz/cifar.html). This gives me 5000 32x32 color images of deer in various poses. For the negative training set, I am using the images from the Labelme12-50k dataset (http://www.ais.uni-bonn.de/download/datasets.html), which gives me 39000 random images. I resized all of these images to 32x32 to make the sizes consistent with the positive training set.
I then created the positive vector with the following command:
./opencv_createsamples -info posFiles.txt -w 32 -h 32 -num 5000 -vec posVector.vec
The vector appeared to be created successfully. Then, I trained my cascade classifier using the command:
./opencv_traincascade -data /home/mitchell/ece492/Deerinator_Software/Deerinator_Software/trunk/Haar/data -vec posVector_5000.vec -bg negFiles.txt -numPos 4000 -numNeg 39000 -w 32 -h 32 -featureType LBP -numStages 18
The cascade classifier takes about 5 hours to train, and appears to have a negative rejection rate of 0.038 However, whenever I test the classifier on an image using the command:
./c-example-facedect --cascade=cascade.xml img.png
I always get the same result: a single hit in the center of the image. This happens for testing images, images from the positive training set, and images from the negative training set. I'm not sure what to do at this point - at this point, I'm just using the opencv sample executables. I'm not sure if the process is with my input training set or with my usage of the classifier. Anyone have any suggestions?
I think this fails because the picture samples are too small. I think they are just 32 by 32. How can that be used for positive samples? If I am wrong and the pictures are actually bigger, then teach me how to unpack them and I bet I can get this to run for you.
Related
As I explained in my previous post here, I am trying to generate some cascade.xml files to recognize euro coins to be used in my iOS app. Anyway, I am founding many difficulties in understanding how to generate a .vec file to give as input to opencv_traincascade. This because I heard many dissenting views: someone told me that vector file must include only positive images containing only the object to recognize; someone else instead (and also as read in my tutorials) said that vector file must include "samples" images, in other words random backgrounds to which the object to recognize has been added by opencv_createsamples. In oter words with:
opencv_createsamples -img positives/1.png -bg negatives.txt -info 1.txt -num 210 -maxxangle 0.0 -maxyangle 0.0 -maxzangle 0.9 -bgcolor 255 -bgthresh 8 -w 48 -h 48
which generated 12000 images.
Finally, I have created the .vec file with:
cat *.txt > positives.txt
opencv_createsamples -info positives.txt -bg negatives.txt -vec 2.vec -num 12600 -w 48 -h 48
So, I would like to ask you which the correct images to be contained in vector files from the following two:
Moreover, which is the final command to give to launch the training? This is the ones I have used up to now:
opencv_traincascade -data final -vec 2.vec -bg negatives.txt -numPos 12000 -numNeg 3000 -numStages 20 -featureType HAAR -precalcValBufSize 2048 -precalcIdxBufSize 2048 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -w 48 -h 48 -mode ALL
where the .vec files contains 12000 samples images (background + coin to recognize).
Should the .vec file contain only positive images (only coins), how shall I tell opencv_traincascade to train using the samples images?
I really need to know how to do things correctly because I have launched many training which then lead to no correct result and since they take many hours or days to execute, I can't waste time anymore.
Thank to all for your attention.
UPDATE
I managed to create a cascade.xml file with LBP. See what happens if I give one of the image used as training samples to a simple OpenCV program:
while with an image like the following:
it does not work at all. I really don't know where I am making the mistake.
UPDATE
Maybe firstly converting positive images to gray scale could help?
I've used the negative samples database of the INRIA training http://pascal.inrialpes.fr/data/human/
and this input (png with alpha transparency around the coin):
using this with this command:
opencv_createsamples -img pos_color.png -num 10 -bg neg.txt -info test.dat -maxxangle 0.6 -maxyangle 0 -maxzangle 0.3 -maxidev 100
-bgcolor 0 -bgthresh 0
produces output like this:
so background color obviously didn't work. Converting to grayscale in the beginning however gives me this input:
and same command produces output like this:
I know this is no answer to all of your questions, but maybe it still helps.
OpenCV cascades (HAAR, LBP) can excellently detect objects which have permanent features. As example all faces have nose, eyes and mouth at the same places. OpenCV cascades are trained to search common features in required class of object and ignore features which changes from object to object. The problem is conclude that the cascade uses rectangular shape of search window, but a coin has round shape. Therefore an image of the coin always will be have part of background.
So training images of the coin must includes all possible backgrounds in order to classifiers can ignore them (otherwise it will be detect coin only on the specific background).
So all training samples must have the same image ratio, size and position of the coin (square images with coin in center, diameter of coin = 0.8-0.9 image width), and different background!
I am sorry it seems a starting question but just wondering can i use rectangular dimensions for training opencv haar cascade. I tried with square samples and the resultant image was detected fine but when i tried with rectangular width and height as for license plate the aspect ratio is 2:1 between width and height so i am using the same aspect ratio while training but the resultant classifier is not detecting anything in the image.
nStages = 14
nPositive = 1780
minHitrate = 0.996
maxFalseAlarm = 0.2
nNegatives = 14000
width = 48
height = 24
Haar classifier type = BASIC
Boost type = gentle adaboost
The above are the parameters i have set for training of the classifier. Can anyone please confirm that can i use rectangular parameters for positive samples or not. Also please suggest some modifications to have the training done properly.
The size of negative images for training is around 240x161 annd 420x240
Thank you.
EDIT 1:
I am using the call as follows.
f_cascade.detectMultiScale( image, detected_objects, pyramidScale, 2, 0|CV_HAAR_SCALE_IMAGE);
The key parts of this are making sure your positive samples and training dimensions are the same. There is no reason why you won't be able to detect a rectangular object.
They key thing to remember is that traincascade is running whatever dimensions you specify over your images.
See here for some proof that rectangular objects should be detected just fine:
http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
Also I wrote a tutorial about object detection if anyone gets stuck on this stuff:
http://johnallen.github.io/opencv-object-detection-tutorial/
I've been doing some research and attempted to build a haarcascade for identifying gender.
I read this article, which describes how they did it, which i also tried to do : http://www.ijcce.org/papers/301-E043.pdf
I used a library of 228 male faces and 350 female faces.
Using the opencv createclassifier on my positives.txt file which contains a list of the male
faces. Using the .vec file create by the classifier I used haartraining with the following command:
opencv_traincascade -data classifier -vec positivies.vec -bg negatives.txt -numStages 20 -minHitRate 0.99 -maxFalseAlarmRate 0.5 -numPos 228 -numNeg 350 -w 640 -h 480 -mode ALL
After running this a few times I do not get a haar classifier.xml output file so I'm unsure whether I am doing everything correctly.
But my question is whether it is possible using male faces as positive samples and female as negative samples to train and use a haarcascade for classifying gender?
As already said in the comments with one cascade classifier you can only detect a male/female face or no face at all.
But you could just train two classifiers one for female and one for male and then run them both.
For the training I would recommend you to use more training examples.
I used this tutorial. It is for python, but can easily used for every other language, it might help you as well:
https://pythonprogramming.net/haar-cascade-object-detection-python-opencv-tutorial/
we have been stuck on a problem on haar cascade training for a week now. Actually we are following this tutorial http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html for creating cascade xml file.
But on the last command
opencv_traincascade -data classifier -vec samples.vec -bg negatives.txt
-numStages 20 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -numPos 45
-numNeg 45 -w 90 -h 100 -mode ALL -precalcValBufSize 1024
-precalcIdxBufSize 1024
we get an error:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std:: bad_alloc
Aborted (core dumped)
Specifications for the images are: 45 positive and 45 negative images(both with dimensions 90 X 100). I have made sure that samples.vec exists in the same folder and have also tried using 2048 for precalcValBufSize parameters. Please help us!
You've run out of memory. You have several options:
Use a 64-bit computer with more memory
Use smaller-size positive training images. 24x24 or 32x32 is typical. 64x64 is considered large.
Use LBP or HOG features instead of Haar. Haar features take orders of magnitude more memory than the others.
By the way, your negative images should not be the same size as your positive images. Negative images should be large scenes containing backgrounds typically associated with your objects of interest. opencv_traincascade automatically scans them for useful negative samples.
I've pasted all my code here in case you'd need that to understand my question: Plotting a graph on axes but getting no results while trying to classify image based on HoG features
My question is: given approximately 500 images (the Caltech "Cars 2001" dataset) with 48 HoG features each, what possible reasons can there be for the boosting to terminate early? What could cause a perfect fit, or a problem with the boosted sample weights, and how can such problems be solved? The specific algorithm I'm using is SAMME, a multiclass Adaboost classifier. I'm using Python 2.7 on Anaconda.
When I checked certain variables during the classification of my dataset, setting the n_estimators parameter to be 600, I found that:
discrete_test_errors: consisted of 1 item instead of being an array of 600 values
discrete_estimator_errors: was again one single value instead of of being an array of 600 values
real_test_errors is just one item again instead of 600
discrete_estimator_weights: array ([1.]) "
n_trees_discrete and n_trees_real: 1 instead of 600
Problem solved. My training array, labels, had no negatives, it consisted only of labels for one class. Of course the training would terminate immediately!