ombhojane commited on
Commit
dc56a44
·
verified ·
1 Parent(s): fca81c0
Files changed (1) hide show
  1. app.py +96 -142
app.py CHANGED
@@ -18,132 +18,89 @@ st.set_page_config(
18
  layout="wide"
19
  )
20
 
21
- class BehaviorDetector(nn.Module):
22
- def __init__(self, num_classes):
23
- super(BehaviorDetector, self).__init__()
24
- # Use EfficientNet as base model (better performance than ResNet)
25
- self.base_model = models.efficientnet_b0(pretrained=True)
26
- # Replace classifier
27
- num_features = self.base_model.classifier[1].in_features
28
- self.base_model.classifier = nn.Sequential(
29
- nn.Dropout(p=0.2),
30
- nn.Linear(num_features, num_classes)
31
- )
32
-
33
- def forward(self, x):
34
- return torch.sigmoid(self.base_model(x))
35
-
36
  class DogBehaviorAnalyzer:
37
- def __init__(self, model_path=None):
38
- self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
39
-
40
- # Initialize YOLO model for dog detection (optional)
41
- try:
42
- self.yolo_model = YOLO(model_path) if model_path else None
43
- except Exception as e:
44
- st.warning("YOLO model not found. Running without dog detection.")
45
- self.yolo_model = None
46
-
47
- # Initialize behavior classifier
48
- self.num_behaviors = 5
49
- try:
50
- self.behavior_model = BehaviorDetector(self.num_behaviors).to(self.device)
51
- except Exception as e:
52
- st.warning("Error loading behavior model. Using default classifier.")
53
- self.behavior_model = models.resnet18(pretrained=True)
54
- num_features = self.behavior_model.fc.in_features
55
- self.behavior_model.fc = nn.Linear(num_features, self.num_behaviors)
56
- self.behavior_model = self.behavior_model.to(self.device)
57
-
58
- self.behavior_model.eval()
59
-
60
- # Define sophisticated transforms
61
- self.transform = transforms.Compose([
62
- transforms.Resize((224, 224)),
63
- transforms.ToTensor(),
64
- transforms.Normalize(mean=[0.485, 0.456, 0.406],
65
- std=[0.229, 0.224, 0.225]),
66
- transforms.RandomHorizontalFlip(p=0.3),
67
- transforms.ColorJitter(brightness=0.2, contrast=0.2)
68
- ])
69
-
70
- # Behavior definitions with confidence thresholds
71
  self.behaviors = {
72
- 'tail_wagging': {'threshold': 0.75, 'description': 'Your dog is displaying happiness and excitement!'},
73
- 'barking': {'threshold': 0.8, 'description': 'Your dog is trying to communicate or alert you.'},
74
- 'ears_perked': {'threshold': 0.7, 'description': 'Your dog is alert and interested in something.'},
75
- 'lying_down': {'threshold': 0.85, 'description': 'Your dog is relaxed and comfortable.'},
76
- 'jumping': {'threshold': 0.8, 'description': 'Your dog is energetic and playful!'}
77
  }
78
 
79
- # Temporal smoothing using sliding window
80
- self.behavior_history = {behavior: deque(maxlen=5) for behavior in self.behaviors.keys()}
81
-
82
- def preprocess_frame(self, frame):
83
- """Advanced frame preprocessing"""
84
- # Convert BGR to RGB
85
- rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
86
 
87
- # Apply adaptive histogram equalization
88
- lab = cv2.cvtColor(rgb_frame, cv2.COLOR_RGB2LAB)
89
- l, a, b = cv2.split(lab)
90
- clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
91
- cl = clahe.apply(l)
92
- enhanced = cv2.merge((cl,a,b))
93
- enhanced = cv2.cvtColor(enhanced, cv2.COLOR_LAB2RGB)
94
 
95
- return Image.fromarray(enhanced)
96
-
97
- def detect_dog(self, frame):
98
- """Detect dog in frame using YOLO"""
99
- if self.yolo_model is None:
100
- return True # Skip detection if no model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
- results = self.yolo_model(frame)
103
- return len(results) > 0 and any(result.boxes for result in results)
 
 
 
104
 
105
  def analyze_frame(self, frame):
