再次修复了车牌判断的bug

This commit is contained in:
2025-10-19 20:21:21 +08:00
parent 40f5e1c1be
commit a99e8fccb2

103
main.py
View File

@@ -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
}
# 标记该识别框ID已发送命令
self.frame_command_sent[plate_id] = {
'plate_number': plate_number,
'command_sent': True
}
# 标记为已发送并清除记录,使第三次识别时重新按首次处理
del self.plate_records[plate_number]
# 清除记录,使第三次识别时重新按首次处理
del self.plate_records[plate_number]
except Exception as e:
print(f"发送道闸命令失败: {e}")
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