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
- 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:
4. Get data
- if you want you can simply use a ready dataset of cars from this link that looks like:
- 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:
- 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:
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.
- 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)
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):
# 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
for x in range(40, 200):
n = random.randint(1, 40)
copyfile(r'path\to\your\images' + str(n) + '.jpg',