106
- """Analyze frame with temporal smoothing and confidence thresholds"""
107
- # First detect if dog is present
108
- if not self.detect_dog(frame):
109
- return []
110
-
111
- # Preprocess frame
112
- processed_frame = self.preprocess_frame(frame)
113
- input_tensor = self.transform(processed_frame).unsqueeze(0).to(self.device)
114
-
115
- with torch.no_grad():
116
- predictions = self.behavior_model(input_tensor).squeeze().cpu().numpy()
117
 
118
- # Update behavior history
119
- for behavior, pred in zip(self.behaviors.keys(), predictions):
120
- self.behavior_history[behavior].append(pred)
121
-
122
- # Apply temporal smoothing and thresholds
123
  detected_behaviors = []
124
- for behavior, history in self.behavior_history.items():
125
- if len(history) > 0:
126
- avg_conf = sum(history) / len(history)
127
- if avg_conf > self.behaviors[behavior]['threshold']:
128
- detected_behaviors.append((behavior, avg_conf))
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  return detected_behaviors
131
 
132
  def main():
133
- st.title("🐕 Advanced Dog Language Understanding")
134
- st.write("Upload a video of your dog for detailed behavior analysis!")
135
 
136
  analyzer = DogBehaviorAnalyzer()
137
 
138
- # Add model confidence control
139
- confidence_threshold = st.sidebar.slider(
140
- "Detection Confidence Threshold",
141
- min_value=0.5,
142
- max_value=0.95,
143
- value=0.7,
144
- step=0.05
145
- )
146
-
147
  video_file = st.file_uploader("Upload Video", type=['mp4', 'avi', 'mov'])
148
 
149
  if video_file is not None:
@@ -179,38 +136,36 @@ def main():
179
  progress = frame_count / total_frames
180
  progress_bar.progress(progress)
181
 
182
- # Update video preview with annotations
183
- annotated_frame = frame.copy()
184
  detected_behaviors = analyzer.analyze_frame(frame)
185
 
186
  # Draw behavior labels on frame
187
  y_pos = 30
188
  for behavior, conf in detected_behaviors:
189
- if conf > confidence_threshold:
190
- behavior_counts[behavior] += 1
191
- confidence_history[behavior].append(conf)
192
- cv2.putText(annotated_frame,
193
- f"{behavior.replace('_', ' ').title()}: {conf:.2f}",
194
- (10, y_pos),
195
- cv2.FONT_HERSHEY_SIMPLEX,
196
- 0.7,
197
- (0, 255, 0),
198
- 2)
199
- y_pos += 30
200
 
201
  video_placeholder.image(
202
- cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB),
203
  channels="RGB",
204
  use_container_width=True
205
  )
206
 
207
- # Update analysis display with confidence scores
208
  analysis_text = "Detected Behaviors:\n\n"
209
  for behavior, count in behavior_counts.items():
210
  if count > 0:
211
  avg_conf = sum(confidence_history[behavior]) / len(confidence_history[behavior])
212
  analysis_text += f"• {behavior.replace('_', ' ').title()}:\n"
213
- analysis_text += f" Count: {count} | Avg Confidence: {avg_conf:.2f}\n"
214
  analysis_text += f" {analyzer.behaviors[behavior]['description']}\n\n"
215
 
