一开始本想基于OpenCV原理编写定位程序的,但发现效果并不是特别理想,只能识别我处理的那张图片的车牌,在使用其他图片识别的时候失误非常多,几乎识别不到车牌,下面附上识别的代码和效果图:
import cv2
import numpy as np
def detect(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 变成灰度图
blurred = cv2.GaussianBlur(gray, (5, 5), 0, 0, cv2.BORDER_DEFAULT)
# cv2.imshow('blurred', blurred)
kernel = np.ones((23, 23), np.uint8)
opened = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, kernel) # 开运算
# cv2.imshow('opened',opened)
opened = cv2.addWeighted(blurred, 1, opened, -1, 0)
# cv2.imshow('opened', opened)
ret, thresh = cv2.threshold(opened, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 阈值分割
edge = cv2.Canny(thresh, 100, 200) # 找到图像边缘
#cv2.imshow('canny',edge)
# 使用开运算和闭运算让图像边缘连成一个整体
kernel = np.ones((10, 10), np.uint8)
edge1 = cv2.morphologyEx(edge, cv2.MORPH_CLOSE, kernel)
edge2 = cv2.morphologyEx(edge1, cv2.MORPH_OPEN, kernel)
cv2.imshow('edge',edge2)
# 查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中
contours, hierarchy = cv2.findContours(edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
temp_contours = []
for contour in contours:
if cv2.contourArea(contour) > 2000:
temp_contours.append(contour)
car_plates = []
for temp_contour in temp_contours:
rect_tupple = cv2.minAreaRect(temp_contour)
rect_width, rect_height = rect_tupple[1]
if rect_width < rect_height:
rect_width, rect_height = rect_height, rect_width
aspect_ratio = rect_width / rect_height
# 车牌正常情况下宽高比在2 - 5.5之间
if aspect_ratio > 2 and aspect_ratio < 5.5:
car_plates.append(temp_contour)
rect_vertices = cv2.boxPoints(rect_tupple)
rect_vertices = np.int0(rect_vertices)
if len(car_plates) == 1:
for car_plate in car_plates:
row_min, col_min = np.min(car_plate[:, 0, :], axis=0)
row_max, col_max = np.max(car_plate[:, 0, :], axis=0)
cv2.rectangle(image, (row_min, col_min), (row_max, col_max), (0, 255, 0), 2)
card = image[col_min:col_max, row_min:row_max, :]
cv2.imshow("img", image)
cv2.imshow("card_img.jpg", card)
if __name__ == '__main__':
image = cv2.imread('Image/5.jpg')
detect(image)
cv2.waitKey(0)
cv2.destroyAllWindows()
可以看出识别不是特别理想,本来想采用第二种想法使用模糊处理之后通过对蓝色以及矩形进行识别定位车牌的,结果发现Github是有车牌识别分类器的,于是直接套着用。(用颜色和形状进行定位的会在用这个分类器方法识别完车牌之后进行尝试)
Github分类器地址:
https://github.com/zeusees/HyperLPR/blob/master/model/cascade.xml
代码如下
import cv2
import numpy as np
def detect(image):
# 定义分类器
cascade_path = 'cascade.xml'
cascade = cv2.CascadeClassifier(cascade_path)
# 修改图片大小
resize_h = 400
height = image.shape[0]
scale = image.shape[1] / float(height)
image = cv2.resize(image, (int(scale * resize_h), resize_h))
# 转为灰度图
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# 车牌定位
car_plates = cascade.detectMultiScale(image_gray, 1.1, 2, minSize=(36, 9), maxSize=(36 * 40, 9 * 40))
print("检测到车牌数", len(car_plates))
if len(car_plates) > 0:
for car_plate in car_plates:
x, y, w, h = car_plate
plate = image[y - 10: y + h + 10, x - 10: x + w + 10]
#cv2.imshow('plate', plate
cv2.rectangle(image, (x - 10, y - 10), (x + w + 10, y + h + 10), (255, 0, 0), 2)
cv2.imshow("image", image)
if __name__ == '__main__':
image = cv2.imread('Image/2.jpg')
detect(image)
cv2.waitKey(0)
cv2.destroyAllWindows()
识别出来效果非常好,果然还是分类器好用…
这样车牌的定位就完成了,之后就是对车牌进行分析