1

Please help to get more knowledge on the my first-time haar training results. So I want to train Haar classifier to recognize simple pen, following Dileep Kumar’s article.

Using my cellphone I made 14 pen pictures. These pictures size is big about: 263x2814
Then I collected negative pictures, some of them downloaded from web, with size 640x480, and some of them made using my phone camera, with size: 1920x1080,5313x2388

Some of these negative images are really big. I have total 158 negative images.
After that create negative and positive images list and run the: createsamples command:

 perl createtrainsamples.pl positives.dat negatives.dat samples 250  "opencv_createsamples  -bgcolor 0 -bgthresh 0 -maxxangle 0.5 -maxyangle 0.5 maxzangle 0.5 -maxidev 40 -w 160 -h 20"

I am not sure here if 160 for with and 20 for height is okay or not?
And then after having samples.vec file I run the cascade training, using this command:

opencv_traincascade -data firstTry -vec samples.vec  -bg negatives.dat -numPos 250 -numNeg 99 -numStages 25 –featureType HAAR  -mode ALL -w 160  -h 20 -mem 2048

I used the same width and height, but not sure if this is something right. I took the width and height values from some reference script. After getting the cascade.xml file, I am running the detectMultiScale on my picture using the following argument:

faces = faceCascade.detectMultiScale(   image,   scaleFactor=1.4,  minNeighbors=3,   minSize=(30, 30) )

The detection does not work well. It is just detecting some parts of the pen and not the full pen.
Also when I have some photo where pen is put in environment, than pen is not being detected.

I think I need to resize all positive and negative images and make them same size, though not sure on this.
Could you please provide some opinions on what I have done wrong here and how I can improve my results.

You can find all my files here:

haykp
  • 435
  • 12
  • 29

1 Answers1

6

These are only based on own my experience:

  1. I think createsamples works well only when the width and height of your original image are equal. This is because when createsamples rotates your image, if the width and height are different the image gets cut (Go into your positive folder and look at the images it created. You'll see.) So my advice is... if this is your first time and you want to test createsamples (and don't know any other ways), choose a round or square object with equal width and height.
  2. Your number of negative and positive images are very very low... it should be in the thousands.
  3. As I said in #1 your -w -h should be equal (if using createsamples). And don't EVER use more than 25 for each of them (I recommend 20 20 or even 15 15). As I have experienced very very long training times without much gain in detection (actually once I experienced lower detection rate with maybe 5 or 6 times the training time).
  4. Resize all your negative images to be the same size before using createsamples (maybe 100x100). and resize your original image to be half or lower in width and height (maybe 50x50).
  5. There are some important variables you can change in traincascade command that make detection far better but they will make the training excruciatingly long:

    -minHitRate 0.999 -maxFalseAlarmRate 0.1 -maxWeakCount 1000
    

    Be warned: If you are going to use the above numbers you basically have to use LBP instead of HAAR. HAAR has better detecting but with LBP you can use better values because it takes way less time (although with these numbers and lots of images (+10000) it might still take days but use these with HAAR and I may be seeing you in a few months ). Here's how you make it LBP: -featureType LBP.
    The closer -minHitRate is to 1 the better. The lower -maxFalseAlarmRate is to 0 the better. And the higher -maxWeakCount the better.
    Also note that the better you set these up the less number of stages you need to go. You might have a 25-stage cascade that performs worse than a 6-stage cascade with a good set up. Also also note that your traincascade might seem like it is stuck on getting the negative images when you use these numbers (It's okay though).

  6. Also lighting is very important in detection. Use a room with good lighting to get better results.

On a weird note: why did you use faces = faceCascade.detectMultiScale when you want to detect pens. :D Don't make the computer more confused than it already is mate. :D

Arash Rohani
  • 984
  • 1
  • 7
  • 30
  • Thank you soo much!! You gave really valuable info. I will try now Just it is not clear for me: if I resize the positive images than can the trained algo detect not-resized images? I mean in real life my images are in big sizes like 1080x1024, so now if I resize my positive images and train the algo using it, than can that trained algo detect bigger size images?? Or each time when I want to detect the object, I have to resize my image? – haykp Aug 22 '17 at 06:50
  • If the resized image is not stretching the picture (messing up width and height ratio), then it can. – Arash Rohani Aug 22 '17 at 08:24
  • Roar I have resized the images, by keeping the ratio. Made them around 50x300, and used lots of images. After training total fail((( It does not recognise the objects at all,cannot understand why could you please please provide some hints, ideas? Or may be you have some training materials – haykp Aug 24 '17 at 01:58
  • Told you in #1. if your width and height are different createsamples just cuts off your images when it rotates them. It's not good for objects with different width and height. Unfortunately I don't know any other way of creating samples other than doing it manually (but who are we kidding). If you want to use createsamples just use a circle or square object with the same width and height. Or use other methods. – Arash Rohani Aug 24 '17 at 02:28
  • To be clear I'm not talking about -w -h. I'm talking about your actual image that you want to create samples with. (although when your image has the same width and height your -w -h will be the same too) – Arash Rohani Aug 24 '17 at 02:29
  • Yes I remember your hint #1, just my object is non-symetric(( But today I will split the pen into 2 parts with the same sizes, I mean I will devide the pen into 2 parts each with the same width x height Thank you soo much! And rankly I dont konw other methods excepts Haar in opencv – haykp Aug 24 '17 at 04:28
  • That is a hacky way of doing it. :D (I love hacky ways.) You can set your program to consider it recognized only when the two (half) objects are recognized and are close to each other. If you wanna just check if it works use that line i mentioned to make it LBP. If you saw no problems you can then do it again with HAAR (the default). – Arash Rohani Aug 24 '17 at 09:40