之前在我的博客中做過國內車牌號識別定位,這次選取了歐盟車牌,並且圖像中的車牌並不是規規矩矩的矩形,但是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()
圖像掩膜結果:
最終車牌裁剪結果: