文章目录
一、简介:二:车牌识别方案三、算法实现步骤3.1 颜色识别,提取蓝色区域:3.2 形态学变换清除噪点以及车牌空洞区域3.3四边形逼近取出车牌区域3.4车牌识别 四:整体代码实现
一、简介:
随着科技的不断发展,车牌识别技术在智能交通、安防监控等领域得到了广泛应用。本文将介绍如何使用OpenCV库来实现车牌识别功能。通过学习本项目,您将掌握如何通过opencv以及ocr字符识别来进行车牌定位与识别。
二:车牌识别方案
本次车牌识别方案为:首先,通过颜色识别技术对图像进行分割,精准定位蓝色区域,这是车牌的显著特征;接着,运用形态学变换,有效清除图像中的噪点和车牌上的空洞区域,确保图像清晰;然后,采用四边形逼近方法,精确提取车牌区域;紧接着,从蒙版中提取出对应的车牌原图;最后,利用OCR技术对车牌数字进行识别,完成整个车牌识别过程。
三、算法实现步骤
待处理的车牌图如下所示:
3.1 颜色识别,提取蓝色区域:
对上面车牌进行分析,车牌的特征为蓝白相间的矩形区域,首先先提取出图像中的蓝色区域
代码为:
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 定义蓝色物体在HSV颜色空间中的范围# 这里需要根据实际情况调整蓝色范围的上下限blue_lower = np.array([100, 50, 50])blue_upper = np.array([120, 255, 255])# 创建掩码,只保留蓝色物体mask = cv2.inRange(hsv_image, blue_lower, blue_upper)
效果为:
3.2 形态学变换清除噪点以及车牌空洞区域
形态学变换是图像处理中的一种重要技术,它基于集合论,通过结构元素对图像进行膨胀和腐蚀操作,以提取图像中的形状特征、连接成分、突出边缘等。开运算和闭运算是形态学变换的两种基本操作,开运算是先腐蚀后膨胀,用于清除图像中的小对象和噪点,平滑较大对象的边界;闭运算则是先膨胀后腐蚀,用于填充物体内的小孔和连接邻近的边缘,从而平滑物体的轮廓。通过将开闭运算级联使用进而获得干净的车牌区域,滤除噪点与空洞。
代码如下(示例):
# 定义结构元kernel = np.ones((9,9), np.uint8)kernel2 = np.ones((21,21), np.uint8)# 进行开闭运算清除噪点填充空洞opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel2)
效果为:
3.3四边形逼近取出车牌区域
根据经验可知,车牌的形状为矩形,所以我们选择通过cv2.approxPolyDP()函数拟合多边形来蒙版中的矩形区域,进一步过滤无效信息。
其中cv2.approxPolyDP() 是OpenCV库中的一个函数,用于对给定的曲线进行多边形逼近。该函数通过最小化多边形的边数来逼近曲线,同时保持逼近多边形与原始曲线之间的距离小于指定的精度阈值。简而言之,它可以将一个形状复杂的轮廓简化为一个具有较少顶点的近似多边形,这对于形状识别和轮廓简化非常有用。函数的输入为输入轮廓、精度阈值以及是否闭合多边形的标志,输出则是逼近后的多边形顶点坐标。
# 使用findContours函数查找轮廓contours_fist, _ = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 创建一个与mask相同大小的零矩阵,用于绘制轮廓mask2 = np.zeros_like(mask)# 遍历所有轮廓for contour in contours_fist: # 计算轮廓的面积 area = cv2.contourArea(contour) # 如果轮廓面积小于200,则跳过 if area < 200: continue # 计算轮廓的近似精度 epsilon = 0.08 * cv2.arcLength(contour, True) #0.08根据实际情况进行修改 # 使用approxPolyDP函数获取轮廓的近似多边形 approx = cv2.approxPolyDP(contour, epsilon, True) # 如果近似多边形有4个顶点,则认为找到了车牌区域 if len(approx) == 4: # 在mask2上绘制找到的车牌区域轮廓 cv2.drawContours(mask2, [approx], -1, (255, 255, 255), -1)
效果为:
至此我们就定位好车牌所在的区域了,接下来只需要对区域与原图进行按位与即可切除原图中的车牌并进行识别
3.4车牌识别
本次ocr使用的是paddleocr,不会使用的小伙伴们请参照上一篇博客,快速使用paddleocr进行文字识别
代码为:
blue_objects = cv2.bitwise_and(image, image, mask=mask2) #按照蒙版抠出原图ocr = PaddleOCR(use_angle_cls=True, lang="ch") # need to run only once to download and load model into memory# img_path = r'C:\Users\zhw\Downloads\ppocr_img\imgs\2.jpg'result = ocr.ocr(blue_objects, cls=True)for idx in range(len(result)): res = result[idx] for line in res: print(line)
效果:
四:整体代码实现
import cv2import numpy as npfrom paddleocr import PaddleOCR, draw_ocr# 读取图像image = cv2.imread(r'F:\traditional_vison\20181109135315489.png')# 将图像从BGR颜色空间转换到HSV颜色空间hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 定义蓝色物体在HSV颜色空间中的范围# 这里需要根据实际情况调整蓝色范围的上下限blue_lower = np.array([100, 50, 50])blue_upper = np.array([120, 255, 255])# 创建掩码,只保留蓝色物体mask = cv2.inRange(hsv_image, blue_lower, blue_upper)# 通过位运算提取蓝色物体# 定义结构元kernel = np.ones((9,9), np.uint8)kernel2 = np.ones((21,21), np.uint8)# 进行开闭运算清除噪点填充空洞opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel2)contours_fist, _ = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)mask2 = np.zeros_like(mask)for contour in contours_fist: area = cv2.contourArea(contour) if area < 200: continue epsilon = 0.08 * cv2.arcLength(contour, True) approx = cv2.approxPolyDP(contour, epsilon, True) if len(approx) == 4: cv2.drawContours(mask2, [approx], -1, (255, 255, 255), -1)blue_objects = cv2.bitwise_and(image, image, mask=mask2)ocr = PaddleOCR(use_angle_cls=True, lang="ch") # need to run only once to download and load model into memory# img_path = r'C:\Users\zhw\Downloads\ppocr_img\imgs\2.jpg'result = ocr.ocr(blue_objects, cls=True)for idx in range(len(result)): res = result[idx] for line in res: print(line)# 显示原图和分割后的蓝色物体cv2.imshow('mask', mask)cv2.imshow('close', close)cv2.imshow('mask2', mask2)cv2.imshow('Blue Objects', blue_objects)# 等待按键后退出cv2.waitKey(0)cv2.destroyAllWindows()