import cv2 from utils.get_image import GetImage from ultralytics import YOLO from config import config_manager import os # 检查模型文件是否存在 model_path = r"best0.pt" if not os.path.exists(model_path): print(f"❌ 模型文件不存在: {model_path}") exit(1) # 加载YOLO模型 try: model = YOLO(model_path).to('cuda') print(f"✅ 模型加载成功: {model_path}") except Exception as e: print(f"❌ 模型加载失败: {e}") exit(1) def yolo_shibie(im_PIL, im_opencv_rgb, raw_frame_bgr, detections, model, show_original=True): """ YOLO识别函数 :param im_PIL: PIL图像对象 :param im_opencv_rgb: RGB格式的OpenCV图像(裁剪后) :param raw_frame_bgr: 原始BGR格式的OpenCV图像(未裁剪,与raw_frame.jpg一致) :param detections: 检测结果字典 :param model: YOLO模型 :param show_original: 是否同时显示原始帧 :return: 更新后的detections字典,如果用户退出则返回None """ if im_PIL is None: return detections try: results = model(im_PIL) result = results[0] # ✅ 获取绘制好框的图像(RGB格式) frame_with_boxes_rgb = result.plot() # ✅ 转换为BGR格式用于OpenCV显示 frame_with_boxes_bgr = cv2.cvtColor(frame_with_boxes_rgb, cv2.COLOR_RGB2BGR) # 显示画面 if show_original and raw_frame_bgr is not None: # 同时显示原始帧和检测结果(并排显示) # 调整原始帧大小以匹配裁剪后的检测结果 h, w = frame_with_boxes_bgr.shape[:2] # 裁剪原始帧(与get_frame的处理一致:30:30+720, 0:1280) raw_height, raw_width = raw_frame_bgr.shape[:2] crop_top = 30 crop_bottom = min(crop_top + h, raw_height) crop_right = min(w, raw_width) raw_cropped = raw_frame_bgr[crop_top:crop_bottom, 0:crop_right] # 如果尺寸不匹配,调整原始帧大小 if raw_cropped.shape[:2] != (h, w): raw_cropped = cv2.resize(raw_cropped, (w, h)) # 并排显示:原始帧(左) | 检测结果(右) # 原始帧已经是BGR格式,检测结果也是BGR格式,可以直接拼接 combined = cv2.hconcat([raw_cropped, frame_with_boxes_bgr]) cv2.imshow("原始帧 (左, 与raw_frame.jpg一致) | YOLO检测结果 (右)", combined) else: # 只显示检测结果 cv2.imshow("YOLO实时检测", frame_with_boxes_bgr) # ✅ 提取检测信息 if result.boxes is not None and len(result.boxes.xyxy) > 0: for i in range(len(result.boxes.xyxy)): try: left = float(result.boxes.xyxy[i][0]) top = float(result.boxes.xyxy[i][1]) right = float(result.boxes.xyxy[i][2]) bottom = float(result.boxes.xyxy[i][3]) cls_id = int(result.boxes.cls[i]) label = result.names[cls_id] if label in ['center', 'next', 'npc1', 'npc2', 'npc3', 'npc4', 'boss', 'zhaozi']: player_x = int(left + (right - left) / 2) + 3 player_y = int(top + (bottom - top) / 2) + 40 detections[label] = [player_x, player_y] elif label in ['daojv', 'gw']: player_x = int(left + (right - left) / 2) + 3 player_y = int(top + (bottom - top) / 2) + 40 # 确保列表存在 if label not in detections: detections[label] = [] detections[label].append([player_x, player_y]) except Exception as e: print(f"⚠️ 处理检测框时出错: {e}") continue except Exception as e: print(f"⚠️ YOLO检测出错: {e}") return detections def main(): """主函数""" print("="*60) print("YOLO实时检测测试") print("="*60) # 从配置加载采集卡设置 active_group = config_manager.get_active_group() if active_group is None: print("⚠️ 没有活动的配置组,使用默认设置") print("提示: 可以运行 python gui_config.py 设置配置") cam_index = 0 width = 1920 height = 1080 else: print(f"📋 使用配置组: {active_group['name']}") cam_index = active_group['camera_index'] width = active_group['camera_width'] height = active_group['camera_height'] print(f" 采集卡索引: {cam_index}") print(f" 分辨率: {width}x{height}") print() # 初始化采集卡 print("🔧 正在初始化采集卡...") get_image = GetImage( cam_index=cam_index, width=width, height=height ) if get_image.cap is None: print("❌ 采集卡初始化失败") print("请检查:") print("1. 采集卡是否正确连接") print("2. 采集卡索引是否正确") print("3. 采集卡驱动是否安装") return print("✅ 采集卡初始化成功") print("按 'q' 或 ESC 键退出测试") print() try: frame_count = 0 show_original = True # 默认同时显示原始帧和检测结果 print("提示: 按 'o' 键切换是否显示原始帧对比") print() while True: # 获取帧 frame_data = get_image.get_frame() if frame_data is None: print("⚠️ 无法获取帧,跳过...") continue # frame_data 是 [im_opencv_rgb, im_PIL] 格式 # im_opencv_rgb 已经是RGB格式(经过BGR2RGB转换) im_opencv_rgb, im_PIL = frame_data if im_PIL is None: print("⚠️ PIL图像为空,跳过...") continue # 获取原始BGR帧(与test_capture_card.py保存的raw_frame.jpg一致) raw_frame_bgr = None if get_image.cap is not None and get_image.frame is not None: raw_frame_bgr = get_image.frame.copy() # 原始BGR格式,未裁剪 # 初始化检测结果字典 detections = { 'center': None, 'next': None, 'npc1': None, 'npc2': None, 'npc3': None, 'npc4': None, 'boss': None, 'zhaozi': None, 'daojv': [], 'gw': [] } # 执行YOLO检测 detections = yolo_shibie(im_PIL, im_opencv_rgb, raw_frame_bgr, detections, model, show_original) # 检查按键 key = cv2.waitKey(1) & 0xFF if key in [27, ord('q'), ord('Q')]: print("\n用户退出") break elif key == ord('o') or key == ord('O'): show_original = not show_original print(f"切换显示模式: {'原始帧对比' if show_original else '仅检测结果'}") frame_count += 1 if frame_count % 30 == 0: # 每30帧打印一次 print(f"📊 已处理 {frame_count} 帧") # 打印有检测到的目标 detected_items = {k: v for k, v in detections.items() if v is not None and v != []} if detected_items: print(f" 检测到: {detected_items}") except KeyboardInterrupt: print("\n\n用户中断测试") except Exception as e: print(f"\n❌ 测试过程中发生错误: {e}") import traceback traceback.print_exc() finally: # 清理资源 get_image.release() cv2.destroyAllWindows() print("🔚 测试结束") if __name__ == "__main__": main()