Spaces:
Running
Running
File size: 3,935 Bytes
1fec9bd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#### pip install imagehash
#### python noinstance_v2i.py 翠星测试.mp4 翠星图片
#### python noinstance_v2i.py 翠星测试.mp4 翠星图片25_0_1
import os
import cv2
import argparse
import shutil
import imagehash
from pathlib import Path
from tqdm import tqdm
from moviepy.editor import VideoFileClip
from collections import deque
from PIL import Image
from animeinsseg import AnimeInsSeg
# 配置参数
CKPT_PATH = "models/AnimeInstanceSegmentation/rtmdetl_e60.ckpt"
DOWNSAMPLE_SIZE = (320, 180) # 下采样尺寸提升处理速度
MIN_SCENE_CHANGE = 0.3 # 场景变化阈值 (0-1)
HASH_THRESHOLD = 25 # 哈希相似度阈值
FRAME_BUFFER = 10 # 连续帧缓冲区
class VideoProcessor:
def __init__(self):
self.net = AnimeInsSeg(
CKPT_PATH,
mask_thr=0.1,
refine_kwargs={'refine_method': 'refinenet_isnet'}
)
self.hash_dict = {}
self.last_saved_hash = None
def _preprocess_frame(self, frame):
"""预处理帧:下采样 + 灰度化"""
small_frame = cv2.resize(frame, DOWNSAMPLE_SIZE)
return cv2.cvtColor(small_frame, cv2.COLOR_BGR2GRAY)
def _has_human(self, frame):
"""快速人物检测"""
instances = self.net.infer(
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB),
output_type='numpy',
pred_score_thr=0.5 # 适当提高置信度阈值加速判断
)
return instances.bboxes is not None
def _is_duplicate(self, frame):
"""基于感知哈希的去重检测"""
current_hash = imagehash.dhash(Image.fromarray(frame))
for existing_hash in self.hash_dict.values():
if current_hash - existing_hash < HASH_THRESHOLD:
return True
return False
def process_video(self, video_path, output_dir):
"""核心处理流程"""
clip = VideoFileClip(str(video_path))
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
# 初始化场景检测
prev_frame = None
frame_buffer = deque(maxlen=FRAME_BUFFER)
for i, frame in enumerate(clip.iter_frames()):
# 转换为OpenCV格式
cv_frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
# 动态抽帧策略
processed_frame = self._preprocess_frame(cv_frame)
if prev_frame is not None:
# 使用结构相似性检测场景变化
similarity = cv2.compareHist(
cv2.calcHist([processed_frame], [0], None, [256], [0, 256]),
cv2.calcHist([prev_frame], [0], None, [256], [0, 256]),
cv2.HISTCMP_CORREL
)
if similarity > (1 - MIN_SCENE_CHANGE):
continue
prev_frame = processed_frame
# 缓冲区去重检测
if any(cv2.absdiff(processed_frame, f).sum() < 1000 for f in frame_buffer):
continue
frame_buffer.append(processed_frame)
# 执行人物检测
if not self._has_human(cv_frame):
# 哈希去重检查
if not self._is_duplicate(frame):
frame_hash = imagehash.dhash(Image.fromarray(frame))
self.hash_dict[i] = frame_hash
cv2.imwrite(str(output_path / f"frame_{i:06d}.jpg"), cv_frame)
clip.close()
def main():
parser = argparse.ArgumentParser(description="提取视频中无人物出现的帧")
parser.add_argument("video_path", type=str, help="输入视频路径")
parser.add_argument("output_dir", type=str, help="输出目录路径")
args = parser.parse_args()
processor = VideoProcessor()
processor.process_video(args.video_path, args.output_dir)
if __name__ == "__main__":
main()
|