OpenCV tutorial—train your custom cascade/classifier/detector

Image by Alex Knight from Pexels

OpenCV is an open source computer vision and machine learning software library. It allows, with little effort, to build a computer vision application like for example a home security system that detects intruders.

OpenCV has already trained classifiers/cascades that may be of low precision in some particular scenarios.

If you want to have a higher accuracy of your object detection model you’ve come to the right place!

This tutorial is a step-by-step instruction on how to train your own cascade for object detection. Let’s start!

Note: here is the official tutorial on training a custom cascade for advanced users that already have some background in CV and python

Steps

  1. Install OpenCV — 3.4.14 (download it from this link)

After installation, you will have below files:

2. Create a python project and install OpenCV in python (link to the library)

  • The easiest option is to install OpenCV from pip by running a below command:
pip install opencv-python
  • create folders in your python project for: data (for your trained classifier), neg (for image that does not contain objects of interest), pos (for images that contain objects of interest), src (for python modules) and val (for validation images). It should have structure like the example below:

3. Copy OpenCV executable files to your python project (location the same as on previous step)

The files should be located where you extracted OpenCV in the first step:

\opencv\build\x64\vc15\bin

4. Get data

  • if you want you can simply use a ready dataset of cars from this link that looks like:
example image for training
  • Or you can generate a data using a simple python script (check appendix 1)

I decided to generate my own dataset of geometric figures where OpenCV will be trained to detect triangles. It looks like this:

left: negative, right: positive
  • Put data to pos and neg folders

5. Prepare needed files for training

  • create info.dat file which should contain a path to positives images and location of an object in the format:
folder/image_name.jpg n x y width height where:
n — number of objects on the image
x — x coordinate of the object on the image
y — y coordinate of the object on the image
width — width of the object
height — height of the object

Note: all points are given in pixels

pos/img1.jpg 1 5 105 80 90  # one object on the image
pos/img2.jpg 2 5 105 80 90 105 5 80 90 # two objects on the image
...
pos/img1000.jpg 1 5 105 80 90

Note: coordinates should be given as on left-upper corner of the object where the origin (0,0) is the left-upper corner of the image.

  • create bg.txt file where you have a path and list of negative images like:
neg/img1.jpg
neg/img2.jpg
neg/img3.jpg

neg/img1000.jpg

Just before training your folder should look like below:

  • open a shell in your project folder (I used PowerShell in windows) and run opencv_createsamples. This will transform positive images into OpenCV consumable format.
.\opencv_createsamples -info info.dat -num 1000 -w 200 -h 200 -vec triangles.vecwhere parameters:
-info: the info.dat file you created in the previous step
-num 1000: how many positive objects you have
-w: width of the images (in pixels)
-h: height of the images (in pixels)
-vec: output file used for training

Note: if you work on other operating system you may not need “.\” at the beginning of the command

  • check if all objects are labelled correctly by:
.\opencv_createsamples -vec triangles.vec -w 200 -h 200

Note: this should pop up a window with your objects

  • finally you can start training of your cascade by running:
.\opencv_traincascade -data data -vec traingles.vec -bg bg.txt -numPos 1000 -numNeg 1000 -numStages 5 -w 200 -h 200 -featureType LBP

Note: -numStages is the number of iteration (the more, the longer model will spent on training). More details here.

Quick help if you encountered below issue:

NEG count : acceptanceRatio 0 : 0
Required leaf false alarm rate achieved. Branch training terminated.

possible solutions:

  • clear data folder in your project. I run a test on a very small dataset and OpenCV couldn’t train on a small training sample.
  • make sure you have plenty of different kind of images. OpenCV requires to have a wide distribution of images.
  • have a lot of images for training. 10 positive and 10 negative samples wouldn’t be enough :)

Time for testing our cascade

This is a simple python script just for testing the cascade on one image:

import cv2img = cv2.imread(r'path/to/validation/image')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_tracker = cv2.CascadeClassifier(r'path\to\data\cascade.xml')
objects = _tracker.detectMultiScale(gray_img)

for (x, y, w, h) in objects:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.putText(img, 'cascade', (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

cv2.imwrite(r'path\to\save\example_.jpg', img)

Hope it all works for you :)

Appendix 1: Python script for generating more images for training.

# below generates just a text that you can insert into bg.txt for x in range(1000):
print('neg/img'+str(x)+'.jpg')
# below is the random copying of images for negatives. You need to generate a sample of 40 images of 200x200 pixels on your own (in paint:) )
from shutil import copyfile
import random

for x in range(40, 200):
n = random.randint(1, 40)
copyfile(r'path\to\your\images' + str(n) + '.jpg',
r'path\to\save'+str(x)+'.jpg')

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store