之前在我的博客中做过国内车牌号识别定位,这次选取了欧盟车牌,并且图像中的车牌并不是规规矩矩的矩形,但是opencv的boundingRect函数只能根据所给点画出最小外接矩形,想了下可以把图像旋转一下,旋转至车牌水平方向即可。
原图如下所示:
import cv2 as cv
import numpy as np
image = cv.imread("card.jpg")
h, w = image.shape[:2]
lower = np.array([158, 100, 19]) # 车牌底色的下限
upper = np.array([255, 255, 255]) # 车牌底色的上限
mask = cv.inRange(image, lower, upper)
image_mask = cv.bitwise_and(image, image, mask=mask) # 掩膜
gray = cv.cvtColor(image_mask, cv.COLOR_BGR2GRAY) # 灰度变换
threshold = gray.sum() / (h * w) # 自定义二值化阈值
ret, binary = cv.threshold(gray, threshold, 255, cv.THRESH_BINARY) # 图像二值化处理
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) # 设置卷积核
closed = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel) # 形态学闭操作
matRotate = cv.getRotationMatrix2D((w*0.5, h*0.5), 8, 1) # 以图像中心点旋转图像
image_rot = cv.warpAffine(image, matRotate, (w, h))
close_rot = cv.warpAffine(closed, matRotate, (w, h))
contours, hierarchy = cv.findContours(close_rot, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # 寻找轮廓(只找外围轮廓)
draw_image = cv.drawContours(image_rot, contours, -1, (9, 233, 234), 8) # 画出轮廓
for i in range(len(contours)):
x, y, w, h = cv.boundingRect(contours[i])
ratio = w / h
if ratio > 3.6 and ratio < 4.8: # 一般欧盟车牌的宽高比大约在3.6~4.8之间
cv.rectangle(draw_image, (x, y), (x+w, y+h), (220, 138, 27), 10)
chepai = image_rot[y:y+h, x:x+w] # 裁剪图像
cv.imshow("Identification", chepai)
cv.waitKey(0)
cv.destroyAllWindows()
图像掩膜结果:
最终车牌裁剪结果: