Hamzah-ALQadasi/Video_Authenticity.Anamoly_Detection.Temporal_Modeling
0
1#!/usr/bin/env python32"""3Outlier removal algorithm for video frame embeddings using DBSCAN.4 5Reads embeddings, detects outliers, and exports predictions to CSV files.6GPU acceleration is automatically detected and used if available.7 8Usage:9 # Process CLIP embeddings from outlier_artifacts10 python outliers_removal_algorithm.py --embeddings-dir ./outlier_artifacts/embeddings --output-dir ./outlier_artifacts/cleaned_CSVs --model-type clip11 12 # Process DINOv2 embeddings13 python outliers_removal_algorithm.py --embeddings-dir ./outlier_artifacts/embeddings --output-dir ./outlier_artifacts/cleaned_CSVs --model-type dinov214 15 # Process ResNet18 embeddings16 python outliers_removal_algorithm.py --embeddings-dir ./outlier_artifacts/embeddings --output-dir ./outlier_artifacts/cleaned_CSVs --model-type resnet1817 18 # Custom DBSCAN parameters with CLIP embeddings19 python outliers_removal_algorithm.py --embeddings-dir ./outlier_artifacts/embeddings --output-dir ./outlier_artifacts/cleaned_CSVs --model-type clip --eps 0.45 --min-samples 5020 21 # Filter to specific action category22 python outliers_removal_algorithm.py --embeddings-dir ./outlier_artifacts/embeddings --output-dir ./outlier_artifacts/cleaned_CSVs --model-type clip --action-filter Crawling23 24 # Limit processing to first 10 videos25 python outliers_removal_algorithm.py --embeddings-dir ./outlier_artifacts/embeddings --output-dir ./outlier_artifacts/cleaned_CSVs --model-type clip --max-videos 1026 27Note: To generate cleaned videos from predictions, use generate_cleaned_videos_from_predictions.py28"""29 30import os31import glob32import csv33import argparse34import numpy as np35import torch36from pathlib import Path37 38try:39 import cupy as cp40 from cuml.cluster import DBSCAN as cuDBSCAN41 CUML_AVAILABLE = True42except ImportError:43 CUML_AVAILABLE = False44 45from sklearn.cluster import DBSCAN as skDBSCAN46 47# Automatically detect GPU availability48USE_GPU = CUML_AVAILABLE and torch.cuda.is_available()49 50 51def to_numpy(x):52 """Convert tensor or array to numpy float32."""53 if isinstance(x, torch.Tensor):54 x = x.detach().cpu().numpy()55 return np.asarray(x, dtype=np.float32)56 57 58def dbscan_outliers(X, eps=0.55, min_samples=10):59 """60 Detect outliers using DBSCAN (noise points).61 62 Args:63 X: Feature matrix (N, D)64 eps: DBSCAN epsilon parameter65 min_samples: DBSCAN minimum samples parameter66 67 Returns:68 Boolean array of shape (N,) where True = outlier69 """70 X = to_numpy(X)71 72 # Ensure X is 2D: (n_samples, n_features)73 if X.ndim > 2:74 X = X.reshape(X.shape[0], -1)75 76 if USE_GPU:77 labels = cuDBSCAN(eps=eps, min_samples=min_samples).fit_predict(cp.asarray(X)).get()78 else:79 labels = skDBSCAN(eps=eps, min_samples=min_samples, n_jobs=-1).fit_predict(X)80 return labels == -181 82 83def extract_action_name(filename, model_type):84 """Extract action category from embedding filename based on model type."""85 name = os.path.basename(filename)86 suffix = f'_{model_type}_embeddings'87 name = name.replace(suffix + '.pt', '').replace(suffix + '.pth', '')88 return name89 90 91def process_all_embeddings(emb_dir, eps, min_samples, output_dir, model_type='clip',92 max_videos=None, action_filter=None):93 """94 Process all embeddings and export predictions to CSV files.95 96 Args:97 emb_dir: Directory containing embedding .pt files98 eps: DBSCAN epsilon parameter99 min_samples: DBSCAN minimum samples parameter100 output_dir: Directory to save CSV predictions101 model_type: Model type to load ('clip', 'dinov2', or 'resnet18')102 max_videos: Limit processing to first N videos103 action_filter: Filter to specific action category104 """105 # Filter files by model type (e.g., *_clip_embeddings.pt, *_dinov2_embeddings.pt, or *_resnet18_embeddings.pt)106 pattern = f"*_{model_type}_embeddings.pt"107 pt_files = sorted(glob.glob(os.path.join(emb_dir, pattern)))108 109 if action_filter:110 pt_files = [f for f in pt_files if action_filter.lower() in os.path.basename(f).lower()]111 print(f"Filtering to action: {action_filter}")112 print(f"Found {len(pt_files)} matching file(s)")113 114 # Create output directory115 output_path = Path(output_dir)116 output_path.mkdir(exist_ok=True, parents=True)117 118 print("=" * 80)119 print("OUTLIER REMOVAL ALGORITHM - DBSCAN")120 print("=" * 80)121 print(f"Model type: {model_type.upper()}")122 print(f"GPU Acceleration: {'Enabled (cuML)' if USE_GPU else 'Disabled (CPU/sklearn)'}")123 print(f"Embeddings dir: {emb_dir}")124 print(f"Output dir: {output_dir}")125 print(f"DBSCAN parameters: eps={eps}, min_samples={min_samples}")126 print(f"Total embedding files: {len(pt_files)}")127 print("=" * 80)128 129 total_videos = 0130 131 for pt_path in pt_files:132 data = torch.load(pt_path, map_location="cpu")133 action_name = extract_action_name(pt_path, model_type)134 print(f"Processing action: {action_name}")135 136 # Create CSV for this action137 csv_path = output_path / f"{action_name}.csv"138 139 with open(csv_path, 'w', newline='') as csvfile:140 writer = csv.writer(csvfile)141 writer.writerow(['video_id', 'predicted_outliers_list'])142 143 for video_name, video_data in data.items():144 if max_videos and total_videos >= max_videos:145 break146 147 total_videos += 1148 embeddings = video_data["embeddings"]149 150 # Run DBSCAN outlier detection151 predictions = dbscan_outliers(embeddings, eps=eps, min_samples=min_samples)152 153 # Convert boolean array to list of outlier indices154 outlier_indices = np.where(predictions)[0].tolist()155 outliers_str = ",".join(map(str, outlier_indices))156 157 # Write to CSV158 writer.writerow([video_name, outliers_str])159 160 num_outliers = predictions.sum()161 num_frames = len(embeddings)162 163 if max_videos and total_videos >= max_videos:164 break165 166 print("\n" + "=" * 80)167 print("PROCESSING COMPLETE")168 print("=" * 80)169 print(f"Total videos processed: {total_videos}")170 print(f"CSV files saved to: {output_path.absolute()}")171 print("\nNext step: Use generate_cleaned_videos_from_predictions.py to create cleaned videos")172 print("=" * 80)173 174 175def main():176 parser = argparse.ArgumentParser(177 description="Outlier removal algorithm using DBSCAN: detect outliers and export predictions to CSV"178 )179 180 parser.add_argument("--embeddings-dir", required=True,181 help="Directory containing embedding .pt files")182 parser.add_argument("--output-dir", default="./outlier_artifacts/cleaned_CSVs",183 help="Directory to save prediction CSV files")184 parser.add_argument("--model-type", type=str, choices=['clip', 'dinov2', 'resnet18'], default='clip',185 help="Model type to load: 'clip', 'dinov2', or 'resnet18' (default: clip)")186 parser.add_argument("--max-videos", type=int,187 help="Limit processing to first N videos")188 parser.add_argument("--action-filter",189 help="Filter to specific action category (e.g., 'Crawling')")190 191 # DBSCAN parameters192 parser.add_argument("--eps", type=float, default=0.5,193 help="DBSCAN: Epsilon parameter")194 parser.add_argument("--min-samples", type=int, default=40,195 help="DBSCAN: Minimum samples parameter")196 197 args = parser.parse_args()198 199 process_all_embeddings(200 emb_dir=args.embeddings_dir,201 eps=args.eps,202 min_samples=args.min_samples,203 output_dir=args.output_dir,204 model_type=args.model_type,205 max_videos=args.max_videos,206 action_filter=args.action_filter207 )208 209 210if __name__ == "__main__":211 main()212 