License plate extraction

I’m trying to recognize ONLY the plate on the following dataset

I couldn’t achieve good results.

The images are fixed in width and height.

enter image description here

import numpy as np
import cv2
import  imutils
import sys
import pandas as pd
import time

image = cv2.imread(r'C:\Users\xgame\Desktop\License-Plate-Detection-with-OpenCV-master\images\8965WDA-School_Exit-20211009100157-Seat Belt Not Buckled Up.jpg')

image = imutils.resize(image, width=1024)

cv2.imshow("Original Image", image)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("1 - Grayscale Conversion", gray)#1

gray = cv2.bilateralFilter(gray, 11, 17, 17)
cv2.imshow("2 - Bilateral Filter", gray)#2

edged = cv2.Canny(gray, 170, 200)
cv2.imshow("4 - Canny Edges", edged)#3

cv2.waitKey(0)
cv2.destroyAllWindows()#4

(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)#removed new
#cv2.imshow("check",edged)#5
cnts=sorted(cnts, key = cv2.contourArea, reverse = True)[:30]
NumberPlateCnt = None 

count = 0
for c in cnts:
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)
        if len(approx) == 4:  
            NumberPlateCnt = approx 
            break
#checker      
"""cv2.drawContours(image, cnts, -1, (0, 0, 255), 5)

# display original image with contours
cv2.namedWindow("output", cv2.WINDOW_NORMAL)
cv2.imshow("output", image)
cv2.waitKey(0)
cv2.drawContours(edged, [NumberPlateCnt], -1, (0,255,0), 3)
cv2.imshow("checker again",edged)"""
#checker

# Masking the part other than the number plate
mask = np.zeros(gray.shape,np.uint8)
new_image = cv2.drawContours(mask,[NumberPlateCnt],0,255,-1)
new_image = cv2.bitwise_and(image,image,mask=mask)
#cv2.imshow("lets see",new_image)#6
cv2.namedWindow("Final_image",cv2.WINDOW_NORMAL)
cv2.imshow("Final_image",new_image)

cv2.waitKey(0)
cv2.destroyAllWindows()#4

only detecting quads will be far too brittle
do more research

I did try it, and would like to just extract the quad of the license plate. The problem I’m getting is it detects the above text in the original image.
Could you show the pipeline as an example of extracting it ?

you mean: i write your program ? nooo …

@break

I did write that: still not detecting the plate correctly.

import numpy as np
import cv2
import imutils
import sys
import pandas as pd
import time


image = cv2.imread('.\images\8327ESA-School_Exit-20211009090601-Seat Belt Not Buckled Up.jpg')

image = imutils.resize(image, width=500)

cv2.imshow("Original Image", image)
cv2.imwrite('outputs/original.png',image)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("1 - Grayscale Conversion", gray)
cv2.imwrite('outputs/grayscale.png',gray)

gray = cv2.bilateralFilter(gray, 18, 18, 17)
cv2.imshow("2 - Bilateral Filter", gray)
cv2.imwrite('outputs/bilateral.png',gray)

gray = cv2.GaussianBlur(gray,(3,3), 0)
#comment for 1,6,7,20


edged = cv2.Canny(gray, 170, 200)
cv2.imshow("4 - Canny Edges", edged)
cv2.imwrite('outputs/edged.png',edged)

cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts=sorted(cnts, key = cv2.contourArea, reverse = True)[:30]
NumberPlateCnt = None

count = 0
for c in cnts:
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)
        if len(approx) == 4:
            NumberPlateCnt = approx
            break

# Masking the part other than the number plate
mask = np.zeros(gray.shape,np.uint8)
new_image = cv2.drawContours(mask,[NumberPlateCnt],0,255,-1)
cv2.imshow("drawn contour",new_image)
new_image = cv2.bitwise_and(image,image,mask=mask)
cv2.namedWindow("Final_image",cv2.WINDOW_NORMAL)
cv2.imshow("Final_image",new_image)
cv2.imwrite('test3.png',new_image)

testimg =cv2.imread('test3.png')

gray = cv2.cvtColor(testimg, cv2.COLOR_BGR2GRAY)
cv2.imshow('filtered image',gray)
cv2.imwrite('test3.png',gray)
cv2.waitKey(0)
# getPlateNumber(gray)

here is a result, which is wrong

well, IF you want to proceed that way, add some conceptual checks, like making sure you have (almost) horizontal / vertical lines, angles are ~90° and the aspect ratio of the rect fits an actual license plate

then you have to check the content of your rect (maybe using some crude ml)

on the other hand, it’s 2021, and there are good pretrained cnns for this purpose available …

related:

See here to see how I recommend to do it: How DarkPlate reads licence plates - YouTube

If you just need to find the plate and not read it, I still recommend the Darknet/YOLO or OpenCV DNN method, like I did it in this video: Compare 4 YOLO results - YouTube