You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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()

四、关键细节说明

  1. 车牌跟踪机制:通过前后帧的车牌列表对比,精准判断车牌是否离开视野,避免重复记录
  2. 预处理效果:自适应二值化适配不同光照场景,形态学操作强化字符轮廓,大幅提升OCR识别准确率
  3. Excel数据安全:车牌离开时立即写入数据,程序退出时自动处理剩余数据,防止数据丢失
  4. Tesseract配置:字符白名单过滤干扰项,单行识别模式适配车牌的文本布局

内容的提问来源于stack exchange,提问作者s0ld13r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:48:28