You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.7 KiB

5 months ago
import cv2
import numpy as np
'''
基于Opencv图像处理的车牌定位和分割
'''
def car_plate_recognize(car):
"""=========================== 1. 定位车牌(车牌检测)==========================="""
# 蓝色、黄色和绿色所对应的色彩空间
lower_blue = np.array([100, 110, 110])
upper_blue = np.array([130, 255, 255])
lower_yellow = np.array([15, 55, 55])
upper_yellow = np.array([50, 255, 255])
lower_green = np.array([35, 100, 100])
upper_green = np.array([85, 255, 255])
hsv = cv2.cvtColor(car, cv2.COLOR_BGR2HSV) # 将BGR图像转化到HSV的颜色空间
mask_blue = cv2.inRange(hsv, lower_blue, upper_blue)
mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow)
mask_green = cv2.inRange(hsv, lower_green, upper_green)
mask_plate = cv2.bitwise_or(mask_blue, mask_yellow)
mask_plate = cv2.bitwise_or(mask_plate, mask_green)
# 根据阈值找到对应颜色
mask = cv2.cvtColor(mask_plate, cv2.COLOR_GRAY2BGR)
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
Matrix = np.ones((20, 20), np.uint8)
mask1 = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, Matrix)
mask = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, Matrix) # 形态学开运算
ret, mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY) # 二值化进而获取轮廓
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 获取轮廓 contours
# 初始化 box
box = None
# 寻找轮廓最大的 定位车牌
for i in range(len(contours)):
cnt = contours[i]
area = cv2.contourArea(cnt)
if area > 3000:
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int_(box)
break # 找到一个符合条件的就跳出循环
if box is None:
raise ValueError("No contours found that meet the size requirement.")
plate = cv2.drawContours(car.copy(), [box], -1, (0, 255, 0), 3)
"""=========================== 2. 分割车牌中的每个字符 ==========================="""
ys = [box[0, 1], box[1, 1], box[2, 1], box[3, 1]]
xs = [box[0, 0], box[1, 0], box[2, 0], box[3, 0]]
ys_sorted_index = np.argsort(ys)
xs_sorted_index = np.argsort(xs)
x1 = box[xs_sorted_index[0], 0]
x2 = box[xs_sorted_index[3], 0]
y1 = box[ys_sorted_index[0], 1]
y2 = box[ys_sorted_index[3], 1]
ROI_plate = plate[y1:y2, x1:x2]
ROI_plate_gray = cv2.cvtColor(ROI_plate, cv2.COLOR_BGR2GRAY) # 灰度化
ROI_plate_blur = cv2.GaussianBlur(ROI_plate_gray, (5, 5), 0) # 高斯滤波
ret, ROI_plate_Binary = cv2.threshold(ROI_plate_blur, 127, 255, cv2.THRESH_BINARY) # 二值化
# 形态学腐蚀 去除边框
kernel = np.ones((5, 5), dtype=np.uint8)
ROI_erode = cv2.erode(ROI_plate_Binary, kernel, iterations=1)
# 根据宽度 裁剪7个字符
width = ROI_erode.shape[1]
height = ROI_erode.shape[0]
word_0 = ROI_erode[0:height, 0:np.uint8(height / 2)]
word_1 = ROI_erode[0:height, np.uint8(height / 2):height]
size = np.uint8((width - height) / 5)
word_2 = ROI_erode[0:height, height + 0 * size:height + 1 * size]
word_3 = ROI_erode[0:height, height + 1 * size:height + 2 * size]
word_4 = ROI_erode[0:height, height + 2 * size:height + 3 * size]
word_5 = ROI_erode[0:height, height + 3 * size:height + 4 * size]
word_6 = ROI_erode[0:height, height + 4 * size:height + 5 * size]
word_all = [word_0, word_1, word_2, word_3, word_4, word_5, word_6]
return plate, word_all
if __name__ == "__main__":
car = cv2.imread(r'/mnt/data/cropped_license_plate_0.jpg', 1)
plate, _ = car_plate_recognize(car)
cv2.imwrite("plate.jpg", plate)