update yolov26
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
debug_detections
|
||||||
|
debug_detectionso
|
||||||
|
|||||||
55
compare_dirs.py
Normal file
55
compare_dirs.py
Normal file
@@ -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)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import time
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -14,7 +15,7 @@ except ImportError:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
class VideoCleaner:
|
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}...")
|
print(f"Initializing YOLO model: {model_path}...")
|
||||||
try:
|
try:
|
||||||
self.model = YOLO(model_path)
|
self.model = YOLO(model_path)
|
||||||
@@ -87,8 +88,8 @@ class VideoCleaner:
|
|||||||
# Following your rules: "If it's night and no lights, delete".
|
# Following your rules: "If it's night and no lights, delete".
|
||||||
# So we only need to detect humans to justify keeping the video.
|
# So we only need to detect humans to justify keeping the video.
|
||||||
small_frame = cv2.resize(frame, (640, 360))
|
small_frame = cv2.resize(frame, (640, 360))
|
||||||
results = self.model(small_frame, classes=[0], verbose=False, conf=0.5)
|
results = self.model(small_frame, classes=[0], verbose=False, conf=0.7)
|
||||||
debugmode=False
|
debugmode=True
|
||||||
if len(results[0].boxes) > 0:
|
if len(results[0].boxes) > 0:
|
||||||
if is_color:
|
if is_color:
|
||||||
# --- DEBUG: Save the frame that triggered detection ---
|
# --- DEBUG: Save the frame that triggered detection ---
|
||||||
@@ -119,7 +120,7 @@ class VideoCleaner:
|
|||||||
video_path = Path(video_path).resolve()
|
video_path = Path(video_path).resolve()
|
||||||
mtime = datetime.fromtimestamp(os.path.getmtime(video_path))
|
mtime = datetime.fromtimestamp(os.path.getmtime(video_path))
|
||||||
if datetime.now() - mtime < self.age_limit:
|
if datetime.now() - mtime < self.age_limit:
|
||||||
return
|
return False # 表示因为时间太新没处理
|
||||||
|
|
||||||
keep, reason = self.should_keep_video(video_path)
|
keep, reason = self.should_keep_video(video_path)
|
||||||
if keep:
|
if keep:
|
||||||
@@ -128,6 +129,7 @@ class VideoCleaner:
|
|||||||
else:
|
else:
|
||||||
print(f"Action: DELETE {video_path.name} - Reason: {reason}")
|
print(f"Action: DELETE {video_path.name} - Reason: {reason}")
|
||||||
os.remove(video_path)
|
os.remove(video_path)
|
||||||
|
return True # 表示处理了
|
||||||
|
|
||||||
def move_to_processed(self, video_path, processed_base_dir, input_base_dir):
|
def move_to_processed(self, video_path, processed_base_dir, input_base_dir):
|
||||||
rel_path = video_path.relative_to(input_base_dir)
|
rel_path = video_path.relative_to(input_base_dir)
|
||||||
@@ -140,17 +142,43 @@ class VideoCleaner:
|
|||||||
input_path = Path(input_dir).resolve()
|
input_path = Path(input_dir).resolve()
|
||||||
if not input_path.exists(): return
|
if not input_path.exists(): return
|
||||||
processed_dir = input_path.parent / "processed"
|
processed_dir = input_path.parent / "processed"
|
||||||
for root, dirs, files in os.walk(input_path):
|
|
||||||
if "processed" in dirs: dirs.remove("processed")
|
print(f"Scanning {input_path}...")
|
||||||
for file in files:
|
|
||||||
if file.lower().endswith(self.supported_extensions):
|
while True:
|
||||||
self.process_video_file(Path(root) / file, processed_dir, input_path)
|
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__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("dir", help="Target directory")
|
parser.add_argument("dir", help="Target directory")
|
||||||
parser.add_argument("--days", type=int, default=30)
|
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()
|
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)
|
cleaner.scan_and_process(args.dir)
|
||||||
|
|||||||
BIN
yolo26n.pt
Normal file
BIN
yolo26n.pt
Normal file
Binary file not shown.
Reference in New Issue
Block a user