一、车牌识别技术背景与核心流程
车牌识别(License Plate Recognition, LPR)是计算机视觉领域的重要应用,广泛用于停车场管理、交通违法监测、高速公路收费等场景。其核心流程可分为三步:车牌定位(从图像中定位车牌区域)、字符分割(将车牌字符逐一切分)、字符识别(识别每个字符的具体内容)。
传统方法依赖图像处理技术(如边缘检测、颜色空间分析),但受光照、倾斜、遮挡等因素影响较大。随着深度学习的发展,基于卷积神经网络(CNN)的端到端识别方案逐渐成为主流,通过数据驱动的方式提升复杂场景下的鲁棒性。
二、车牌定位算法实现
1. 基于传统图像处理的方法
步骤:
- 灰度化与二值化:将RGB图像转为灰度图,通过自适应阈值(如Otsu算法)生成二值图像。
import cv2def preprocess_image(img):gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)return binary
- 边缘检测与形态学操作:使用Canny算子检测边缘,结合膨胀、腐蚀操作增强车牌区域。
edges = cv2.Canny(binary, 50, 150)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))dilated = cv2.dilate(edges, kernel, iterations=1)
- 轮廓筛选:通过轮廓面积、长宽比等特征筛选可能的车牌区域。
contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)aspect_ratio = w / hif 2 < aspect_ratio < 6 and w > 100: # 典型车牌长宽比cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
局限性:对倾斜、模糊或低对比度图像效果较差,需结合颜色信息(如蓝色车牌的HSV范围)进一步优化。
2. 基于深度学习的方法
使用目标检测模型(如YOLO、SSD)直接定位车牌区域,代码示例(基于PyTorch):
import torchfrom torchvision import transforms# 加载预训练模型(示例为简化代码,实际需替换为车牌检测模型)model = torch.hub.load('ultralytics/yolov5', 'yolov5s') # 需替换为车牌检测模型img_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])def detect_plate(img_path):img = cv2.imread(img_path)img_tensor = img_transform(img).unsqueeze(0)results = model(img_tensor)boxes = results.xyxy[0].cpu().numpy() # 输出坐标为[x1, y1, x2, y2, conf, class]for box in boxes:if box[5] == 0: # 假设class 0为车牌x1, y1, x2, y2 = map(int, box[:4])cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)return img
优势:对复杂场景适应性更强,但需标注大量车牌数据训练模型。
三、字符分割与识别
1. 字符分割
步骤:
- 倾斜校正:通过霍夫变换检测车牌倾斜角度,使用仿射变换校正。
def correct_skew(img):gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)edges = cv2.Canny(gray, 50, 150)lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=100, minLineLength=50, maxLineGap=10)angles = []for line in lines:x1, y1, x2, y2 = line[0]angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.piangles.append(angle)median_angle = np.median(angles)(h, w) = img.shape[:2]center = (w // 2, h // 2)M = cv2.getRotationMatrix2D(center, median_angle, 1.0)rotated = cv2.warpAffine(img, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)return rotated
- 字符切分:基于投影法或连通域分析分割字符。
def segment_chars(plate_img):gray = cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY)_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)chars = []for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)if w > 10 and h > 20: # 过滤噪声char = thresh[y:y+h, x:x+w]chars.append((x, char))# 按x坐标排序chars.sort(key=lambda x: x[0])return [char[1] for char in chars]
2. 字符识别
方法对比:
- 传统OCR:使用Tesseract等工具,需预处理字符图像并调整参数。
import pytesseractdef recognize_char(char_img):text = pytesseract.image_to_string(char_img, config='--psm 10 --oem 3 -c tessedit_char_whitelist=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')return text.strip()
- 深度学习模型:训练CRNN(CNN+RNN)或Transformer模型,直接输出字符序列。
# 示例代码(需替换为实际模型)def recognize_with_crnn(char_imgs):# 假设char_imgs为字符图像列表predictions = []for img in char_imgs:img_tensor = img_transform(img).unsqueeze(0)output = crnn_model(img_tensor) # 假设已加载CRNN模型_, predicted = torch.max(output.data, 1)predictions.append(predicted.item())return ''.join([CHARS[pred] for pred in predictions]) # CHARS为字符映射表
四、性能优化与工程实践
- 数据增强:在训练阶段对车牌图像进行随机旋转、缩放、添加噪声,提升模型泛化能力。
- 模型轻量化:使用MobileNet、ShuffleNet等轻量级骨干网络,适配嵌入式设备。
- 多线程处理:在服务端部署时,采用异步队列处理多路视频流,避免IO阻塞。
- 硬件加速:利用GPU或NPU加速深度学习推理,某平台提供的AI加速库可提升3-5倍性能。
五、总结与展望
车牌识别技术已从传统图像处理向深度学习演进,但实际应用中仍需结合场景特点选择算法。例如,在资源受限的边缘设备中,可优先采用轻量级模型;在高精度要求的场景中,需构建大规模标注数据集优化模型。未来,随着多模态融合(如结合雷达、激光雷达)和自监督学习的发展,车牌识别的鲁棒性和效率将进一步提升。开发者可根据实际需求,灵活选择技术方案并持续优化。