我正在使用 Python 开发车牌识别系统,使用 OpenCV 进行图像处理,使用 Tesseract OCR 进行字符识别。我编写了一个函数来处理车牌图像并从中提取文本,但我在一致检测大字符和小字符时遇到了问题。该功能旨在在使用 Tesseract OCR 之前锐化图像、增加对比度并应用各种预处理步骤。
@staticmethod
def process_license_plate(frame, x1, y1, x2, y2):
"""
Extracts and processes the license plate area from the frame using enhanced OCR.
Parameters:
- frame (numpy.ndarray): The image or video frame containing the license plate.
- x1, y1, x2, y2 (int): Coordinates of the license plate bounding box.
Returns:
- str: The recognized text of the license plate.
"""
# Step 1: Crop the license plate area
license_plate_area = frame[y1:y2, x1:x2]
# Step 2: Sharpen the license plate area using a kernel
sharpening_kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
sharpened_license_plate = opencv.filter2D(license_plate_area, -1, sharpening_kernel)
# Step 3: Increase contrast using CLAHE
lab = opencv.cvtColor(sharpened_license_plate, opencv.COLOR_BGR2LAB)
l, a, b = opencv.split(lab)
clahe = opencv.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
limg = opencv.merge([clahe.apply(l), a, b])
enhanced_license_plate = opencv.cvtColor(limg, opencv.COLOR_LAB2BGR)
# Step 4: Preprocess for OCR - Grayscale conversion, Gaussian blur, and Adaptive thresholding
grayscale_license_plate = opencv.cvtColor(enhanced_license_plate, opencv.COLOR_BGR2GRAY)
blurred_license_plate = opencv.GaussianBlur(grayscale_license_plate, (3, 3), 0)
_, thresholded_license_plate = opencv.threshold(blurred_license_plate, 0, 255, opencv.THRESH_BINARY + opencv.THRESH_OTSU)
# Step 5: Morphological operations to clean up the image
morph_kernel = opencv.getStructuringElement(opencv.MORPH_RECT, (3, 3))
opened_license_plate = opencv.morphologyEx(thresholded_license_plate, opencv.MORPH_OPEN, morph_kernel, iterations=1)
inverted_license_plate = opencv.bitwise_not(opened_license_plate)
# Step 6: Extract text using OCR
license_plate_text = pytesseract.image_to_string(
inverted_license_plate, lang='eng',
config='--psm 6 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
)
return license_plate_text.strip()
我尝试以车牌的高度比例作为参考来隔离较大的字符。然而,正如预期的那样,这种方法并没有成功。
# Step 6: Filter out smaller elements and keep larger characters (optional)
contours, _ = opencv.findContours(inverted_license_plate, opencv.RETR_EXTERNAL, opencv.CHAIN_APPROX_SIMPLE)
filtered_license_plate = np.zeros_like(inverted_license_plate)
# Define a threshold for contour area (e.g., 90% of the license plate area)
threshold_area = 0.9 * license_plate_area.shape[0] * license_plate_area.shape[1] # Debbuging values
for contour in contours:
if opencv.contourArea(contour) > threshold_area:
opencv.drawContours(filtered_license_plate, [contour], -1, (255, 255, 255), thickness=opencv.FILLED)
这是使用过滤器的最终结果:
[]
这是没有滤镜的结果
我们看到 3 个字符,一个花园状态图标,然后是另外 3 个字符。
考虑编写一个例程,在 NJ 图标上放置一个边界框。 有了这些,您就可以更好地找到 bbox 对于 6 个感兴趣的字符。 您可能还会发现删除图标 bbox 内的像素 提高 OCR 性能。
我们在几个地方看到书写,字体大小变化很大。
Tesseract 与分辨率有一些奇怪的相互作用。 给它一些干净的 Helvetica 字符 PDF 位图, 它在较小的分辨率范围内工作得很好, 假设 1 em 是十几个到几十个像素。 炸毁东西,这样我们每个角色就有几百个像素, OCR 性能下降。
请注意,小字体文本已被充分识别。 这里有一些建议,以便 Tesseract 会忽略此类干扰性文本:
如果您能够使用边界框来消除干扰因素, 这也是公平的游戏。 但它对板材和汽车之间的变化更敏感。