import argparse
import cv2
import numpy as np
from keras.models import load_model
from tensorflow.keras.utils import img_to_array
import functools
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
ap.add_argument("-m", "--model", required=True, help="Path to the pre-trained model")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("License Plate", image)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blurred, 255,
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 45, 15)
_, labels = cv2.connectedComponents(thresh)
mask = np.zeros(thresh.shape, dtype="uint8")
total_pixels = image.shape[0] * image.shape[1]
lower = total_pixels // 70
upper = total_pixels // 20
for (i, label) in enumerate(np.unique(labels)):
if label == 0:
continue
labelMask = np.zeros(thresh.shape, dtype="uint8")
labelMask[labels == label] = 255
numPixels = cv2.countNonZero(labelMask)
if numPixels > lower and numPixels < upper:
mask = cv2.add(mask, labelMask)
cnts, _ = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
def compare(rect1, rect2):
if abs(rect1[1] - rect2[1]) > 10:
return rect1[1] - rect2[1]
else:
return rect1[0] - rect2[0]
boundingBoxes = sorted(boundingBoxes, key=functools.cmp_to_key(compare) )
TARGET_WIDTH = 128
TARGET_HEIGHT = 128
chars = [
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
]
model = load_model(args["model"], compile=False)
vehicle_plate = ""
for rect in boundingBoxes:
x,y,w,h = rect
crop = mask[y:y+h, x:x+w]
crop = cv2.bitwise_not(crop)
rows = crop.shape[0]
columns = crop.shape[1]
paddingY = (TARGET_HEIGHT - rows) // 2 if rows < TARGET_HEIGHT else int(0.17 * rows)
paddingX = (TARGET_WIDTH - columns) // 2 if columns < TARGET_WIDTH else int(0.45 * columns)
crop = cv2.copyMakeBorder(crop, paddingY, paddingY, paddingX, paddingX, cv2.BORDER_CONSTANT, None, 255)
crop = cv2.cvtColor(crop, cv2.COLOR_GRAY2RGB)
crop = cv2.resize(crop, (TARGET_WIDTH, TARGET_HEIGHT))
crop = crop.astype("float") / 255.0
crop = img_to_array(crop)
crop = np.expand_dims(crop, axis=0)
prob = model.predict(crop)[0]
idx = np.argsort(prob)[-1]
vehicle_plate += chars[idx]
cv2.rectangle(image, (x,y), (x+w,y+h), (0, 255, 0), 2)
cv2.putText(image, chars[idx], (x,y+15), 0, 0.8, (0, 0, 255), 2)
cv2.imshow('Final', image)
print("Vehicle plate: " + vehicle_plate)
cv2.waitKey(0)