车牌识别
车牌识别1.0版本,只实现了纯数字的识别,可以持续关注我滴博客,查看新改良版本
主体思路:把模板图片与输入图片分别处理,得到轮廓,再利用函数boundingRect(c)函数得到轮廓信息(在原图像坐标),再把用此轮廓信息把图片切割下来,这样就得到了模板与输入图像的切割图像,然后让这些切割图像进行匹配。
除杂处理——>轮廓信息——>切割图像——>切割图像匹配
处理模板及输入图像
模板图像处理
因为模板图像没有杂点,所以画轮廓时不会有多余轮廓,因此不需要膨胀腐蚀操作再与空面板相减
先二值化即可
输入图像处理
这个输入的图像就会有边界什么的了,先二值化,我采样的是空模板相减,但是考虑到尺寸的缩放以及位置的偏差,所以再对空模板做膨胀操作,让外框更大,然后更好的除掉无关图像
核心代码:
input_img,thresh2 = being_binary(input_address,127, 255, cv2.THRESH_BINARY)
null_img,thresh_null = being_binary("D:/python/pycharm/chepai_null.png",127, 255, cv2.THRESH_BINARY)
y,x = null_img.shape
kernel = np.ones((5, 5), np.uint8)
null_img = cv2.dilate(null_img,kernel,iterations=4)
thresh2 = cv2.resize(thresh2,(x,y))
thresh2 = cv2.subtract(thresh2, null_img)
轮廓信息提取
没什么好说的,就是一个findcontours函数,就是提取出来的轮廓要打印一下contours的数量,即len(contours),与数字个数比较要相等,要不然很可能画到了杂点轮廓
# 寻找轮廓函数
contours, hierarachy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
取出模板的切割图片
代码:
def cutting_(thresh,contours):
name = 0
img_all = []
station = []
for c in contours:
# 边界矩形--其实就是用获得边界信息,然后再用画矩形函数画一个矩形
x, y, w, h = cv2.boundingRect(c)
station.append(x)
img = thresh[y:y+h,x:x+w]
img_all.append(img)
img_all = [img_temp for _, img_temp in sorted(zip(station,img_all))]
for t in img_all:
cv2.imwrite(f"D:/python/{name}.jpg",t)
name += 1
return img_all
如何对应图像对应数字
这里数字顺序就是按照切割顺序来的,所以得到的切割图像列表的下标就代表数字
再处理输入图像
考虑到输入图像的性状杂点可能会比较多,防止未排除杂点轮廓的影响,再一步处理,这次采样的是只取最大的前7个轮廓(因为车牌全为数字的话一般只有7位),精度再一步提高
# 获得所有面积,以后方便排序
area_all = []
for cnt in contours2:
area = cv2.arcLength(cnt, True)
area_all.append(area)
# 将面积切片,因为车牌全为数字的话一般只有7位,取面积最大的7个就可以了
# zip主要目的是想与下标连接起来画轮廓,与主线无关。zip完了之后如果是两个不同的数据类型记得强制指定一下数据类型,要不然不男不女
zip_contours2 = sorted(zip(area_all,list(range(len(area_all)+1))),reverse=True)[:8]
print(zip_contours2)
for _,i in zip_contours2:
cv2.drawContours(input0, contours2[i], -1, (0, 0, 255), 2)
切割输入图片并模板匹配
和切割模板图片一样,这个取出感兴趣区。得到输入图片的7张感兴趣区(也就是被切割图片),模板有10个,就这样每一个感兴趣区都要与10个模板匹配一次,但是匹配函数返回的是一个二维数组,这时用于其搭配的函数:,获取最值,具体是大还是小代表匹配程度高,这个要去看匹配函数使用的模式,我这里是取最小值,一个切割图像匹配10次会获得10个最小值,我们取这些最小值中的最小的那一个,就是匹配程度最高的了。
for contour in contours2:
x, y, w, h = cv2.boundingRect(contour) # 获取轮廓的外接矩形
digit_roi = thresh2[y:y + h, x:x + w] # 从图像中提取数字的感兴趣区域
digit_roi = cv2.copyMakeBorder(digit_roi, 300, 300, 300, 300, cv2.BORDER_CONSTANT, value=0)
min_score = 100
min_match_index = None
for i in range(len(img_all)):
result_ = cv2.matchTemplate(digit_roi, img_all[i], cv2.TM_SQDIFF_NORMED)
match_score, _, _, _ = cv2.minMaxLoc(result_)
if match_score < min_score:
min_score = match_score
min_match_index = i
cv2.putText(input_draw, f'{min_match_index}',(x,y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
结果
这里我是画在图片上,当然也可以打印出来
下一阶段:从大背景提取车牌并识别
预期涉及基本图像图像处理(膨胀腐蚀找边界)以及resize改变大小