Patryk Szlagowski
detect and read license plate
e121a44
import cv2
import numpy as np
from PIL import ImageOps, ImageEnhance, Image
def enhance(crop: Image.Image) -> Image.Image:
"""
prepare crop for ocr - grayscale, contrast, sharpness, resize
:param crop: image to prepare
:rtype: Image.Image
:return: processed image
"""
image = ImageOps.grayscale(crop)
image = ImageEnhance.Contrast(image).enhance(5)
image = ImageEnhance.Sharpness(image).enhance(5)
image = ImageOps.scale(image, 3.5)
image = _remove_dark_frame(image)
image = _remove_shades(image)
return image
def _remove_dark_frame(img: Image.Image) -> Image.Image:
# Convert PIL Image to OpenCV format
open_cv_image = np.array(img.convert('RGB'))
open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR)
# Convert to grayscale
gray = cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2GRAY)
# Blur the image to reduce noise
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Apply a binary threshold after blurring
_, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Find contours from the binary image
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Assume the largest contour is the frame
c = max(cnts, key=cv2.contourArea)
# Find the bounding box coordinates from the contour
x, y, w, h = cv2.boundingRect(c)
# Crop the original image using the bounding box coordinates
cropped = open_cv_image[y:y+h, x:x+w]
# Convert back to PIL format
cropped_pil = Image.fromarray(cv2.cvtColor(cropped, cv2.COLOR_BGR2RGB))
return cropped_pil
def _remove_shades(image: Image.Image, threshold: int = 64) -> Image.Image:
"""
Remove shades between white and black from an image using PIL.
Parameters:
- image_path: The path to the image.
- threshold: The cutoff for determining whether a pixel should be white or black.
Returns:
- A new PIL Image object with shades removed.
"""
# Convert the image to grayscale
gray_img = image.convert("L")
# Apply the threshold
# All pixels value > threshold will be set to 255 (white)
# All pixels value <= threshold will be set to 0 (black)
binary_img = gray_img.point(lambda x: 255 if x > threshold else 0, '1')
return binary_img