Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a4e3bf3
Create image_object_detection
is-leplus Dec 8, 2025
12a6503
Delete src/image_object_detection
is-leplus Dec 8, 2025
0a15c3f
Create image_object_detection
is-leplus Dec 8, 2025
42d02ad
Delete src/image_object_detection
is-leplus Dec 8, 2025
acb8b4d
Create Image_object_detection
is-leplus Dec 8, 2025
7e0dcb8
Delete src/Image_object_detection
is-leplus Dec 8, 2025
7e26f7d
Create Image_object_detection
is-leplus Dec 8, 2025
17f5843
Delete src/Image_object_detection
is-leplus Dec 8, 2025
b7a579a
Create Image_object_detection
is-leplus Dec 8, 2025
d093821
Delete src/Image_object_detection
is-leplus Dec 8, 2025
e96466e
Create Image_object_detection
is-leplus Dec 8, 2025
044ac8f
Delete src/Image_object_detection
is-leplus Dec 8, 2025
456f8b1
Add files via upload
is-leplus Dec 8, 2025
786d740
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 8, 2025
4f39239
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
989791c
Add files via upload
is-leplus Dec 15, 2025
3c881c1
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
09aeed3
Add files via upload
is-leplus Dec 15, 2025
895adb5
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
7dd7143
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
54e1843
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
556825a
Add files via upload
is-leplus Dec 15, 2025
1e4a806
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
e5faaee
Delete src/image_object_detection/main.py
is-leplus Dec 15, 2025
cbe3f1f
Delete src/image_object_detection/requirements.txt
is-leplus Dec 15, 2025
de9a2d2
Add files via upload
is-leplus Dec 15, 2025
fa4bcfb
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 15, 2025
0c432cd
Delete src/image_object_detection/requirements.txt
is-leplus Dec 15, 2025
d46dbef
Add files via upload
is-leplus Dec 15, 2025
7baa719
Add files via upload
is-leplus Dec 15, 2025
e2c38ed
Update detection_engine.py
is-leplus Dec 15, 2025
43271ab
Update image_detector.py
is-leplus Dec 15, 2025
13fa00c
Create camera_detector.py
is-leplus Dec 15, 2025
f12fb41
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 16, 2025
aa5b42a
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 16, 2025
a85a0bd
Update camera_detector.py
is-leplus Dec 16, 2025
b2ee661
Merge branch 'OpenHUTB:main' into main
is-leplus Dec 16, 2025
4ec40e1
Update main.py
is-leplus Dec 16, 2025
93f4da1
Update image_detector.py
is-leplus Dec 16, 2025
2e4d4a8
Update camera_detector.py
is-leplus Dec 16, 2025
950cf9f
Update ui_handler.py
is-leplus Dec 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 41 additions & 78 deletions src/image_object_detection/camera_detector.py
Original file line number Diff line number Diff line change
@@ -1,110 +1,73 @@
# camera_detector.py
import cv2
import time
import os
import traceback

class CameraDetector:
def __init__(self, detection_engine, camera_index=0):
def __init__(self, detection_engine, output_interval=1.0):
self.engine = detection_engine
self.camera_index = camera_index
self.window_name = "YOLO 实时检测 - 摄像头"
self.output_interval = output_interval
self.last_output_time = 0
self.frame_count = 0
self.window_name = "YOLO_Live_Detection" # 👈 英文窗口名

def detect_camera(self):
"""对外统一接口:启动摄像头实时检测"""
self.start_detection()

def start_detection(self):
"""实际执行摄像头检测的逻辑"""
print("正在初始化摄像头...")
cap = self._open_camera()
if cap is None:
def start_detection(self, camera_index=0):
cap = cv2.VideoCapture(camera_index)
if not cap.isOpened():
print(f"Error: Cannot open camera {camera_index}")
return

cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL)
cv2.resizeWindow(self.window_name, 800, 600)

