diff --git a/main.py b/main.py index 3bfbfc6..555f93d 100644 --- a/main.py +++ b/main.py @@ -42,6 +42,8 @@ class PlateStabilizer: self.plate_last_seen = {} # 车牌帧计数器,用于跟踪每个车牌被检测的帧数 self.plate_frame_count = {} + # 车牌首次检测时间戳,用于基于时间的帧计数 + self.plate_first_seen = {} def calculate_plate_distance(self, pos1, pos2): """计算两个车牌位置的距离""" @@ -95,11 +97,22 @@ class PlateStabilizer: matched_plates[new_id] = detection self.plate_positions[new_id] = bbox self.plate_last_seen[new_id] = current_time # 设置时间戳 - # 初始化帧计数 + # 初始化帧计数和首次检测时间 self.plate_frame_count[new_id] = 1 + self.plate_first_seen[new_id] = current_time return matched_plates + def is_plate_ready_for_processing(self, plate_id, delay_seconds=0.7): + """检查车牌是否已经过了指定的延迟时间,可以进行处理""" + import time + if plate_id not in self.plate_first_seen: + return False + + current_time = time.time() + first_seen_time = self.plate_first_seen[plate_id] + return (current_time - first_seen_time) >= delay_seconds + def calculate_confidence(self, plate_text, detection_quality=1.0): """计算识别结果的置信度""" if not plate_text or plate_text == "识别失败": @@ -240,6 +253,8 @@ class PlateStabilizer: del self.plate_last_seen[plate_id] if plate_id in self.plate_frame_count: del self.plate_frame_count[plate_id] + if plate_id in self.plate_first_seen: + del self.plate_first_seen[plate_id] class CameraThread(QThread): """摄像头线程类""" @@ -496,6 +511,11 @@ class MainWindow(QMainWindow): # 白名单存储 self.whitelist = set() # 存储白名单车牌号 + # 帧率检测相关 + self.frame_times = deque(maxlen=30) # 存储最近30帧的时间戳 + self.current_fps = 30.0 # 默认帧率 + self.skip_frames_count = 21 # 默认跳过帧数 (0.7秒 * 30fps) + self.init_ui() self.init_detector() self.init_camera() @@ -1056,6 +1076,9 @@ class MainWindow(QMainWindow): self.current_frame = frame.copy() + # 更新帧率计算 + self.update_fps() + # 先显示原始帧,保证视频流畅播放 self.display_frame(frame) @@ -1092,6 +1115,19 @@ class MainWindow(QMainWindow): # 无论成功或失败,都要重置标志位 self.is_processing = False + def update_fps(self): + """更新帧率计算""" + current_time = time.time() + self.frame_times.append(current_time) + + # 如果有足够的帧时间数据,计算帧率 + if len(self.frame_times) >= 2: + time_span = self.frame_times[-1] - self.frame_times[0] + if time_span > 0: + self.current_fps = (len(self.frame_times) - 1) / time_span + # 根据当前帧率计算需要跳过的帧数 (0.7秒) + self.skip_frames_count = max(1, int(self.current_fps * 0.7)) + def draw_detections(self, frame): """在图像上绘制检测结果""" # 获取车牌号列表 @@ -1232,11 +1268,9 @@ class MainWindow(QMainWindow): # 更新车牌数量显示 self.count_label.setText(f"识别到的车牌数量: {len(stable_results)}") - print(f"稳定结果数量: {len(stable_results)}") # 检查结果是否发生变化 results_changed = self.check_results_changed(stable_results) - print(f"结果是否变化: {results_changed}") if results_changed: # 清除之前的结果 @@ -1272,20 +1306,7 @@ class MainWindow(QMainWindow): for frame_id in expired_frame_ids: del self.frame_command_sent[frame_id] - # 清理过期的车牌记录 - 获取当前所有稳定车牌号 - current_plate_numbers = set() - for result in stable_results: - plate_number = result.get('plate_number', '') - if plate_number and plate_number != "识别失败": - current_plate_numbers.add(plate_number) - - # 清理不再出现的车牌记录 - expired_plate_numbers = [plate_number for plate_number in self.plate_records.keys() - if plate_number not in current_plate_numbers] - for plate_number in expired_plate_numbers: - del self.plate_records[plate_number] - - print("结果显示更新完成") + def check_results_changed(self, new_results): """检查识别结果是否发生变化""" @@ -1379,7 +1400,6 @@ class MainWindow(QMainWindow): self.process_frame(self.current_frame) def handle_gate_control(self, stable_results): - """处理道闸控制逻辑""" current_time = datetime.now() @@ -1393,13 +1413,12 @@ class MainWindow(QMainWindow): if not plate_number or plate_number == "识别失败": continue - # 获取该车牌的帧计数,忽略最早的两帧结果 - frame_count = self.plate_stabilizer.plate_frame_count.get(plate_id, 0) - if frame_count <= 2: - print(f"车牌ID: {plate_id} 帧数: {frame_count}, 忽略前两帧") + # 使用基于时间的延迟检查,确保车牌检测到0.7秒后才处理 + if not self.plate_stabilizer.is_plate_ready_for_processing(plate_id, 0.7): + print(f"车牌ID: {plate_id} 尚未达到0.7秒延迟,跳过处理") continue - # 检查该识别框ID是否已经发送过命令 + # 检查该识别框ID是否已经发送过命令(防止同一识别框重复发送) if plate_id in self.frame_command_sent: print(f"识别框ID: {plate_id} 已发送过命令,跳过") continue @@ -1422,32 +1441,32 @@ class MainWindow(QMainWindow): print(f"发送道闸命令失败: {e}") continue + # 白名单车牌的处理逻辑:基于车牌号判断首次/二次识别 if plate_number in self.plate_records: - # 二次识别到同一车牌 + # 二次识别到同一车牌号(出库) record = self.plate_records[plate_number] - if not record['sent']: - # 计算时间间隔 - time_diff = (current_time - record['first_time']).total_seconds() + # 计算时间间隔 + time_diff = (current_time - record['first_time']).total_seconds() + + # 发送时间间隔命令 + message = f"{plate_number} {int(time_diff)}sec" + try: + send_command(1, message) + print(f"发送道闸命令: {message}") - # 发送时间间隔命令 - message = f"{plate_number} {int(time_diff)}sec" - try: - send_command(1, message) - print(f"发送道闸命令: {message}") - - # 标记该识别框ID已发送命令 - self.frame_command_sent[plate_id] = { - 'plate_number': plate_number, - 'command_sent': True - } - - # 标记为已发送并清除记录,使第三次识别时重新按首次处理 - del self.plate_records[plate_number] - - except Exception as e: - print(f"发送道闸命令失败: {e}") + # 标记该识别框ID已发送命令 + self.frame_command_sent[plate_id] = { + 'plate_number': plate_number, + 'command_sent': True + } + + # 清除记录,使第三次识别时重新按首次处理 + del self.plate_records[plate_number] + + except Exception as e: + print(f"发送道闸命令失败: {e}") else: - # 首次识别到车牌 + # 首次识别到车牌号(入库) try: message = f"{plate_number} 通行" send_command(1, message) @@ -1459,7 +1478,7 @@ class MainWindow(QMainWindow): 'command_sent': True } - # 记录车牌信息 + # 记录车牌信息,等待二次识别 self.plate_records[plate_number] = { 'first_time': current_time, 'sent': False