diff --git a/.gitignore b/.gitignore index e43b0f9..472ab4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .DS_Store +debug_detections +debug_detectionso diff --git a/compare_dirs.py b/compare_dirs.py new file mode 100644 index 0000000..43fa72e --- /dev/null +++ b/compare_dirs.py @@ -0,0 +1,55 @@ +import os +import sys +import argparse + +def compare_directories(dir_a, dir_b): + if not os.path.isdir(dir_a): + print(f"错误: 目录 '{dir_a}' 不存在。") + return + if not os.path.isdir(dir_b): + print(f"错误: 目录 '{dir_b}' 不存在。") + return + + def get_prefix(filename): + if "_frame_" in filename: + return filename.split("_frame_")[0] + return filename + + # 获取文件名到前缀的映射 + files_a_map = {get_prefix(f): f for f in os.listdir(dir_a) if os.path.isfile(os.path.join(dir_a, f))} + files_b_map = {get_prefix(f): f for f in os.listdir(dir_b) if os.path.isfile(os.path.join(dir_b, f))} + + prefixes_a = set(files_a_map.keys()) + prefixes_b = set(files_b_map.keys()) + + only_in_a_prefixes = sorted(list(prefixes_a - prefixes_b)) + only_in_b_prefixes = sorted(list(prefixes_b - prefixes_a)) + both_prefixes = sorted(list(prefixes_a & prefixes_b)) + + print(f"目录 A: {dir_a} (前缀总数: {len(prefixes_a)})") + print(f"目录 B: {dir_b} (前缀总数: {len(prefixes_b)})") + print("-" * 30) + + print(f"只出现在 A 的文件前缀 ({len(only_in_a_prefixes)} 个):") + if only_in_a_prefixes: + for p in only_in_a_prefixes: + print(f" - {files_a_map[p]}") + else: + print(" (无)") + + print(f"\n只出现在 B 的文件前缀 ({len(only_in_b_prefixes)} 个):") + if only_in_b_prefixes: + for p in only_in_b_prefixes: + print(f" - {files_b_map[p]}") + else: + print(" (无)") + + print(f"\n共同出现的前缀: {len(both_prefixes)} 个") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="对比两个目录的文件名差异") + parser.add_argument("dir_a", help="第一个目录路径") + parser.add_argument("dir_b", help="第二个目录路径") + + args = parser.parse_args() + compare_directories(args.dir_a, args.dir_b) diff --git a/video_cleaner.py b/video_cleaner.py index 53660ce..e1e346c 100644 --- a/video_cleaner.py +++ b/video_cleaner.py @@ -1,6 +1,7 @@ import os import sys import subprocess +import time import cv2 import numpy as np from pathlib import Path @@ -14,7 +15,7 @@ except ImportError: sys.exit(1) class VideoCleaner: - def __init__(self, model_path='yolov8n.pt', brightness_threshold=25, age_days=30): + def __init__(self, model_path='yolo26n.pt', brightness_threshold=25, age_days=30): print(f"Initializing YOLO model: {model_path}...") try: self.model = YOLO(model_path) @@ -87,8 +88,8 @@ class VideoCleaner: # Following your rules: "If it's night and no lights, delete". # So we only need to detect humans to justify keeping the video. small_frame = cv2.resize(frame, (640, 360)) - results = self.model(small_frame, classes=[0], verbose=False, conf=0.5) - debugmode=False + results = self.model(small_frame, classes=[0], verbose=False, conf=0.7) + debugmode=True if len(results[0].boxes) > 0: if is_color: # --- DEBUG: Save the frame that triggered detection --- @@ -119,7 +120,7 @@ class VideoCleaner: video_path = Path(video_path).resolve() mtime = datetime.fromtimestamp(os.path.getmtime(video_path)) if datetime.now() - mtime < self.age_limit: - return + return False # 表示因为时间太新没处理 keep, reason = self.should_keep_video(video_path) if keep: @@ -128,6 +129,7 @@ class VideoCleaner: else: print(f"Action: DELETE {video_path.name} - Reason: {reason}") os.remove(video_path) + return True # 表示处理了 def move_to_processed(self, video_path, processed_base_dir, input_base_dir): rel_path = video_path.relative_to(input_base_dir) @@ -140,17 +142,43 @@ class VideoCleaner: input_path = Path(input_dir).resolve() if not input_path.exists(): return processed_dir = input_path.parent / "processed" - for root, dirs, files in os.walk(input_path): - if "processed" in dirs: dirs.remove("processed") - for file in files: - if file.lower().endswith(self.supported_extensions): - self.process_video_file(Path(root) / file, processed_dir, input_path) + + print(f"Scanning {input_path}...") + + while True: + all_videos = [] + # 每次循环都获取最新列表 + for root, dirs, files in os.walk(input_path): + if "processed" in dirs: dirs.remove("processed") + for file in files: + if file.lower().endswith(self.supported_extensions): + full_path = Path(root) / file + all_videos.append(full_path) + + if not all_videos: + print("No more files to process. Exiting.") + break + + # 按修改时间排序,取最旧的一个 + all_videos.sort(key=lambda x: os.path.getmtime(x)) + + processed_in_this_loop = False + for target_file in all_videos: + if self.process_video_file(target_file, processed_dir, input_path): + processed_in_this_loop = True + break # 处理了一个,重新获取列表 + + if not processed_in_this_loop: + # 如果列表里剩下的所有文件都还没到 30 天,那就退出 + print("All remaining files are newer than the age limit. Exiting.") + break if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("dir", help="Target directory") parser.add_argument("--days", type=int, default=30) + parser.add_argument("--model", type=str, default='yolo26n.pt', help="Path to YOLO model or model name") args = parser.parse_args() - cleaner = VideoCleaner(age_days=args.days) + cleaner = VideoCleaner(model_path=args.model, age_days=args.days) cleaner.scan_and_process(args.dir) diff --git a/yolo26n.pt b/yolo26n.pt new file mode 100644 index 0000000..be48188 Binary files /dev/null and b/yolo26n.pt differ