216
  analysis_placeholder.text_area(
@@ -227,11 +182,11 @@ def main():
227
  # Final analysis
228
  st.subheader("Comprehensive Analysis")
229
 
230
- # Create detailed metrics
231
  col1, col2, col3 = st.columns(3)
232
 
233
  with col1:
234
- most_common = max(behavior_counts.items(), key=lambda x: x[1])[0]
235
  st.metric("Primary Behavior", most_common.replace('_', ' ').title())
236
 
237
  with col2:
@@ -239,32 +194,31 @@ def main():
239
  st.metric("Total Behaviors", total_behaviors)
240
 
241
  with col3:
242
- avg_confidence = np.mean([np.mean(conf) for conf in confidence_history.values() if conf])
 
243
  st.metric("Average Confidence", f"{avg_confidence:.2%}")
244
 
245
  # Behavior distribution chart
246
- st.subheader("Behavior Distribution")
247
- behavior_data = {k.replace('_', ' ').title(): v for k, v in behavior_counts.items() if v > 0}
248
- st.bar_chart(behavior_data)
249
-
250
- # Recommendations based on analysis
251
- st.subheader("Personalized Recommendations")
252
- if total_behaviors > 0:
253
- st.write("Based on the detailed analysis, here are tailored recommendations:")
254
 
255
- # Generate specific recommendations based on detected behaviors
 
256
  recommendations = []
 
257
  if behavior_counts['tail_wagging'] > total_behaviors * 0.3:
258
- recommendations.append("• Your dog shows frequent happiness - great time for training!")
259
- if behavior_counts['barking'] > total_behaviors * 0.2:
260
- recommendations.append("• Consider quiet command training to manage barking")
261
- if behavior_counts['jumping'] > total_behaviors * 0.25:
262
- recommendations.append("• Focus on calm behavior reinforcement")
263
 
264
  for rec in recommendations:
265
  st.write(rec)
266
  else:
267
- st.write("No clear behaviors detected. Try recording with better lighting and closer camera angle.")
268
 
269
  if __name__ == "__main__":
270
  main()
 
18
  layout="wide"
19
  )
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  class DogBehaviorAnalyzer:
22
+ def __init__(self):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  self.behaviors = {
24
+ 'tail_wagging': {'threshold': 0.6, 'description': 'Your dog is displaying happiness and excitement!'},
25
+ 'movement': {'threshold': 0.5, 'description': 'Your dog is active and moving around.'},
26
+ 'stationary': {'threshold': 0.7, 'description': 'Your dog is calm and still.'},
27
+ 'high_activity': {'threshold': 0.65, 'description': 'Your dog is very energetic!'}
 
28
  }
29
 
30
+ # Motion detection parameters
31
+ self.history = []
32
+ self.max_history = 10
33
+ self.prev_frame = None
 
 
 
34
 
35
+ def detect_motion(self, frame):
36
+ """Detect motion in frame"""
37
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
38
+ gray = cv2.GaussianBlur(gray, (21, 21), 0)
 
 
 
39
 
40
+ if self.prev_frame is None:
41
+ self.prev_frame = gray
42
+ return 0.0
43
+
44
+ frame_delta = cv2.absdiff(self.prev_frame, gray)
45
+ thresh = cv2.threshold(frame_delta, 25, 255, cv2.THRESH_BINARY)[1]
46
+ thresh = cv2.dilate(thresh, None, iterations=2)
47
+
48
+ motion_score = np.sum(thresh > 0) / thresh.size
49
+ self.prev_frame = gray
50
+
51
+ return motion_score
52
+
53
+ def detect_color_changes(self, frame):
54
+ """Detect significant color changes that might indicate tail wagging"""
55
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
56
+ lower = np.array([0, 0, 0])
57
+ upper = np.array([180, 255, 255])
58
+ mask = cv2.inRange(hsv, lower, upper)
59
+
60
+ if len(self.history) > 0:
61
+ prev_mask = self.history[-1]
62
+ diff = cv2.absdiff(mask, prev_mask)
63
+ change_score = np.sum(diff > 0) / diff.size
64
+ else:
65
+ change_score = 0.0
66
 
67
+ self.history.append(mask)
68
+ if len(self.history) > self.max_history:
69
+ self.history.pop(0)
70
+
71
+ return change_score
72
 
73
  def analyze_frame(self, frame):
74
+ """Analyze frame using motion and color change detection"""
75
+ motion_score = self.detect_motion(frame)
76
+ color_change_score = self.detect_color_changes(frame)
 
 
 
 
 
 
 
 
77
 
 
 
 
 
 
78
  detected_behaviors = []
 
 
 
 
 
79
 
80
+ # Detect tail wagging based on localized color changes
81
+ if color_change_score > self.behaviors['tail_wagging']['threshold']:
82
+ detected_behaviors.append(('tail_wagging', color_change_score))
83
+
84
+ # Detect movement
85
+ if motion_score > self.behaviors['movement']['threshold']:
86
+ detected_behaviors.append(('movement', motion_score))
87
+
88
+ # Detect stationary behavior
89
+ if motion_score < self.behaviors['stationary']['threshold']:
90
+ detected_behaviors.append(('stationary', 1.0 - motion_score))
91
+
92
+ # Detect high activity
93
+ if motion_score > self.behaviors['high_activity']['threshold']:
94
+ detected_behaviors.append(('high_activity', motion_score))
95
+
96
  return detected_behaviors