print("摄像头已启动。按 'q' 或 ESC 退出,按 's' 保存当前帧。")

prev_time = time.time()
saved_frame_index = 0
print("Starting live detection. Press 'q' to quit, 's' to save frame.")
cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL) # 创建一次即可

try:
while True:
ret, frame = cap.read()
if not ret:
print("警告: 无法读取摄像头帧(可能设备被拔出或占用)")
print("Warning: Failed to read frame from camera")
break

annotated_frame, results = self._perform_detection(frame)
if annotated_frame is None:
annotated_frame = frame
current_time = time.time()
annotated_frame, results = self.engine.detect(frame)

curr_time = time.time()
fps = 1.0 / (curr_time - prev_time) if (curr_time - prev_time) > 0 else 0
prev_time = curr_time

num_objects = len(results[0].boxes) if results else 0
info_text = f"FPS: {fps:.1f} | Objects: {num_objects}"
cv2.putText(
annotated_frame,
info_text,
(10, 30),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(0, 255, 0),
2
)
if annotated_frame is None or annotated_frame.size == 0:
print("Warning: Invalid detection result")
continue

cv2.imshow(self.window_name, annotated_frame)

key = cv2.waitKey(1) & 0xFF
if key == ord('q') or key == 27:
print("用户请求退出。")
if key == ord('q'):
break
elif key == ord('s'):
saved_frame_index = self._save_frame(annotated_frame, saved_frame_index)

self.save_frame(annotated_frame)

self._print_fps_if_needed(current_time)
self.frame_count += 1

except KeyboardInterrupt:
print("\nDetection interrupted by user.")
except Exception as e:
print(f"检测过程中发生未预期错误: {e}")
print(f"Unexpected error during detection: {e}")
traceback.print_exc()
finally:
cap.release()
cv2.destroyAllWindows()
print("摄像头已关闭,窗口已清理.")

def _open_camera(self):
cap = cv2.VideoCapture(self.camera_index)
if not cap.isOpened():
print(f"错误: 无法打开摄像头(索引 {self.camera_index})")
print("请检查摄像头是否连接、是否被其他程序占用。")
return None

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
return cap

def _perform_detection(self, frame):
try:
# 抑制 YOLO 内部输出
import sys, os
old_stdout = sys.stdout
sys.stdout = open(os.devnull, 'w')
annotated_frame, results = self.engine.detect(frame)
sys.stdout = old_stdout
return annotated_frame, results
except Exception as e:
print(f"单帧检测失败: {e}")
return None, []

def _save_frame(self, frame, index):
save_dir = "saved_frames"
os.makedirs(save_dir, exist_ok=True)
filename = os.path.join(save_dir, f"frame_{index:04d}.jpg")
print("Camera released and windows closed.")

def _print_fps_if_needed(self, current_time):
if current_time - self.last_output_time >= self.output_interval:
fps = self.frame_count / (current_time - self.last_output_time) if self.last_output_time > 0 else 0
print(f"FPS: {fps:.2f}")
self.last_output_time = current_time
self.frame_count = 0

def save_frame(self, frame):
import os
timestamp = int(time.time())
filename = f"saved_frame_{timestamp}.jpg"
success = cv2.imwrite(filename, frame)
if success:
print(f"✅ 帧已保存: {filename}")
return index + 1
print(f"Frame saved as {filename}")
else:
print("❌ 保存帧失败!")
return index
print("Failed to save frame")
86 changes: 20 additions & 66 deletions src/image_object_detection/image_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,111 +2,65 @@
import cv2
import numpy as np
import traceback
import os

class ImageDetector:
def __init__(self, detection_engine):
self.engine = detection_engine

def detect_static_image(self, image_path):
"""检测静态图像"""
print(f"正在加载图像: {image_path}")
print(f"Loading image: {image_path}")

if not self._check_image_exists(image_path):
if not os.path.exists(image_path):
print(f"Error: Image file not found - {image_path}")
return

