简介:本文围绕OpenCV在车牌识别中的应用展开,系统解析了车牌定位、字符分割与识别的技术原理,结合代码示例和优化策略,为开发者提供可落地的技术方案。
车牌识别(License Plate Recognition, LPR)作为计算机视觉领域的典型应用,需解决图像预处理、目标定位、字符分割与识别四大核心问题。OpenCV作为开源计算机视觉库,凭借其跨平台特性、丰富的算法模块(如图像处理、特征提取、机器学习)及高效的C++/Python接口,成为实现LPR系统的首选工具。其优势体现在:
原始图像可能存在光照不均、噪声干扰等问题,需通过以下步骤增强目标特征:
cv2.cvtColor(img, cv2.COLOR_BGR2GRAY));cv2.GaussianBlur(img, (5,5), 0));cv2.equalizeHist(img))。车牌区域通常具有明显的边缘特征,可通过Sobel算子或Canny边缘检测提取轮廓:
edges = cv2.Canny(img, 50, 150)
随后利用形态学操作(如闭运算)连接断裂边缘:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 5))closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
通过cv2.findContours获取所有轮廓,根据长宽比、面积等几何特征筛选车牌候选区域:
contours, _ = cv2.findContours(closed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)aspect_ratio = w / hif 3 < aspect_ratio < 6 and 1000 < w * h < 10000: # 经验阈值plate_region = img[y:y+h, x:x+w]
对车牌区域进行自适应阈值二值化(cv2.adaptiveThreshold),消除背景干扰:
binary = cv2.adaptiveThreshold(plate_region, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV, 11, 2)
统计每列的像素值和,通过波谷定位字符间隔:
hist = np.sum(binary, axis=0)min_val = np.min(hist)char_widths = []start = 0for i in range(1, len(hist)):if hist[i] < min_val * 0.3: # 波谷阈值if i - start > 5: # 最小字符宽度char_widths.append((start, i))start = i
将分割后的字符调整为统一尺寸(如20x40像素),便于后续识别:
char_img = cv2.resize(binary[:, start:end], (20, 40))
预定义数字、字母的模板图像,通过相关性匹配识别字符:
def match_char(char_img, templates):max_score = -1result = '?'for char, template in templates.items():res = cv2.matchTemplate(char_img, template, cv2.TM_CCOEFF_NORMED)_, score, _, _ = cv2.minMaxLoc(res)if score > max_score:max_score = scoreresult = charreturn result if max_score > 0.7 else '?' # 置信度阈值
对于复杂场景(如倾斜、污损车牌),可结合CNN模型(如CRNN)提升识别率:
cv2.dnn.readNetFromONNX加载。cv2.cuda.GpuMat),提升大尺寸图像处理速度;
import cv2import numpy as npdef detect_plate(img):# 预处理gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)blur = cv2.GaussianBlur(gray, (5,5), 0)edges = cv2.Canny(blur, 50, 150)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17,5))closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)# 轮廓检测contours, _ = cv2.findContours(closed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)for cnt in contours:x,y,w,h = cv2.boundingRect(cnt)if 3 < w/h < 6 and 1000 < w*h < 10000:plate = img[y:y+h, x:x+w]return platereturn Nonedef recognize_chars(plate):# 假设已实现字符分割与识别逻辑chars = []# ... 分割与识别代码 ...return ''.join(chars)# 主流程cap = cv2.VideoCapture(0)while True:ret, frame = cap.read()plate = detect_plate(frame)if plate is not None:text = recognize_chars(plate)cv2.putText(frame, text, (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)cv2.imshow('LPR', frame)if cv2.waitKey(1) == 27:breakcap.release()
基于OpenCV的车牌识别系统已具备较高的成熟度,但面对复杂场景(如夜间、运动模糊)仍需持续优化。未来方向包括:
通过合理选择算法、优化性能参数,开发者可快速构建满足实际需求的车牌识别系统,为智慧交通、安防监控等领域提供技术支撑。