Goal of the project is to recognize license plates on images without using deep learning methods. Project was prepared for course "Vision systems". Final accuracy on test set was around 80-85%.
The project was written for Python 3.11. Requirements are listed in requirements.txt
file. To install them run:
pip install -r requirements.txt
The training set containing 26 images of license plates was shared by the course lecturer. There were some rules for the data:
- all license plates were from Poland,
- all license plates were white (no EV or temporary plates),
- license plates were rotated by maximum 45 degrees,
- license plates width was at least 1/3 of the image width.
The project is divided into several files:
- main script
- image processing script
- pictures of separate letters
- script to calculate the result
- script to create and train KNN and Random Forest Classifiers
Before first run you need to train the classifiers. To do this, run the script knn_model_training.py
in the pictures
directory. It will create and save the models in the same directory.
Once you have the model trained, to run the project you need a training set of images in .jpg
format. Copy path to the directory with images and path where do you want to save the results and run it in the terminal:
python main.py /path/to/training_dataset /path/to/results/results.json
Image processing inside the utils.py script can be divided into the following steps:
- Resize the image to 1920x1080 and create a greyscale and hsv version of it.
- Create a mask for blue color and apply it to the hsv image. After doing so find contours and apply some rules (like for example height to width ratio) to find the rectangle that is always on the left side of the license plate.
- Filter the greyscale image with bilateral filter and use Canny detector to find edges. Dilate the edges and find contours. Create a bounding rectangle for each contour and check it's position comparing to the blue rectangle and remove contours with small area. After that use convexHull to get the contour as polygon.
- Sort hulls by the area and choose the smallest one. After that approximate the polygon with 4 points (there is a function that is increasing the difference between the points and the original polygon to finally find only 4 points).
- Use the 4 points to warp the image. Now the license plate is straight.
- Take the v channel of hsv image of the license plate and filter it, use Canny detenctor and find contours.
- Iterate through the found contours and remove all that are too wide or not high enough. After that create a bounding rectangle for each contour. Scale the rectangle to be height of 90 pixels and add padding with black pixels to both sides so the width is 66 pixels. Add the new image to a dictionary with the x coordinate being a key.
- Remove images that are inside another one (happened with the inside and outside of 0).
- Iterate through the dictionary (sorted by x coordinate) and predict the letter with the KNN and Random Forest classifiers. Save the predictions to the list.
- If length of the list is longer than 8, remove the elements with indices >=8. Check if the first or second element is a number, if so than change it to a letter that has similar shape.
- Save the results to the json file.
Because the training set wasn't big, the classifiers were trained on pictures that were randomly deformed using the elasticdeform
library. In addition there was a function to squeeze the pictures to add even more differences. By doing so, from one picture there were 50 new images that were used for training and 10 new images for validation. The accuracy on validation set for both KNN and Random Forest classifiers was around 99%.