License Plate Recognition using OpenCV, YOLO and Keras

1. Plate detection

import numpy as np
from darkflow.net.build import TFNet
import cv2
options = {"model": "cfg/yolo-1c.cfg",
"load": "bin/yolo.weights",
"batch": 8,
"epoch": 100,
"gpu": 0.9,
"train": True,
"annotation": "./data/AnnotationsXML/007/",
"dataset": "./data/Images/007/"}
tfnet = TFNet(options)
tfnet.train()
tfnet.savepb()
Images from our dataset with annotation in LabelImg
options = {"pbLoad": "yolo-plate.pb", "metaLoad": "yolo-plate.meta", "gpu": 0.9}
yoloPlate = TFNet(options)
def firstCrop(img, predictions):
predictions.sort(key=lambda x: x.get('confidence'))
xtop = predictions[i].get('topleft').get('x')
ytop = predictions[i].get('topleft').get('y')
xbottom = predictions[i].get('bottomright').get('x')
ybottom = predictions[i].get('bottomright').get('y')
firstCrop = img[ytop:ybottom, xtop:xbottom]
cv2.rectangle(img,(xtop,ytop),(xbottom,ybottom),(0,255,0),3)
return firstCrop
def secondCrop(img):
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,0)
contours,_ = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in contours]
if(len(areas)!=0):
max_index = np.argmax(areas)
cnt=contours[max_index]
x,y,w,h = cv2.boundingRect(cnt)
bounds = cv2.boundingRect(cnt)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
secondCrop = img[y:y+h,x:x+w]
else:
secondCrop = img
return secondCrop
predictions = yoloPlate.return_predict(frame)
firstCropImg = firstCrop(frame, predictions)
secondCropImg = secondCrop(firstCropImg)
Example : Output of the plate detection

2. Character Segmentation

options = {"pbLoad": "yolo-character.pb", "metaLoad": "yolo-character.meta", "gpu":0.9}
yoloCharacter = TFNet(options)
def auto_canny(image, sigma=0.33):
# compute the median of the single channel pixel intensities
v = np.median(image)

# apply automatic Canny edge detection using the computed median
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edged = cv2.Canny(image, lower, upper)

# return the edged image
return edged
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh_inv = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,39,1)
edges = auto_canny(thresh_inv)
ctrs, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0])
img_area = img.shape[0]*img.shape[1]
for i, ctr in enumerate(sorted_ctrs):
x, y, w, h = cv2.boundingRect(ctr)
roi_area = w*h
roi_ratio = roi_area/img_area
if((roi_ratio >= 0.015) and (roi_ratio < 0.09)):
if ((h>1.2*w) and (3*w>=h)):
cv2.rectangle(img,(x,y),( x + w, y + h ),(90,0,255),2)

3. Character Recognition

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(height, width, channel)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(35, activation='softmax'))
model.summary()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=8)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(test_acc)
model.save("model_char_recognition.h5")
Dataset sample
def cnnCharRecognition(img):
dictionary = {0:'0', 1:'1', 2 :'2', 3:'3', 4:'4', 5:'5', 6:'6', 7:'7', 8:'8', 9:'9', 10:'A',
11:'B', 12:'C', 13:'D', 14:'E', 15:'F', 16:'G', 17:'H', 18:'I', 19:'J', 20:'K',
21:'L', 22:'M', 23:'N', 24:'P', 25:'Q', 26:'R', 27:'S', 28:'T', 29:'U',
30:'V', 31:'W', 32:'X', 33:'Y', 34:'Z'}
blackAndWhiteChar= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blackAndWhiteChar = cv2.resize(blackAndWhiteChar,(75,100))
image = blackAndWhiteChar.reshape((1, 100,75, 1))
image = image / 255.0
new_predictions = characterRecognition.predict(image)
char = np.argmax(new_predictions)
return dictionary[char]

4. Final Results

5. Axis of improvement

Useful links

--

--

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