赞
踩
修复程序识别时大部分图片报错RGB转HSV失败的问题
try:
card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
except:
card_img_hsv = None
- 基于
opencv-python
的车牌识别,代码主要参考CSDN上几篇博主的代码,对预处理部分的代码进行了一定的优化,提高了识别的准确率。- 重写了一个GUI界面,添加数据导出功能。
- 添加API接口。
- Github工程已适配高版本OpenCV( 4.2.0)
先放一张运行截图:
读取图像
使用cv2.imdecode()
函数将图片文件转换成流数据,赋值到内存缓存中,便于后续图像操作。使用cv2.resize()
函数对读取的图像进行缩放,以免图像过大导致识别耗时过长。
降噪
使用cv2.GaussianBlur()
进行高斯去噪。使用cv2.morphologyEx()
函数进行开运算,再使用cv2.addWeighted()
函数将运算结果与原图像做一次融合,从而去掉孤立的小点,毛刺等噪声。
# 高斯去噪
if blur > 0:
img = cv2.GaussianBlur(img, (blur, blur), 0)
oldimg = img
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cv2.imshow('GaussianBlur', img)
kernel = np.ones((20, 20), np.uint8)
img_opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 开运算
img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0); # 与上一次开运算结果融合
# cv2.imshow('img_opening', img_opening)
3. 二值化
使用cv2.threshold()
函数进行二值化处理,再使用cv2.Canny()
函数找到各区域边缘。
ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 二值化
img_edge = cv2.Canny(img_thresh, 100, 200)
# cv2.imshow('img_edge', img_edge)
将图像边缘连接为一个整体
使用cv2.morphologyEx()
和cv2.morphologyEx()
两个函数分别进行一次开运算(先腐蚀运算,再膨胀运算)和一个闭运算(先膨胀运算,再腐蚀运算),去掉较小区域,同时填平小孔,弥合小裂缝。将车牌位置凸显出来。
kernel = np.ones((self.cfg["morphologyr"], self.cfg["morphologyc"]), np.uint8)
img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel) # 闭运算
img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel) # 开运算
# cv2.imshow('img_edge2', img_edge2)
查找车牌(矩形区域)
查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中,逐个排除不是车牌的矩形区域。车牌形成的矩形区域长宽比在2到5.5之间,因此使用cv2.minAreaRect()
函数框选矩形区域计算长宽比,长宽比在2到5.5之间的可能是车牌,其余的矩形排除。最后使用cv2.drawContours()
函数将可能是车牌的区域在原图中框选出来。(此处处理结果可能得到多个符合要求的矩形,而未必直接得到车牌位置,因此还需后续处理。)
图形修正
矩形区域可能是倾斜的矩形,需要矫正,以便使用颜色定位,从而进一步确认是否是车牌。类似下两图(仅列举出两个,可能有很多)。
颜色识别
使用颜色定位,排除不是车牌的矩形,目前只识别车牌的颜色主要为蓝、绿、黄三种颜色车牌。根据矩形的颜色不同从而选出最可能是车牌的矩形。同时匹配出车牌的类型(颜色类型)。使用参数为*cv2.COLOR_BGR2HSV
*的cv2.cvtColor()
函数将原始的RGB图像转换成HSV图像,以便定位颜色。
基于HSV颜色模型可知色调H的取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;查阅相关资料确定出下表:
黄色 | 绿色 | 蓝色 | |
---|---|---|---|
H | 14-34 | 34-99 | 99-124 |
根据上表计算出每个矩形中各颜色的占有量,比较每个矩形三个颜色的占有量,即可确定最可能是车牌的矩形以及车牌颜色。
车牌部分二值化
利用参数为*cv2.COLOR_BGR2GRAY
*的cv2.cvtColor()
函数将定位到的车牌部分RGB图像转化为灰度图像,再利用cv2. threshold()
函数将灰度图像二值化。需要注意的是,黄、绿色车牌字符比背景暗、与蓝的车牌刚好相反,所以黄、绿车牌在二值化前需要利用cv2.bitwise_not( )
函数取反向。
# 做一次锐化处理
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) # 锐化
card_img = cv2.filter2D(card_img, -1, kernel=kernel)
# cv2.imshow("custom_blur", card_img)
# RGB转GARY
gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY)
# cv2.imshow('gray_img', gray_img)
# 黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向
if color == "green" or color == "yellow":
gray_img = cv2.bitwise_not(gray_img)
# 二值化
ret, gray_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# cv2.imshow('gray_img', gray_img)
字符分割(投影法)
根据设定的阈值和图片直方图,找出波峰,利用找出的波峰,分隔图片。因为车牌中“ • ”也会产生一组波峰,因此将八组波峰中的第三组去除掉,即可得到每个字符的波峰,再根据每组波峰的宽度分割牌照图像得到每个字符的图像.
匹配模板
将分割后的每个图像逐个与已训练好的模板进行匹配,得到识别结果。
# !/usr/bin/python # -*- coding: utf-8 -*- # @Time: 2020/2/6 下午12:13 # @Author: Casually # @File: Server.py # @Email: fjkl@vip.qq.com # @Software: PyCharm from _collections import OrderedDict from flask import Flask, request, jsonify from json_utils import jsonify import numpy as np import cv2 import time from collections import OrderedDict from Recognition import PlateRecognition # 实例化 app = Flask(__name__) PR = PlateRecognition() # 设置编码-否则返回数据中文时候-乱码 app.config['JSON_AS_ASCII'] = False # route()方法用于设定路由;类似spring路由配置 @app.route('/', methods=['POST']) # 在线识别 def forecast(): # 获取输入数据 stat = time.time() file = request.files['image'] img_bytes = file.read() image = np.asarray(bytearray(img_bytes), dtype="uint8") image = cv2.imdecode(image, cv2.IMREAD_COLOR) RES = PR.VLPR(image) if RES is not None: result = OrderedDict( Error=0, Errmsg='success', InputTime=RES['InputTime'], UseTime='{:.2f}'.format(time.time() - stat), # RES['UseTime'], Number=RES['Number'], From=RES['From'], Type=RES['Type'], List=RES['List']) else: result = OrderedDict( Error=1, Errmsg='unsuccess') return jsonify(result) if __name__ == '__main__': app.run()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。