如何用Python OpenCV实现车牌检测的时间记录、Excel存储及OCR优化
解决方案
一、Excel存储逻辑实现
要完成车牌进出时间与停留时长的记录,需通过状态跟踪字典实现核心逻辑:
- 用字典
current_plates保存当前视野内的车牌,键为车牌号码,值为首次检测的时间和日期 - 每帧对比前后两次检测到的车牌列表,找出消失的车牌(已离开视野),计算停留时长并写入Excel
- 程序退出时,自动处理仍在视野中的车牌,避免数据丢失
二、OCR准确率优化
车牌识别准确率低的核心问题是图像预处理不足,可通过以下步骤优化:
- 自适应二值化:解决光照不均导致的字符与背景对比度低的问题
- 形态学膨胀:填补字符的微小缺口,让字符轮廓更连贯
- Tesseract参数定制:限制识别字符范围(仅大写字母+数字),指定单行文本识别模式
pytesseract优化参数示例:
custom_config = r'--oem 3 --psm 8 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 '
参数说明:
--oem 3:使用默认OCR引擎模式--psm 8:将图像视为单个单词,适配单行车牌字符tessedit_char_whitelist:过滤无关字符,只识别目标范围内的内容
三、完整代码实现
import cv2 from openpyxl import Workbook, load_workbook import os import pytesseract from datetime import datetime # 设置Tesseract安装路径(根据你的实际路径调整) pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' # 加载车牌级联分类器 plate_cascade = cv2.CascadeClassifier('C:/Users/35568/PycharmProjects/pythonProject1/venv/Lib/site-packages/cv2/data/haarcascade_russian_plate_number.xml') # 启动前置摄像头 cap = cv2.VideoCapture(0) min_area = 500 # 初始化Excel文件路径 desktop = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop') filename = os.path.join(desktop, 'plates.xlsx') # 加载或创建Excel工作簿 try: wb = load_workbook(filename) ws = wb.active except FileNotFoundError: wb = Workbook() ws = wb.active ws.append(['Plate', 'Date', 'Start Time', 'End Time', 'Duration']) # 跟踪当前视野中的车牌:{车牌号码: (首次检测时间, 日期)} current_plates = {} # 存储上一帧检测到的车牌,用于对比消失的车牌 last_detected_plates = [] def preprocess_plate(img): """车牌图像预处理,提升OCR识别率""" # 高斯模糊降噪 img_blur = cv2.GaussianBlur(img, (5,5), 0) # 自适应二值化,处理光照不均 thresh = cv2.adaptiveThreshold(img_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 形态学膨胀,填补字符缺口 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2)) processed_img = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel) return processed_img def calculate_duration(start_time, end_time): """计算停留时长,返回hh:mm:ss格式""" start = datetime.strptime(start_time, "%H:%M:%S") end = datetime.strptime(end_time, "%H:%M:%S") delta = end - start total_seconds = delta.total_seconds() hours = int(total_seconds // 3600) minutes = int((total_seconds % 3600) // 60) seconds = int(total_seconds % 60) return f"{hours:02d}:{minutes:02d}:{seconds:02d}" while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) plates = plate_cascade.detectMultiScale(gray, 1.1, 4) current_frame_plates = [] for (x, y, w, h) in plates: area = w * h if area > min_area: # 绘制车牌检测框 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 裁剪并预处理车牌图像 plate_img = gray[y:y + h, x:x + w] processed_plate = preprocess_plate(plate_img) cv2.imshow("Processed Plate", processed_plate) # OCR识别车牌文本 custom_config = r'--oem 3 --psm 8 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ' plate_text = pytesseract.image_to_string(processed_plate, config=custom_config).strip() if plate_text: current_frame_plates.append(plate_text) # 首次检测到该车牌,记录时间 if plate_text not in current_plates: now = datetime.now() current_plates[plate_text] = (now.strftime("%H:%M:%S"), now.strftime("%Y-%m-%d")) # 找出已离开视野的车牌 left_plates = [plate for plate in last_detected_plates if plate not in current_frame_plates] for plate in left_plates: if plate in current_plates: start_time, date = current_plates.pop(plate) end_time = datetime.now().strftime("%H:%M:%S") duration = calculate_duration(start_time, end_time) # 写入Excel并保存 ws.append([plate, date, start_time, end_time, duration]) wb.save(filename) print(f"已记录车牌 {plate} 的进出信息") # 更新上一帧的车牌列表 last_detected_plates = current_frame_plates.copy() cv2.imshow('Video', frame) key = cv2.waitKey(25) if key == ord('q') or key == 27: # 退出时处理仍在视野中的车牌 for plate in current_plates: start_time, date = current_plates[plate] end_time = datetime.now().strftime("%H:%M:%S") duration = calculate_duration(start_time, end_time) ws.append([plate, date, start_time, end_time, duration]) wb.save(filename) break if cv2.getWindowProperty('Video', cv2.WND_PROP_VISIBLE) < 1: # 窗口关闭时保存数据 for plate in current_plates: start_time, date = current_plates[plate] end_time = datetime.now().strftime("%H:%M:%S") duration = calculate_duration(start_time, end_time) ws.append([plate, date, start_time, end_time, duration]) wb.save(filename) break cap.release() cv2.destroyAllWindows()
四、关键细节说明
- 车牌跟踪机制:通过前后帧的车牌列表对比,精准判断车牌是否离开视野,避免重复记录
- 预处理效果:自适应二值化适配不同光照场景,形态学操作强化字符轮廓,大幅提升OCR识别准确率
- Excel数据安全:车牌离开时立即写入数据,程序退出时自动处理剩余数据,防止数据丢失
- Tesseract配置:字符白名单过滤干扰项,单行识别模式适配车牌的文本布局
内容的提问来源于stack exchange,提问作者s0ld13r
相关产品推荐
相关产品推荐

