计算机视觉车牌检测存储项目:单车牌重复抓拍问题求助
车牌检测重复抓拍问题解决
我正在进行计算机视觉方向的项目,需实现车辆车牌检测、抓拍并将图片存储至指定文件夹。编写的代码逻辑为:当车牌目标完全进入矩形框时,脚本会抓拍并存储该图片。但目前遇到问题:单个车牌目标会被重复抓拍并存储多张图片。
解决方案思路
要解决重复抓拍问题,核心是跟踪车牌目标的进入状态——只有当车牌从"不在框内"变为"进入框内"的瞬间才触发抓拍,而非只要在框内就持续触发。这里采用状态标记+唯一标识的方案,确保同一车牌仅被抓拍一次。
修改后的完整代码
import cv2 import os from ultralytics import YOLO # 源视频文件路径 video_path = 'sample.mp4' # 存储抓拍图片的目录 output_directory = 'captured_images' os.makedirs(output_directory, exist_ok=True) # 使用训练好的模型创建YOLO对象 yolo = YOLO('./models/license_plate_detector.pt') # 替换为你的训练权重实际路径 # 创建VideoCapture对象 cap = cv2.VideoCapture(video_path) # 检查视频是否成功打开 if not cap.isOpened(): print("Error: Could not open video.") exit() # 获取视频属性 frame_width = int(cap.get(3)) frame_height = int(cap.get(4)) aspect_ratio = frame_width / frame_height # 设置窗口大小以匹配视频宽高比 window_height = 768 window_width = int(window_height * aspect_ratio) cv2.namedWindow("Video with Rectangle", cv2.WINDOW_NORMAL) cv2.resizeWindow("Video with Rectangle", window_width, window_height) # 矩形框的坐标与尺寸 x, y, width, height = 2200, 1600, 700, 100 # 存储已抓拍过的车牌标识,避免重复抓拍 captured_plates = set() image_counter = 1 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 使用训练好的YOLO模型检测目标 results = yolo(frame) # 获取检测框 detected_boxes = results[0].boxes.xyxy # 检测框格式:xmin, ymin, xmax, ymax # 记录当前帧中在框内的车牌标识 current_in_box = set() for box in detected_boxes: x_min, y_min, x_max, y_max = box[:4] center_x = (x_min + x_max) / 2 center_y = (y_min + y_max) / 2 # 生成车牌唯一标识(用中心坐标取整哈希,避免浮点精度问题) plate_id = (int(center_x // 10), int(center_y // 10)) # 检查是否在触发框内 if x < center_x < x + width and y < center_y < y + height: current_in_box.add(plate_id) # 仅对未抓拍过的车牌执行存储 if plate_id not in captured_plates: # 截取检测到的目标区域 object_frame = frame[int(y_min):int(y_max), int(x_min):int(x_max)] # 保存目标图片 image_filename = os.path.join(output_directory, f"captured_object_{image_counter}.jpg") cv2.imwrite(image_filename, object_frame) print(f"已抓拍并存储: {image_filename}") image_counter += 1 # 标记该车牌为已抓拍 captured_plates.add(plate_id) else: # 车牌离开框内时移除标记,支持后续再次进入时抓拍(可选) if plate_id in captured_plates: captured_plates.remove(plate_id) # 在帧上绘制矩形框 cv2.rectangle(frame, (x, y), (x + width, y + height), (0, 255, 0), 2) # 显示帧 cv2.imshow("Video with Rectangle", frame) # 按下'q'键退出循环 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放视频捕获对象 cap.release() # 关闭所有窗口 cv2.destroyAllWindows()
关键改动说明
- 新增
captured_plates集合:存储已抓拍车牌的唯一标识,防止重复触发。 - 生成
plate_id:用车牌中心坐标取整哈希作为唯一标识,解决浮点精度导致的重复识别问题。 - 状态判断逻辑:仅当车牌首次进入框内且未被抓拍时执行存储;车牌离开框内时可移除标记,支持再次进入时抓拍(可根据需求关闭此逻辑)。
- 可选优化:若需更精准的目标跟踪,可改用YOLO的跟踪模式(
yolo.track()),直接使用模型返回的id作为plate_id,确保移动中的车牌被准确识别为同一目标。
内容的提问来源于stack exchange,提问作者Rajkumar
相关产品推荐
相关产品推荐

