支持本地视频测试
This commit is contained in:
z66
2025-12-23 17:59:18 +08:00
parent ae9d252255
commit 1a135cdda7
9 changed files with 301 additions and 14 deletions
+96
View File
@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
"""
离线视频检测与告警验证脚本
用法示例:
python test_video.py --video sample.mp4
python test_video.py --video sample.mp4 --output result.mp4
按下 `q` 可中途退出。
"""
import argparse
import cv2
from datetime import datetime
from fish_tracker import FishTracker
from history_manager import FishHistoryManager
def run(video_path: str, output_path: str | None, report_path: str | None):
tracker = FishTracker()
history = FishHistoryManager()
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise RuntimeError(f"无法打开视频文件:{video_path}")
writer = None
if output_path:
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
fps = cap.get(cv2.CAP_PROP_FPS) or 25
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
writer = cv2.VideoWriter(output_path, fourcc, fps, (w, h))
try:
while True:
ret, frame = cap.read()
# 读取失败:可能是到结尾,也可能是坏帧,先尝试继续几次
if not ret or frame is None:
# 到达文件末尾:直接退出
if not ret:
break
# 否则跳过本帧
print("警告:读取到空帧,跳过。")
continue
# 防御性检查:帧尺寸异常也跳过
h, w = frame.shape[:2]
if h == 0 or w == 0:
print("警告:帧尺寸异常,跳过。")
continue
# 个别帧解码失败时,YOLO/DeepSORT 可能抛异常,这里捕获并跳过
try:
output_frame, alerts, track_stats = tracker.process_frame(frame)
except Exception as e:
print(f"警告:处理当前帧时出错,已跳过。错误信息:{e}")
continue
now = datetime.now()
history.update(track_stats, now)
# 显示结果
if alerts:
print("; ".join(alerts))
cv2.imshow("fish monitor (press q to exit)", output_frame)
if writer:
writer.write(output_frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
finally:
cap.release()
if writer:
writer.release()
if report_path:
# 结束后生成一次离线报告
out = history.generate_report()
print(f"报告已生成:{out}")
cv2.destroyAllWindows()
def parse_args():
parser = argparse.ArgumentParser(description="离线视频检测验证脚本")
parser.add_argument("--video", required=True, help="待检测的视频文件路径")
parser.add_argument("--output", help="可选,保存标注结果的视频路径")
parser.add_argument("--report", action="store_true", help="视频结束后生成报告(reports/ 下)")
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()
report_path = "reports/fish_report_offline.txt" if args.report else None
run(args.video, args.output, report_path)