最近接到一个项目,需要从几万个零散的视频中提取有人走动的的内容保存为图片,方便查找线索。
这对于python的cv2加上YoLo8模型,简直不要太好用,先测试一个文件,然后批量调用就行。

下载示例文件:video.zip (10MB),把这个压缩包里的文件解压到C盘根目录,执行video/video.bat或者手动运行下面的命令
命令:python c:/video/video.py c:/video/20210305.mp4 c:/video

链接:https://caiyun.139.com/w/i/2pU95BMDyRc86
提取码:037q

需要用到的组件,python版本3.10,其它版本可能不兼容,需要排错
最好先更新一下pip(建议)
python.exe -m pip install –upgrade pip

安装OpenCV (cv2,必须)
用于视频处理和图像操作。
安装命令:pip install opencv-python==4.8.0.76
Ultralytics YOLO(必须)
提供 YOLOv8 模型支持。
安装命令:pip install ultralytics       (大概需下载好几百兆的文件,没有国外加速会下很久很久。。。)
PyTorch
YOLOv8 的深度学习框架依赖。

如果需要显卡CUDA加速,需要安装(文件很大。。。。,我不装了)

python.exe -m pip install torch torchvision torchaudio –index-url https://download.pytorch.org/whl/cu118

这几个组件版本分别如下,版本不兼容可能会导致CUDA无法运行:

numpy 1.26.4
opencv-python 4.8.0.76
torch 2.2.0+cu118
torchvision 0.17.0+cu118
ultralytics 8.2.89 

import sys
import os
import cv2
from ultralytics import YOLO
import torch

def analyze_video_yolo(video_path, output_dir, save_interval_sec=1, min_confidence=0.5):
    if not os.path.exists(video_path):
        print(f"视频文件 {video_path} 不存在")
        return
    try:
        os.makedirs(output_dir, exist_ok=True)
        test_file = os.path.join(output_dir, "test.txt")
        with open(test_file, 'w') as f:
            f.write("test")
        os.remove(test_file)
    except Exception as e:
        print(f"输出目录 {output_dir} 不可写: {e}")
        return
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print(f"无法打开视频:{video_path}")
        return
    fps = cap.get(cv2.CAP_PROP_FPS)
    if fps == 0:
        print("无法获取视频FPS,默认30")
        fps = 30
    save_interval_frames = int(fps * save_interval_sec)
    if torch.cuda.is_available():
        device = 'cuda'
        print("使用 GPU(CUDA)进行人体检测")
    else:
        device = 'cpu'
        print("未检测到可用的 GPU,将使用 CPU 进行人体检测")
    try:
        model = YOLO("yolov8n.pt")
    except Exception as e:
        print(f"模型加载失败: {e}")
        return

    frame_count = 0
    saved_count = 0

    print(f"开始分析视频: {video_path},FPS: {fps:.2f}")

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        # 每隔一定帧检测一次并保存(如果检测到人)
        if frame_count % save_interval_frames == 0:
            results = model(frame, device=device)[0]

            person_boxes = [
                box for box in results.boxes
                if int(box.cls) == 0 and box.conf.item() > min_confidence
            ]

            if person_boxes:
                output_path = os.path.join(output_dir, f"frame_{frame_count}.jpg")
                try:
                    cv2.imwrite(output_path, frame)
                    saved_count += 1
                    print(f"[帧 {frame_count}] 检测到 {len(person_boxes)} 人体,保存整帧截图")
                except Exception as e:
                    print(f"保存图像失败: {e}")

        # 绘制检测框用于显示
        results = model(frame, device=device)[0]
        for box in results.boxes:
            if int(box.cls) == 0 and box.conf.item() > min_confidence:
                x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
                conf = box.conf.item()
                cv2.putText(frame, f"Person {conf:.2f}", (x1, y1 - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)

        cv2.imshow("YOLOv8 Detection", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            print("检测中止,手动退出。")
            break

        frame_count += 1

    cap.release()
    cv2.destroyAllWindows()
    print(f"完成!总帧数: {frame_count},保存截图: {saved_count}")

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("用法: python video_yolo.py [视频路径] [输出目录] [可选:截图间隔秒数(默认1秒)]")
        sys.exit(1)

    video_path = sys.argv[1]
    output_dir = sys.argv[2]
    interval_sec = float(sys.argv[3]) if len(sys.argv) > 3 else 1

    analyze_video_yolo(video_path, output_dir, interval_sec)

By OO不OO

发表回复