This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker. Thank you for your support.
This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker.

Number Plate Recognition with OpenCV and EasyOCR

Feb. 28 2022 Yacine Rouizi
OpenCV Computer Vision Object Detection Optical Character Recognition
Number Plate Recognition with OpenCV and EasyOCR

In this tutorial, you will learn how to use OpenCV and the EasyOCR package to automatically perform license/number plate recognition (LPR/NPR).

EasyOCR is an open-source Python package that is used to perform Optical Character Recognition - OCR (extract text from images).

The package is very easy to use and at the time of this writing, it supports 80+ languages including Chinese, Arabic, French, English, Cyrillic, etc.

In license plate recognition, not only do we want to find the bounding boxes of the license plate (like we did in the previous tutorial), but we also want to extract the text from the detected license plate.

Install EasyOCR

To install the EasyOCR package we can simply use the pip command:

pip install easyocr

Please note that at the time of this writing OpenCV version (4.5.5.62) is not compatible with EasyOCR, so if you have it installed you'll need to downgrade to version 4.5.4.60 (I spent several hours to figure this out x)).

To downgrade, just run the following command:

pip install opencv-python==4.5.4.60

Or if you have installed opencv-contrib-python, you can simply downgrade using the command below:

pip install opencv-contrib-python==4.5.4.60

If you don't know which command you used to install OpenCV, then uninstall them all with pip uninstall and reinstall only one package; because if you have both packages installed in the same environment you may have unexpected consequences:

pip uninstall opencv-python
pip uninstall opencv-contrib-python

and reinstall it:

pip install opencv-python==4.5.4.60

Number Plate Recognition

Now, create a new Python file and write the following code:

from easyocr import Reader
import cv2

# load the image and resize it
image = cv2.imread('image1.jpg')
image = cv2.resize(image, (800, 600))

The first thing we need to do is to import the required packages.

Then we load our image and resize it.

Now we can preprocess our image:

# convert the input image to grayscale,
# blur it, and detect the edges 
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
blur = cv2.GaussianBlur(gray, (5,5), 0) 
edged = cv2.Canny(blur, 10, 200) 
cv2.imshow('Canny', edged)
cv2.waitKey(0)
cv2.destroyAllWindows()

We convert our image to grayscale, remove some noise by applying a Gaussian blur, and finally detect the edges using the Canny edge detector.

Below is our output image:

Edged image

Next, we need to find the contours on the image and extract the contour of the license plate:

# find the contours, sort them, and keep only the 5 largest ones
contours, _ = cv2.findContours(edged, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5]

# loop over the contours
for c in contours:
    # approximate each contour
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    # if the contour has 4 points, we can say
    # that we have found our license plate
    if len(approx) == 4:
        n_plate_cnt = approx
        break        

# get the bounding box of the contour and 
# extract the license plate from the image
(x, y, w, h) = cv2.boundingRect(n_plate_cnt)
license_plate = gray[y:y + h, x:x + w]

We used our edged image to find the contours and then sort them from biggest to smallest and keep the 5 largest ones.

We then go through the contours, approximate each one, and if we found a contour with four points we can say that we have found our license plate.

So next, we get the bounding box of the license plate's contour and we use Numpy slicing to extract the number plate from the image.

License plate

Now we are ready to perform Optical Character Recognition using the EasyOCR package:

# initialize the reader object
reader = Reader(['en'])
# detect the text from the license plate
detection = reader.readtext(license_plate)

if len(detection) == 0:
    # if the text couldn't be read, show a custom message
    text = "Impossible to read the text from the license plate"
    cv2.putText(image, text, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)
    cv2.imshow('Image', image)
    cv2.waitKey(0)
else:
    # draw the contour and write the detected text on the image
    cv2.drawContours(image, [n_plate_cnt], -1, (0, 255, 0), 3)
    text = f"{detection[0][1]} {detection[0][2] * 100:.2f}%"
    cv2.putText(image, text, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)
    # display the license plate and the output image
    cv2.imshow('license plate', license_plate)
    cv2.imshow('Image', image)
    cv2.waitKey(0)

We first initialize the Reader object and then use the readtext function passing it our license plate image.

This will return a list containing 3 elements: the first one is the bounding box of the text, the second element is the detect text, and the last one is the confidence for the detection.

In the case where the length of the returned list is equal to 0, this means that the function couldn't detect the text. So we display a custom message to the end user.

In case the length of the returned list is 0, this means that the function couldn't detect the text. So we display a custom message to the user.

Otherwise, we draw the contour of the license plate on the image along with the detected text and its probability.

Here is the final result:

Number plate recognition

As you can see, our program successfully recognized the license plate and the extracted text matches the one on the license plate.

But this is not always the case, as you can see in the image below:

Recognition not accurate

Here instead of detecting the text "4143 KZM", EasyOCR detects the text "41L3 KZM". This is one of the limitations of using only image processing techniques to detect number plates.

Or sometimes the program can't even detect the license plate:

Number plate not detected

This time we detected nothing. This is because the detection depends on the lighting, preprocessing of our image, and other factors. 

Of course, here we have built a toy example, but in a real project, it would be better to use deep learning to get better accuracy.

Summary

Hopefully, this has given you an idea of how to perform Optical Character Recognition using OpenCV and EasyOCR.

Although this tutorial shows you how to perform number plate recognition with OpenCV and EasyOCR, if you want to dive deeper into the topic and learn how to build an end-to-end Automatic Number Plate Recognition system using deep learning-based object detectors like YOLO, you might be interested in my ebook Mastering YOLO: Build an Automatic Number Plate Recognition System.

This comprehensive resource contains detailed explanations, practical examples, and step-by-step tutorials to help you master YOLO and build your own ANPR system. You can learn more about the ebook by visiting this page.

You can get the source code for this article by clicking this link.

Comments 2
Avatar Jonathan said
I'm happy. But I have problem with my computer it displayed an error message..

June 24, 2022, 3:52 p.m.

Avatar Yacine said
Thank you Jonathan for the feedback. Can you give more details about the error message you get?

June 25, 2022, 12:24 p.m.

Leave a comment

(Your email address will not be published)