本文将从各种角度介绍基于OpenCV的车牌识别,包括车牌定位、车牌字符分割及识别等方面。
一、车牌定位
车牌定位是车牌识别的第一步,其目的是在整张图像中找出车牌的位置,并将车牌区域从图像中提取出来。车牌定位可以采用基于颜色的方法或基于形状的方法。
以下是基于颜色的车牌定位代码示例:
import cv2 import numpy as np def locate_car_plate(img): # 转换为HSV空间 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 设定蓝色区域的HSV范围 lower_blue = np.array([100, 50, 50]) upper_blue = np.array([124, 255, 255]) # 根据HSV范围生成掩膜 mask = cv2.inRange(hsv, lower_blue, upper_blue) # 对掩膜进行开闭运算 kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 找出轮廓 contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 找出最大轮廓 max_area = 0 max_contour = None for contour in contours: area = cv2.contourArea(contour) if area > max_area: max_area = area max_contour = contour # 找出轮廓的外接矩形 x, y, w, h = cv2.boundingRect(max_contour) # 在原图像上绘制外接矩形 cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 返回车牌图像 plate_img = img[y:y + h, x:x + w] return plate_img
二、车牌字符分割
车牌字符分割的目的是将车牌中的字符区域提取出来进行识别。字符分割可以采用基于形状或基于颜色的方法。
以下是基于形状的车牌字符分割代码示例:
def segment_car_plate_characters(img): # 转换为灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 进行OTSU阈值分割 ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 找出轮廓 contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 对轮廓进行排序 contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[0]) # 提取字符图像 character_imgs = [] for contour in contours: x, y, w, h = cv2.boundingRect(contour) if w > h: character_img = img[y:y + h, x:x + w] character_img = cv2.resize(character_img, (20, 20)) character_imgs.append(character_img) return character_imgs
三、车牌字符识别
车牌字符识别的目的是将字符图像中的字符进行识别。字符识别可以采用基于SVM或基于深度学习的方法。
以下是基于SVM的车牌字符识别代码示例:
import joblib def recognize_car_plate_characters(character_imgs): # 加载分类器模型 svm = joblib.load('svm.pkl') # 提取特征 features = [] for img in character_imgs: gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) feature = hog(gray, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3)) features.append(feature) # 进行分类 pred_labels = svm.predict(features) # 转换为字符 characters = [] for label in pred_labels: characters.append(chr(label)) return characters
四、实例演示
本文提供了一个基于OpenCV的简单车牌识别实例,可以通过以下代码进行测试:
import cv2 import numpy as np import joblib from skimage.feature import hog def locate_car_plate(img): hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) lower_blue = np.array([100, 50, 50]) upper_blue = np.array([124, 255, 255]) mask = cv2.inRange(hsv, lower_blue, upper_blue) kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) max_area = 0 max_contour = None for contour in contours: area = cv2.contourArea(contour) if area > max_area: max_area = area max_contour = contour x, y, w, h = cv2.boundingRect(max_contour) cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) plate_img = img[y:y + h, x:x + w] return plate_img def segment_car_plate_characters(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[0]) character_imgs = [] for contour in contours: x, y, w, h = cv2.boundingRect(contour) if w > h: character_img = img[y:y + h, x:x + w] character_img = cv2.resize(character_img, (20, 20)) character_imgs.append(character_img) return character_imgs def recognize_car_plate_characters(character_imgs): svm = joblib.load('svm.pkl') features = [] for img in character_imgs: gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) feature = hog(gray, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3)) features.append(feature) pred_labels = svm.predict(features) characters = [] for label in pred_labels: characters.append(chr(label)) return characters if __name__ == "__main__": img = cv2.imread("test.jpg") plate_img = locate_car_plate(img) character_imgs = segment_car_plate_characters(plate_img) characters = recognize_car_plate_characters(character_imgs) print(characters)
结论
本文从车牌定位、车牌字符分割及识别等方面详细介绍了基于OpenCV的车牌识别。通过实例演示可以发现该方法在车牌定位和字符分割方面表现较好,但字符识别需要更多的训练数据和优化才能达到更好的效果。