97
 
98
  def main():
99
+ st.title("🐕 Dog Behavior Analyzer")
100
+ st.write("Upload a video of your dog for behavior analysis!")
101
 
102
  analyzer = DogBehaviorAnalyzer()
103
 
 
 
 
 
 
 
 
 
 
104
  video_file = st.file_uploader("Upload Video", type=['mp4', 'avi', 'mov'])
105
 
106
  if video_file is not None:
 
136
  progress = frame_count / total_frames
137
  progress_bar.progress(progress)
138
 
139
+ # Analyze frame
 
140
  detected_behaviors = analyzer.analyze_frame(frame)
141
 
142
  # Draw behavior labels on frame
143
  y_pos = 30
144
  for behavior, conf in detected_behaviors:
145
+ behavior_counts[behavior] += 1
146
+ confidence_history[behavior].append(conf)
147
+ cv2.putText(frame,
148
+ f"{behavior.replace('_', ' ').title()}: {conf:.2f}",
149
+ (10, y_pos),
150
+ cv2.FONT_HERSHEY_SIMPLEX,
151
+ 0.7,
152
+ (0, 255, 0),
153
+ 2)
154
+ y_pos += 30
 
155
 
156
  video_placeholder.image(
157
+ cv2.cvtColor(frame, cv2.COLOR_BGR2RGB),
158
  channels="RGB",
159
  use_container_width=True
160
  )
161
 
162
+ # Update analysis display
163
  analysis_text = "Detected Behaviors:\n\n"
164
  for behavior, count in behavior_counts.items():
165
  if count > 0:
166
  avg_conf = sum(confidence_history[behavior]) / len(confidence_history[behavior])
167
  analysis_text += f"• {behavior.replace('_', ' ').title()}:\n"
168
+ analysis_text += f" Count: {count} | Confidence: {avg_conf:.2f}\n"
169
  analysis_text += f" {analyzer.behaviors[behavior]['description']}\n\n"
170
 
171
  analysis_placeholder.text_area(
 
182
  # Final analysis
183
  st.subheader("Comprehensive Analysis")
184
 
185
+ # Create metrics
186
  col1, col2, col3 = st.columns(3)
187
 
188
  with col1:
189
+ most_common = max(behavior_counts.items(), key=lambda x: x[1])[0] if any(behavior_counts.values()) else "None"
190
  st.metric("Primary Behavior", most_common.replace('_', ' ').title())
191
 
192
  with col2:
 
194
  st.metric("Total Behaviors", total_behaviors)
195
 
196
  with col3:
197
+ valid_confidences = [conf for confs in confidence_history.values() if confs for conf in confs]
198
+ avg_confidence = np.mean(valid_confidences) if valid_confidences else 0
199
  st.metric("Average Confidence", f"{avg_confidence:.2%}")
200
 
201
  # Behavior distribution chart
202
+ if any(behavior_counts.values()):
203
+ st.subheader("Behavior Distribution")
204
+ behavior_data = {k.replace('_', ' ').title(): v for k, v in behavior_counts.items() if v > 0}
205
+ st.bar_chart(behavior_data)
 
 
 
 
206
 
207
+ # Recommendations
208
+ st.subheader("Behavior Insights")
209
  recommendations = []
210
+
211
  if behavior_counts['tail_wagging'] > total_behaviors * 0.3:
212
+ recommendations.append("• Your dog shows frequent happiness - great time for positive reinforcement!")
213
+ if behavior_counts['high_activity'] > total_behaviors * 0.4:
214
+ recommendations.append("• High energy levels detected - consider more physical exercise")
215
+ if behavior_counts['stationary'] > total_behaviors * 0.5:
216
+ recommendations.append("• Your dog appears calm - good for training sessions")
217
 
218
  for rec in recommendations:
219
  st.write(rec)
220
  else:
221
+ st.write("Upload a video to see behavior analysis!")
222
 
223
  if __name__ == "__main__":
224
  main()