santa47 commited on
Commit
03ab521
Β·
verified Β·
1 Parent(s): 5a2ec9e

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +23 -6
  2. app (2).py +235 -0
  3. requirements (2).txt +5 -0
README.md CHANGED
@@ -1,12 +1,29 @@
1
  ---
2
- title: Violence Detection App
3
- emoji: 🏒
4
- colorFrom: purple
5
  colorTo: yellow
6
- sdk: gradio
7
- sdk_version: 6.5.1
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Violence Detection 3D CNN
3
+ emoji: πŸŽ₯
4
+ colorFrom: red
5
  colorTo: yellow
6
+ sdk: streamlit
7
+ sdk_version: 1.28.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
  ---
12
 
13
+ # πŸŽ₯ Violence Detection in Videos
14
+
15
+ A Streamlit application that uses a **3D CNN** model to detect violence in video clips.
16
+
17
+ ## Model
18
+ - **Architecture:** 3D CNN (4 convolutional blocks)
19
+ - **Dataset:** RWF-2000 (Real World Fighting)
20
+ - **Task:** Binary Classification (Violence vs Non-Violence)
21
+ - **Input:** 16 frames Γ— 112 Γ— 112 RGB
22
+
23
+ ## How to Use
24
+ 1. Upload a video file (AVI, MP4, or MKV)
25
+ 2. Click "Analyze Video"
26
+ 3. View the prediction results
27
+
28
+ ## Model Card
29
+ [https://huggingface.co/santa47/violence-detection-3dcnn](https://huggingface.co/santa47/violence-detection-3dcnn)
app (2).py ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import torch
3
+ import torch.nn as nn
4
+ import numpy as np
5
+ import cv2
6
+ import tempfile
7
+ import os
8
+ from huggingface_hub import hf_hub_download
9
+
10
+ # ============================================
11
+ # MODEL DEFINITION
12
+ # ============================================
13
+ class Conv3DBlock(nn.Module):
14
+ def __init__(self, in_ch, out_ch, kernel=3, stride=1, padding=1):
15
+ super().__init__()
16
+ self.conv = nn.Conv3d(in_ch, out_ch, kernel, stride, padding)
17
+ self.bn = nn.BatchNorm3d(out_ch)
18
+ self.relu = nn.ReLU(inplace=True)
19
+
20
+ def forward(self, x):
21
+ return self.relu(self.bn(self.conv(x)))
22
+
23
+
24
+ class ViolenceDetector3DCNN(nn.Module):
25
+ def __init__(self, num_classes=2, dropout=0.5):
26
+ super().__init__()
27
+
28
+ self.features = nn.Sequential(
29
+ Conv3DBlock(3, 64),
30
+ nn.MaxPool3d((1, 2, 2), (1, 2, 2)),
31
+
32
+ Conv3DBlock(64, 128),
33
+ nn.MaxPool3d((2, 2, 2), (2, 2, 2)),
34
+
35
+ Conv3DBlock(128, 256),
36
+ Conv3DBlock(256, 256),
37
+ nn.MaxPool3d((2, 2, 2), (2, 2, 2)),
38
+
39
+ Conv3DBlock(256, 512),
40
+ Conv3DBlock(512, 512),
41
+ nn.MaxPool3d((2, 2, 2), (2, 2, 2)),
42
+ )
43
+
44
+ self.gap = nn.AdaptiveAvgPool3d((1, 1, 1))
45
+
46
+ self.classifier = nn.Sequential(
47
+ nn.Dropout(dropout),
48
+ nn.Linear(512, 256),
49
+ nn.ReLU(inplace=True),
50
+ nn.Dropout(dropout),
51
+ nn.Linear(256, num_classes)
52
+ )
53
+
54
+ def forward(self, x):
55
+ x = self.features(x)
56
+ x = self.gap(x)
57
+ x = x.view(x.size(0), -1)
58
+ x = self.classifier(x)
59
+ return x
60
+
61
+
62
+ # ============================================
63
+ # LOAD MODEL
64
+ # ============================================
65
+ @st.cache_resource
66
+ def load_model():
67
+ # Download model from Hugging Face
68
+ model_path = hf_hub_download(
69
+ repo_id="santa47/violence-detection-3dcnn",
70
+ filename="violence_detector.pth"
71
+ )
72
+
73
+ # Load model
74
+ model = ViolenceDetector3DCNN(num_classes=2, dropout=0.5)
75
+ checkpoint = torch.load(model_path, map_location=torch.device('cpu'))
76
+ model.load_state_dict(checkpoint['model_state_dict'])
77
+ model.eval()
78
+
79
+ return model
80
+
81
+
82
+ # ============================================
83
+ # VIDEO PROCESSING
84
+ # ============================================
85
+ def process_video(video_path, num_frames=16, frame_size=(112, 112)):
86
+ """Extract and preprocess frames from video"""
87
+ cap = cv2.VideoCapture(video_path)
88
+ frames = []
89
+
90
+ while True:
91
+ ret, frame = cap.read()
92
+ if not ret:
93
+ break
94
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
95
+ frame = cv2.resize(frame, frame_size)
96
+ frames.append(frame)
97
+
98
+ cap.release()
99
+
100
+ if len(frames) == 0:
101
+ return None
102
+
103
+ # Sample frames uniformly
104
+ total_frames = len(frames)
105
+ if total_frames >= num_frames:
106
+ indices = np.linspace(0, total_frames - 1, num_frames, dtype=int)
107
+ else:
108
+ indices = list(range(total_frames)) + [total_frames - 1] * (num_frames - total_frames)
109
+
110
+ sampled_frames = [frames[i] for i in indices]
111
+
112
+ # Convert to tensor: (T, H, W, C) -> (C, T, H, W)
113
+ video_tensor = np.stack(sampled_frames, axis=0)
114
+ video_tensor = video_tensor.transpose(3, 0, 1, 2)
115
+ video_tensor = video_tensor.astype(np.float32) / 255.0
116
+
117
+ # Normalize
118
+ mean = np.array([0.485, 0.456, 0.406]).reshape(3, 1, 1, 1)
119
+ std = np.array([0.229, 0.224, 0.225]).reshape(3, 1, 1, 1)
120
+ video_tensor = (video_tensor - mean) / std
121
+
122
+ # Add batch dimension
123
+ video_tensor = torch.from_numpy(video_tensor).unsqueeze(0).float()
124
+
125
+ return video_tensor
126
+
127
+
128
+ # ============================================
129
+ # PREDICTION
130
+ # ============================================
131
+ def predict(model, video_tensor):
132
+ """Run prediction on video"""
133
+ with torch.no_grad():
134
+ outputs = model(video_tensor)
135
+ probs = torch.softmax(outputs, dim=1)
136
+ pred_class = torch.argmax(probs, dim=1).item()
137
+ confidence = probs[0][pred_class].item()
138
+
139
+ return pred_class, confidence, probs[0].numpy()
140
+
141
+
142
+ # ============================================
143
+ # STREAMLIT APP
144
+ # ============================================
145
+ def main():
146
+ st.set_page_config(
147
+ page_title="Violence Detection",
148
+ page_icon="πŸŽ₯",
149
+ layout="centered"
150
+ )
151
+
152
+ st.title("πŸŽ₯ Violence Detection in Videos")
153
+ st.markdown("**3D CNN Model trained on RWF-2000 Dataset**")
154
+ st.markdown("---")
155
+
156
+ # Load model
157
+ with st.spinner("Loading model..."):
158
+ model = load_model()
159
+ st.success("βœ… Model loaded!")
160
+
161
+ # File uploader
162
+ st.markdown("### Upload a Video")
163
+ uploaded_file = st.file_uploader(
164
+ "Choose a video file (AVI, MP4, MKV)",
165
+ type=['avi', 'mp4', 'mkv']
166
+ )
167
+
168
+ if uploaded_file is not None:
169
+ # Save uploaded file temporarily
170
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.avi') as tmp_file:
171
+ tmp_file.write(uploaded_file.read())
172
+ tmp_path = tmp_file.name
173
+
174
+ # Display video
175
+ st.video(uploaded_file)
176
+
177
+ # Process and predict
178
+ if st.button("πŸ” Analyze Video", type="primary"):
179
+ with st.spinner("Processing video..."):
180
+ # Process video
181
+ video_tensor = process_video(tmp_path)
182
+
183
+ if video_tensor is None:
184
+ st.error("❌ Could not process video. Please try another file.")
185
+ else:
186
+ # Predict
187
+ pred_class, confidence, probs = predict(model, video_tensor)
188
+
189
+ # Display results
190
+ st.markdown("---")
191
+ st.markdown("### πŸ“Š Results")
192
+
193
+ col1, col2 = st.columns(2)
194
+
195
+ with col1:
196
+ if pred_class == 1:
197
+ st.error("⚠️ **VIOLENCE DETECTED**")
198
+ else:
199
+ st.success("βœ… **NO VIOLENCE**")
200
+
201
+ with col2:
202
+ st.metric("Confidence", f"{confidence * 100:.1f}%")
203
+
204
+ # Probability bars
205
+ st.markdown("### Probability Distribution")
206
+
207
+ col1, col2 = st.columns(2)
208
+ with col1:
209
+ st.markdown("**Non-Violence**")
210
+ st.progress(float(probs[0]))
211
+ st.write(f"{probs[0] * 100:.1f}%")
212
+
213
+ with col2:
214
+ st.markdown("**Violence**")
215
+ st.progress(float(probs[1]))
216
+ st.write(f"{probs[1] * 100:.1f}%")
217
+
218
+ # Cleanup
219
+ os.unlink(tmp_path)
220
+
221
+ # Footer
222
+ st.markdown("---")
223
+ st.markdown(
224
+ """
225
+ <div style='text-align: center; color: gray;'>
226
+ Model: 3D CNN | Dataset: RWF-2000 |
227
+ <a href='https://huggingface.co/santa47/violence-detection-3dcnn'>Model Card</a>
228
+ </div>
229
+ """,
230
+ unsafe_allow_html=True
231
+ )
232
+
233
+
234
+ if __name__ == "__main__":
235
+ main()
requirements (2).txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit==1.28.0
2
+ torch==2.0.1
3
+ numpy==1.24.3
4
+ opencv-python-headless==4.8.0.76
5
+ huggingface_hub==0.17.3