Reputation: 41
I'm trying to recognize a license plate but got error such as wrong/not reading the character
Here's a visualization of each step:
Obtained mask from color thresholding + morph closing
Filter for license plate contours highlighted in green
Pasted plate contours onto a blank mask
The expected result from Tesseract OCR
BP 1309 GD
But the result I got is
BP 1309 6D
and I try to slices the contour to 3 slices
and yes it's working but if I insert difference image to this method some image not recognize for example this one
the letter N is not recognized but if using first method it's working
Here's is the code
import numpy as np
import pytesseract
import cv2
import os
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
image_path = "data"
for nama_file in sorted(os.listdir(image_path)):
print(nama_file)
# Load image, create blank mask, convert to HSV, define thresholds, color threshold
I = cv2.imread(os.path.join(image_path, nama_file))
dim = (500, 120)
I = cv2.resize(I, dim, interpolation = cv2.INTER_AREA)
(thresh, image) = cv2.threshold(I, 127, 255, cv2.THRESH_BINARY)
result = np.zeros(image.shape, dtype=np.uint8)
result = 255 - result
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0,0,0])
upper = np.array([179,100,130])
mask = cv2.inRange(hsv, lower, upper)
slices = []
slices.append(result.copy())
slices.append(result.copy())
slices.append(result.copy())
i = 0
j = 0
xs = []
# Perform morph close and merge for 3-channel ROI extraction
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=1)
extract = cv2.merge([close,close,close])
# Find contours, filter using contour area, and extract using Numpy slicing
cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
key=lambda b:b[1][0], reverse=False))
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
area = w * h
ras = format(w / h, '.2f')
if h >= 40 and h <= 70 and w >= 10 and w <= 65 and float(ras) <= 1.3:
cv2.rectangle(I, (x, y), (x + w, y + h), (36,255,12), 3)
result[y:y+h, x:x+w] = extract[y:y+h, x:x+w]
# Slice
xs.append(x)
if i > 0:
if (xs[i] - xs[i-1]) > 63:
j = j+1
i = i + 1
slices[j][y:y+h, x:x+w] = extract[y:y+h, x:x+w]
# Split throw into Pytesseract
j=0
for s in slices:
cv2.imshow('result', s)
cv2.waitKey()
if j != 1 :
data = pytesseract.image_to_string(s, lang='eng',config='--psm 6 _char_whitelist=ABCDEFGHIJKLMNOPQRTUVWXYZ')
else :
data = pytesseract.image_to_string(s, lang='eng',config='--psm 6 _char_whitelist=1234567890')
print(data)
# Block throw into Pytesseract
data = pytesseract.image_to_string(result, lang='eng',config='--psm 6')
print(data)
cv2.imshow('image', I)
cv2.imshow('close', close)
cv2.imshow('extract', extract)
cv2.imshow('result', result)
cv2.waitKey()
Maybe someone knows why this happens and what should do?
Thanks in advance
Upvotes: 1
Views: 721
Reputation: 643
I can decode the plate instantly by using a simple command in ubuntu shell. But in order to do that, you must upgrade tesseract from version 4 to 5.
tesseract a364k.png stdout -l eng --oem 3 --psm 7 -c tessedit_char_whitelist="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "
BP 1309 GD
In your code, you can add this to config
-l eng --oem 3 --psm 7 -c tessedit_char_whitelist="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "
Upvotes: 0
Reputation: 32094
I have tried many things and found some sort of solution:
Apply dilate morphological operation to make the letter thinner:
# Split throw into Pytesseract
j=0
for s in slices:
cv2.imshow('result', s)
cv2.waitKey(1)
if j != 1:
data = pytesseract.image_to_string(s, config="-c tessedit"
"_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
" --psm 6"
" ")
if data=='':
s = cv2.dilate(s, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)))
cv2.imshow('cv2.dilate(s)', s)
cv2.waitKey(1)
data = pytesseract.image_to_string(s, config="-c tessedit"
"_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
" --psm 6"
" ")
else:
pytesseract.pytesseract.tessedit_char_whitelist = '1234567890'
data = pytesseract.image_to_string(s, lang='eng',config='--psm 6 _char_whitelist=1234567890')
print(data)
This behavior is very weird.
There are many complains, and the suggested solutions are not working.
See the following post for example: Tesseract does not recognize single characters
At least I learned how to use _char_whitelist
option (you need to add -c tessedit
)...
I suppose the solution is not robust enough (probably working by chance).
I think there in no simple solution in the current version of Tesseract.
Upvotes: 1