frame = self._load_image(image_path)
frame = cv2.imread(image_path)
if frame is None or frame.size == 0:
print("错误: 无法读取图像文件或图像为空")
print("Error: Failed to load image")
return

print("正在检测图像...")
results, annotated_frame = self._perform_detection(frame)
print("Running detection...")
annotated_frame, results = self.engine.detect(frame)

if annotated_frame is None:
print("错误: 检测未返回有效图像")
if annotated_frame is None or annotated_frame.size == 0:
print("Error: Invalid annotated frame")
return

# 显示检测结果文本
self._display_results(results)

# 显示图像窗口(带固定初始大小)
self._show_image(annotated_frame, 'YOLO 检测结果 - 静态图像')

def _check_image_exists(self, image_path):
import os
if not os.path.exists(image_path):
print(f"错误: 图像文件不存在 - {image_path}")
return False
return True

def _load_image(self, image_path):
try:
with open(image_path, "rb") as f:
bytes_data = bytearray(f.read())
nparr = np.frombuffer(bytes_data, np.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
return frame
except Exception as e:
print(f"加载图像时出错: {e}")
return None

def _perform_detection(self, frame):
try:
annotated_frame, results = self.engine.detect(frame)
return results, annotated_frame
except Exception as e:
print(f"检测过程中发生错误: {e}")
traceback.print_exc()
return [], None
self._show_image(annotated_frame, "YOLO_Static_Detection")

def _display_results(self, results):
if not results:
print("未检测到任何对象(results 为空)")
print("No objects detected.")
return

result = results[0]
boxes = result.boxes
if len(boxes) == 0:
print("未检测到任何对象")
print("No objects detected.")
return

print("检测完成,正在显示结果...")
print(f"检测到 {len(boxes)} 个对象:")

print(f"Detected {len(boxes)} object(s):")
names_list = self.engine.model.names

for i, box in enumerate(boxes):
try:
cls_index = int(box.cls.item())
confidence = box.conf.item()

if 0 <= cls_index < len(names_list):
cls_name = names_list[cls_index]
else:
cls_name = f"unknown_class_{cls_index}"
print(f" ⚠️ 警告:类别索引 {cls_index} 超出范围(共 {len(names_list)} 类)")

print(f" {i+1}. {cls_name} (置信度: {confidence:.2f})")
cls_name = names_list[cls_index] if 0 <= cls_index < len(names_list) else f"unknown_{cls_index}"
print(f" {i+1}. {cls_name} (confidence: {confidence:.2f})")
except Exception as e:
print(f" ⚠️ 解析第 {i+1} 个检测框时出错: {e}")
print(f" Warning: Failed to parse box {i+1}: {e}")

def _show_image(self, annotated_frame, window_name):
"""显示图像,并设置窗口为可调整的小尺寸"""
if annotated_frame is None or annotated_frame.size == 0:
print("错误: 标注帧无效,无法显示")
return

print("\n图像已显示。按任意键关闭窗口...")
def _show_image(self, annotated_frame, window_name="YOLO_Static_Detection"):
try:
# 创建可调整大小的窗口
cv2.destroyAllWindows()
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
# 设置初始窗口大小为 800x600(你可以按需修改)
cv2.resizeWindow(window_name, 800, 600)
# 显示图像(OpenCV 会自动适应窗口)
cv2.imshow(window_name, annotated_frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
print("窗口已关闭。")
except Exception as e:
print(f"显示图像时发生错误: {e}")
print(f"Failed to display image: {e}")
traceback.print_exc()
5 changes: 4 additions & 1 deletion src/image_object_detection/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# main.py
import matplotlib
matplotlib.use('Agg') # 必须在最前,禁用 GUI 后端

from ui_handler import UIHandler
from config import Config

Expand All @@ -8,4 +11,4 @@ def main():
ui_handler.run()

if __name__ == "__main__":
main()
main()
Loading
Loading