print('Hello! Thanks for reading this project')
In this post, I am going to explain about license plate detection system.
Are you excited? Okay...Let's start.
To build this project, you'll need OpenCV and imutils. You can install it by using this command.
- Open your command prompt & type.
pip install opencv-python
pip install imutils
Why imutils?
A series of convenience functions to make basic image processing functions such as translation, rotation, resizing, skeletonization, displaying Matplotlib images, sorting contours, detecting edges, and much more easier with OpenCV and both Python 2.7 and Python 3.
Description source: https://pypi.org/project/imutils/
Now, we have installed packages needed for this project. let's start building.
1. Import packages
. Here, we are importing OpenCV and imutils.
import cv2
import imutils as im
2. Read Image file
from a specific folder. It is good to have in the source file directory.
# specify the path
input = 'car5.jpg'
image = cv2.imread(input)
3. Resizing
input image, because every image comes with a different shape. so, resizing makes all in one standard size.
newwidth = 500
resize_image = im.resize(image, width=newwidth)
4. Color conversion
Here, we are converting the input color(BGR) image into a grayscale image. Because the canny edge detector input image should be a single-channel 8-bit input image.
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
5. Image Smoothing
Filtering is perhaps the most fundamental operation of image processing. Gaussian and Median filters tend to blur edges. So I am going to apply a bilateral filter it can reduce unwanted noise very well while keeping edges fairly sharp. However, it is very slow compared to most filters.
Given parameters:
src: 1 or 3 channel image
d: Diameter of each pixel neighborhood that is used during filtering.
sigmaColor: Filter sigma in the color space.
sigmaSpace: Filter sigma in the coordinate space.
For simplicity, you can set the 2 sigma values to be the same. If they are small (< 10), the filter will not have much effect, whereas if they are large (> 150), they will have a very strong effect, making the image look "cartoonish".
For more information: https://docs.opencv.org/trunk/d4/d86/group__imgproc__filter.html#ga9d7064d478c95d60003cf839430737ed
d, sigmaColor, sigmaSpace = 10,15,15
filtered_img = cv2.bilateralFilter(gray, d, sigmaColor, sigmaSpace)
6. Edge Detection
Canny Edge Detection is a popular edge detection algorithm. First argument is our input image. Second and third arguments are our lower and upper threshold respectively.
Okay! What is Lower and Upper threshold?
Canny use two thresholds (upper and lower)
- If a pixel gradient is greater than upper threshold, then pixel is accepted as edge.
- If a pixel gradient is lower than lower value, then its rejected.
- If the pixel gradient is in between the two threshold, then it will be accepted only if it is connected to a pixel that is above the upper threshold.
# Find Edges in the grayscale image
lower, upper = 170, 200
edged = cv2.Canny(filtered_img, lower, upper)
7. Contours
Contours are defined as the line joining all the points along the boundary of an image that are having the same intensity. Contours are used in shape analysis and object detection. Contour works well with binary images. Read more about this here.
cnts,hir = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
It will return a Python list of all the contours in the image. Each contour is a numpy array of (x, y) coordinates of the object. Like this
[[[218 353]]
[[219 376]]
[[331 375]]
[[328 352]]]
It will return so many contour coordinates. so, we have to sort out the list based on its area. sorted function in python would be useful here.
Parameters:
- iterable - contour lists
- key function can be supplied to customize the sort order, we are going to sort using area.
- reverse flag can be set to true for descending order list.
# Return list with 10 biggest contour area
cnts=sorted(cnts, key = cv2.contourArea, reverse = True)[:10]
print("Number of Contours found : " + str(len(cnts))) # 10
8. Number plate Detection
Finally, we have contour with large area and its coordinates.
Loop over our contours to find the best possible contour of license plate.
Okay! Now we are going to break what's happening inside loop into pieces.
count = 0
for c in cnts:
perimeter = cv2.arcLength(c, True)
epsilon = 0.01 * perimeter
approx = cv2.approxPolyDP(c, epsilon , True)
if len(approx) == 4: # Select the contour with 4 corners
print(approx)
NumberPlateCnt = approx #This is our approx Number Plate Contour
break
First we have to find perimeter.It is also called arc length.
Perimeter is the distance around a two-dimensional shape.
First argument is contour points and True specify whether shape is closed contour.
perimeter = cv2.arcLength(c,True)
Next, Contour Approximation
Description source :OpenCV DocumentationTo understand this, suppose you are trying to find a square in an image, but due to some problems in the image, you didn’t get a perfect square, but a “bad shape” (As shown in first image below). Now you can use this function to approximate the shape. In this, second argument is called epsilon
, which is maximum distance from contour to approximated contour. It is an accuracy parameter. A wise selection of epsilon
is needed to get the correct output.
epsilon = 0.01 * perimeter
approx = cv2.approxPolyDP(c, epsilon , True)
Finally, select the contour with 4 corners.
if len(approx) == 4: # Select the contour with 4 corners
print(approx)
NumberPlateCnt = approx #This is our approx Number Plate Contour
break
9. Draw Contours
# Draw all contours
# -1 signifies drawing all contours
cv2.drawContours(image, [NumberPlateCnt], -1, (255,0,0), 2)
Most of the readers don’t make it to the end of the blog but you did, because you are special who just don’t just give up reading.
I’m hoping that I’ve taught you something. If you’ve found this post useful then do like. See you in another post.
Comments