| import torch |
| import gradio as gr |
| import cv2 |
| import numpy as np |
| from PIL import Image |
|
|
| from model import AdvancedCrimeDetectionModel |
| from feature_extractor import extract_features |
|
|
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
|
|
| |
| print("Loading model...") |
| try: |
| checkpoint = torch.load( |
| "crime_model_advanced.pth", |
| map_location=device, |
| weights_only=False |
| ) |
| threshold = checkpoint.get("threshold", 0.5) |
| model = AdvancedCrimeDetectionModel().to(device) |
| model.load_state_dict(checkpoint["model_state_dict"]) |
| model.eval() |
| print(f"Model loaded! Threshold: {threshold:.3f}") |
| except Exception as e: |
| print(f"Error loading model: {e}") |
| threshold = 0.5 |
|
|
|
|
| def extract_frames_optimized(video_path, max_frames=72, target_fps=4): |
| """Efficiently extract frames from video using adaptive sampling.""" |
| cap = cv2.VideoCapture(video_path) |
| if not cap.isOpened(): |
| raise ValueError("Could not open video file") |
|
|
| total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) |
| fps = cap.get(cv2.CAP_PROP_FPS) |
| duration = total_frames / fps if fps > 0 else 0 |
|
|
| print(f"Video: {total_frames} frames, {fps:.1f} FPS, {duration:.1f}s") |
|
|
| frame_interval = max(1, int(fps / target_fps)) if duration > 0 else 1 |
|
|
| estimated_frames = total_frames // frame_interval |
| if estimated_frames > max_frames: |
| frame_interval = total_frames // max_frames |
|
|
| frames = [] |
| tmp_paths = [] |
| frame_count = 0 |
|
|
| while len(frames) < max_frames: |
| ret, frame = cap.read() |
| if not ret: |
| break |
|
|
| if frame_count % frame_interval == 0: |
| frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
| frames.append(frame_rgb) |
|
|
| |
| path = f"/tmp/frame_{len(frames) - 1}.png" |
| cv2.imwrite(path, frame) |
| tmp_paths.append(path) |
|
|
| frame_count += 1 |
|
|
| cap.release() |
| print(f"Extracted {len(frames)} frames (every {frame_interval} frames)") |
| return frames, tmp_paths |
|
|
|
|
| def get_risk_level(prob): |
| """Categorize risk level based on probability.""" |
| if prob < 0.3: |
| return "π’ Low Risk" |
| elif prob < 0.5: |
| return "π‘ Medium Risk" |
| elif prob < 0.7: |
| return "π Elevated Risk" |
| else: |
| return "π΄ High Risk" |
|
|
|
|
| def get_interpretation(max_prob, avg_prob, threshold): |
| """Provide interpretation of results.""" |
| if max_prob < threshold: |
| return "The video appears to show normal activity. No suspicious behavior detected." |
| else: |
| severity = "significant" if max_prob > 0.7 else "potential" |
| consistency = "throughout the video" if avg_prob > threshold else "in specific segments" |
| return f"The model detected {severity} anomalous behavior {consistency}. Manual review recommended." |
|
|
|
|
| def format_output(result): |
| """Format result dictionary into readable markdown.""" |
| if "error" in result: |
| return f"β {result['error']}" |
|
|
| output = f""" |
| # {result['prediction']} |
| |
| **Confidence:** {result['confidence']} |
| **Risk Level:** {result['risk_level']} |
| |
| --- |
| |
| ### Analysis Details |
| - **Max Anomaly Score:** {result['max_anomaly_score']} |
| - **Average Anomaly Score:** {result['avg_anomaly_score']} |
| - **Detection Threshold:** {result['threshold']} |
| - **Frames Analyzed:** {result['frames_analyzed']} |
| - **Segments Analyzed:** {result['segments_analyzed']} |
| |
| --- |
| |
| ### Interpretation |
| {result['details']} |
| |
| --- |
| |
| **Note:** This is an AI-based analysis tool. Results should be used as a supplementary assessment and verified by trained personnel. |
| """ |
| return output |
|
|
|
|
| def predict_video(video_path, progress=gr.Progress()): |
| """Main prediction function using model.py and feature_extractor.py.""" |
| try: |
| progress(0, desc="Extracting frames...") |
|
|
| frames, tmp_paths = extract_frames_optimized(video_path, max_frames=72, target_fps=4) |
|
|
| if len(frames) < 24: |
| return format_output({ |
| "error": f"Video too short. Extracted only {len(frames)} frames (need at least 24)." |
| }) |
|
|
| progress(0.3, desc="Extracting features...") |
|
|
| |
| window_size = 24 |
| stride = 12 |
| all_probs = [] |
| num_windows = max(1, (len(tmp_paths) - window_size) // stride + 1) |
|
|
| for i in range(0, len(tmp_paths) - window_size + 1, stride): |
| window_paths = tmp_paths[i:i + window_size] |
| feats = extract_features(window_paths).unsqueeze(0).to(device) |
|
|
| with torch.no_grad(): |
| prob = torch.sigmoid(model(feats)).item() |
| all_probs.append(prob) |
|
|
| progress( |
| 0.3 + 0.6 * ((i // stride + 1) / num_windows), |
| desc=f"Analyzing segments... ({i // stride + 1}/{num_windows})" |
| ) |
|
|
| progress(0.9, desc="Finalizing results...") |
|
|
| max_prob = max(all_probs) |
| avg_prob = float(np.mean(all_probs)) |
| is_anomaly = max_prob > threshold |
|
|
| result = { |
| "prediction": "π¨ ANOMALY DETECTED" if is_anomaly else "β
NORMAL ACTIVITY", |
| "confidence": f"{max_prob * 100:.1f}%", |
| "max_anomaly_score": f"{max_prob:.3f}", |
| "avg_anomaly_score": f"{avg_prob:.3f}", |
| "threshold": f"{threshold:.3f}", |
| "frames_analyzed": len(frames), |
| "segments_analyzed": len(all_probs), |
| "risk_level": get_risk_level(max_prob), |
| "details": get_interpretation(max_prob, avg_prob, threshold), |
| } |
|
|
| progress(1.0, desc="Complete!") |
| return format_output(result) |
|
|
| except Exception as e: |
| return format_output({"error": f"Error processing video: {str(e)}"}) |
|
|
|
|
| |
| with gr.Blocks(theme=gr.themes.Soft(), title="Crime Detection AI") as demo: |
| gr.Markdown(""" |
| # π Advanced Crime Detection System |
| |
| Upload a video to analyze for potential anomalous or criminal behavior. |
| The model uses dual-backbone feature extraction with Transformer + GRU architecture. |
| |
| **Supported formats:** MP4, AVI, MOV, MKV |
| **Optimized for:** Videos from 10 seconds to several minutes |
| """) |
|
|
| with gr.Row(): |
| with gr.Column(): |
| video_input = gr.Video(label="Upload Video", height=400) |
| analyze_btn = gr.Button("π Analyze Video", variant="primary", size="lg") |
|
|
| gr.Markdown(""" |
| ### Tips: |
| - Videos are processed efficiently using adaptive frame sampling |
| - Longer videos are analyzed in overlapping segments |
| - Analysis typically takes 30-60 seconds |
| """) |
|
|
| with gr.Column(): |
| output_text = gr.Markdown(label="Analysis Results") |
|
|
| gr.Markdown(""" |
| --- |
| ### About This Model |
| |
| This system uses a deep learning model trained on the UCF-Crime dataset to detect anomalous activities in videos. |
| |
| **Architecture:** |
| - Dual backbone feature extraction (Transformer + GRU) |
| - Transformer encoder for long-range dependencies |
| - Bidirectional GRU for temporal modeling |
| - Multi-head attention mechanism |
| |
| **Detection Capabilities:** |
| - Identifies unusual patterns and behaviors |
| - Analyzes motion and spatial features |
| - Provides confidence scores and risk levels |
| |
| """) |
|
|
| analyze_btn.click( |
| fn=predict_video, |
| inputs=video_input, |
| outputs=output_text |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |