python实现mp4视频生成关键帧九宫格画布图片代码

代码语言:python

所属分类:其他

代码描述:python实现mp4视频生成关键帧九宫格画布图片代码,抽取视频中关键帧图片拼凑成多宫格的一张图片。

代码标签: python mp4 视频 生成 关键帧 九宫格 画布 图片 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

#!/usr/bin/env python3
"""
视频关键帧多宫格截图工具
支持: 均匀采样 / 场景变化检测 / I帧提取
输出: 九宫格(3x3)或自定义多宫格排列的合成图片
"""

import cv2
import numpy as np
import os
import argparse
from math import ceil, sqrt
from datetime import timedelta


# ============================================================
# 1. 关键帧提取模块
# ============================================================

def extract_keyframes_uniform(video_path, num_frames=9):
    """均匀采样: 按时间均匀提取指定数量的帧"""
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        raise ValueError(f"无法打开视频: {video_path}")

    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = cap.get(cv2.CAP_PROP_FPS)

    if total_frames <= 0 or fps <= 0:
        cap.release()
        raise ValueError("无法读取视频帧信息")

    # 避免首尾黑帧, 取中间 10%~90% 区间
    start_frame = int(total_frames * 0.05)
    end_frame = int(total_frames * 0.95)
    usable_frames = end_frame - start_frame

    if usable_frames <= num_frames:
        # 视频太短, 逐帧提取
        indices = list(range(total_frames))
    else:
        interval = usable_frames / (num_frames + 1)
        indices = [int(start_frame + interval * (i + 1)) for i in range(num_frames)]

    frames = []
    for idx in indices:
        cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
        ret, frame = cap.read()
        if ret:
            timestamp = idx / fps
            frames.append({
                'frame': frame,
                'frame_idx': idx,
                'timestamp': timestamp,
                'time_str': _format_time(timestamp),
            })

    cap.release()
    return frames


def extract_keyframes_scene(video_path, num_frames=9, threshold=25.0):
    """场景变化检测: 当画面发生显著变化时提取关键帧"""
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        raise ValueError(f"无法打开视频: {video_path}")

    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = cap.get(cv2.CAP_PROP_FPS)

    all_changes = []
    prev_gray = None
    frame_idx = 0

    # 第一步: 遍历全片, 记录所有场景变化点
    while True:
        ret, frame = cap.read()
        if not ret:
            break

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (21, 21), 0)

        if prev_gray is not None:
            diff = cv2.absdiff(prev_gray, gray)
            score = np.mean(diff)
           .........完整代码请登录后点击上方下载按钮下载查看

网友评论0