PrashanthB461 commited on
Commit
de9b54b
·
verified ·
1 Parent(s): 7a9da38

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -56
app.py CHANGED
@@ -24,7 +24,8 @@ CONFIG = {
24
  "VIOLATION_LABELS": {
25
  0: "no_helmet",
26
  1: "no_harness",
27
- 2: "unsafe_posture"
 
28
  },
29
  "SF_CREDENTIALS": {
30
  "username": "prashanth1ai@safety.com",
@@ -33,7 +34,8 @@ CONFIG = {
33
  "domain": "login"
34
  },
35
  "PUBLIC_URL_BASE": "https://huggingface.co/spaces/PrashanthB461/AI_Safety_Demo1/resolve/main/static/output/",
36
- "MAX_PROCESSING_TIME": 60 # Set to 60 seconds for 1-minute video
 
37
  }
38
 
39
  # Setup logging
@@ -178,7 +180,7 @@ def push_report_to_salesforce(violations, score, pdf_path, pdf_file):
178
  logger.info(f"Salesforce record created: {record_id}")
179
 
180
  if pdf_file:
181
- uploaded_url = upload_pdf_to_salesforce(sf, pdf_file, record_id)
182
  if uploaded_url:
183
  try:
184
  sf.Safety_Video_Report__c.update(record_id, {"PDF_Report_URL__c": uploaded_url})
@@ -196,17 +198,17 @@ def push_report_to_salesforce(violations, score, pdf_path, pdf_file):
196
  # ==========================
197
  # Safety Score Calculation
198
  # ==========================
199
- def calculate_safety_score(violations, total_frames):
200
  penalties = {
201
- "no_helmet": 25 / max(total_frames, 1), # Normalize penalty by video length
202
- "no_harness": 30 / max(total_frames, 1),
203
- "unsafe_posture": 20 / max(total_frames, 1)
204
  }
205
  score = 100
206
  for v in violations:
207
- penalty = penalties.get(v["violation"], 0)
208
- score -= penalty
209
- return max(round(score, 2), 0)
210
 
211
  # ==========================
212
  # Video Processing
@@ -224,30 +226,28 @@ def process_video(video_data):
224
 
225
  violations, snapshots = [], []
226
  frame_count = 0
227
- total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
228
- fps = video.get(cv2.CAP_PROP_FPS)
229
- video_duration = total_frames / max(fps, 1)
230
- logger.info(f"Video duration: {video_duration:.2f} seconds, Total frames: {total_frames}, FPS: {fps:.2f}")
231
-
232
  start_time = time.time()
233
- max_frames = int(fps * CONFIG["MAX_PROCESSING_TIME"]) # Max frames for 60 seconds
 
234
 
235
  while True:
236
  ret, frame = video.read()
237
- if not ret:
238
- logger.info(f"End of video reached at frame {frame_count}")
239
- break
240
- if frame_count >= max_frames:
241
- logger.info(f"Reached maximum processing limit at frame {frame_count}")
242
  break
243
 
 
 
 
 
244
  results = model(frame, device=device)
245
  seen_violations = set()
246
  for result in results:
247
  for box in result.boxes:
248
  cls, conf = int(box.cls), float(box.conf)
249
  label = CONFIG["VIOLATION_LABELS"].get(cls, f"class_{cls}")
250
- if label in seen_violations or label not in ["no_helmet", "no_harness", "unsafe_posture"]:
 
 
251
  continue
252
  seen_violations.add(label)
253
 
@@ -256,10 +256,9 @@ def process_video(video_data):
256
  "violation": label,
257
  "confidence": round(conf, 2),
258
  "bounding_box": [round(x, 2) for x in box.xywh.cpu().numpy()[0]],
259
- "timestamp": frame_count / max(fps, 1)
260
  }
261
  violations.append(violation)
262
- logger.debug(f"Violation detected: {label} at frame {frame_count}, timestamp {violation['timestamp']:.2f}s")
263
 
264
  snapshot_path = os.path.join(CONFIG["OUTPUT_DIR"], f"snapshot_{frame_count}_{label}.jpg")
265
  cv2.imwrite(snapshot_path, frame)
@@ -274,13 +273,20 @@ def process_video(video_data):
274
 
275
  frame_count += 1
276
 
277
- processing_time = time.time() - start_time
278
- logger.info(f"Processed {frame_count} frames in {processing_time:.2f} seconds")
279
-
280
  video.release()
281
  os.remove(video_path)
282
- score = calculate_safety_score(violations, frame_count)
283
- logger.info(f"Safety score calculated: {score}% with {len(violations)} violations")
 
 
 
 
 
 
 
 
 
 
284
  pdf_path, pdf_url, pdf_file = generate_violation_pdf(violations, score)
285
  report_id, final_pdf_url = push_report_to_salesforce(violations, score, pdf_path, pdf_file)
286
 
@@ -289,20 +295,16 @@ def process_video(video_data):
289
  "snapshots": snapshots,
290
  "score": score,
291
  "salesforce_record_id": report_id,
292
- "violation_details_url": final_pdf_url,
293
- "processed_frames": frame_count,
294
- "video_duration": video_duration
295
  }
296
  except Exception as e:
297
- logger.error(f"Error processing video: {e}", exc_info=True)
298
  return {
299
  "violations": [],
300
  "snapshots": [],
301
- "score": 0,
302
  "salesforce_record_id": None,
303
- "violation_details_url": "",
304
- "processed_frames": 0,
305
- "video_duration": 0
306
  }
307
 
308
  # ==========================
@@ -310,7 +312,7 @@ def process_video(video_data):
310
  # ==========================
311
  def gradio_interface(video_file):
312
  if not video_file:
313
- return "No file uploaded.", "", "No file uploaded.", "", "", ""
314
  try:
315
  with open(video_file, "rb") as f:
316
  video_data = f.read()
@@ -318,25 +320,19 @@ def gradio_interface(video_file):
318
 
319
  violation_table = "No violations detected."
320
  if result["violations"]:
321
- header = "| Violation | Timestamp | Confidence | Bounding Box | Violation Details |\n"
322
- separator = "|------------------|-----------|------------|--------------------------|-------------------------|\n"
323
  rows = []
324
  for v in result["violations"]:
325
- violation_name = v["violation"]
326
- if violation_name == "no_helmet":
327
- violation_name = "Missing Helmet"
328
- elif violation_name == "no_harness":
329
- violation_name = "Missing Harness"
330
- else:
331
- violation_name = "Unsafe Posture"
332
- row = f"| {violation_name:<16} | {v['timestamp']:.2f}s | {v['confidence']:.2f} | {v['bounding_box']} | {result['violation_details_url']} |"
333
  rows.append(row)
334
  violation_table = header + separator + "\n".join(rows)
335
 
336
  snapshots_text = "No snapshots captured."
337
  if result["snapshots"]:
338
  snapshots_text = "\n".join(
339
- f"- Snapshot for {s['violation'].replace('no_helmet', 'Missing Helmet').replace('no_harness', 'Missing Harness').replace('unsafe_posture', 'Unsafe Posture')} at frame {s['frame']}: ![]({s['snapshot_base64']})"
340
  for s in result["snapshots"]
341
  )
342
 
@@ -345,26 +341,24 @@ def gradio_interface(video_file):
345
  f"Safety Score: {result['score']}%",
346
  snapshots_text,
347
  f"Salesforce Record ID: {result['salesforce_record_id'] or 'N/A'}",
348
- result["violation_details_url"] or "N/A",
349
- f"Processed {result['processed_frames']} frames (Video duration: {result['video_duration']:.2f} seconds)"
350
  )
351
  except Exception as e:
352
  logger.error(f"Error in Gradio interface: {e}", exc_info=True)
353
- return f"Error: {str(e)}", "", "Error in processing.", "", "", ""
354
 
355
  interface = gr.Interface(
356
  fn=gradio_interface,
357
- inputs=gr.Video(label="Upload Site Video (Up to 1 Minute)"),
358
  outputs=[
359
  gr.Markdown(label="Detected Safety Violations"),
360
  gr.Textbox(label="Compliance Score"),
361
  gr.Markdown(label="Snapshots"),
362
  gr.Textbox(label="Salesforce Record ID"),
363
- gr.Textbox(label="Violation Details URL"),
364
- gr.Textbox(label="Processing Summary")
365
  ],
366
  title="Worksite Safety Violation Analyzer",
367
- description="Upload a video (up to 1 minute) to detect safety violations (missing helmet, missing harness, unsafe posture). Violations are only recorded when safety gear is missing or posture is unsafe."
368
  )
369
 
370
  if __name__ == "__main__":
 
24
  "VIOLATION_LABELS": {
25
  0: "no_helmet",
26
  1: "no_harness",
27
+ 2: "unsafe_posture",
28
+ 3: "unsafe_zone" # Ignored in scoring
29
  },
30
  "SF_CREDENTIALS": {
31
  "username": "prashanth1ai@safety.com",
 
34
  "domain": "login"
35
  },
36
  "PUBLIC_URL_BASE": "https://huggingface.co/spaces/PrashanthB461/AI_Safety_Demo1/resolve/main/static/output/",
37
+ "FRAME_SKIP": 5,
38
+ "MAX_PROCESSING_TIME": 30
39
  }
40
 
41
  # Setup logging
 
180
  logger.info(f"Salesforce record created: {record_id}")
181
 
182
  if pdf_file:
183
+ uploaded_url = upload_pdf_to_salesforce(sf, pdf_file, report_id)
184
  if uploaded_url:
185
  try:
186
  sf.Safety_Video_Report__c.update(record_id, {"PDF_Report_URL__c": uploaded_url})
 
198
  # ==========================
199
  # Safety Score Calculation
200
  # ==========================
201
+ def calculate_safety_score(violations):
202
  penalties = {
203
+ "no_helmet": 25,
204
+ "no_harness": 30,
205
+ "unsafe_posture": 20
206
  }
207
  score = 100
208
  for v in violations:
209
+ if v["violation"] in penalties:
210
+ score -= penalties[v["violation"]]
211
+ return max(score, 0)
212
 
213
  # ==========================
214
  # Video Processing
 
226
 
227
  violations, snapshots = [], []
228
  frame_count = 0
 
 
 
 
 
229
  start_time = time.time()
230
+ fps = video.get(cv2.CAP_PROP_FPS)
231
+ max_frames = int(CONFIG["MAX_PROCESSING_TIME"] * fps)
232
 
233
  while True:
234
  ret, frame = video.read()
235
+ if not ret or frame_count >= max_frames:
 
 
 
 
236
  break
237
 
238
+ if frame_count % CONFIG["FRAME_SKIP"] != 0:
239
+ frame_count += 1
240
+ continue
241
+
242
  results = model(frame, device=device)
243
  seen_violations = set()
244
  for result in results:
245
  for box in result.boxes:
246
  cls, conf = int(box.cls), float(box.conf)
247
  label = CONFIG["VIOLATION_LABELS"].get(cls, f"class_{cls}")
248
+ if label not in ["no_helmet", "no_harness", "unsafe_posture"]:
249
+ continue
250
+ if label in seen_violations:
251
  continue
252
  seen_violations.add(label)
253
 
 
256
  "violation": label,
257
  "confidence": round(conf, 2),
258
  "bounding_box": [round(x, 2) for x in box.xywh.cpu().numpy()[0]],
259
+ "timestamp": frame_count / fps
260
  }
261
  violations.append(violation)
 
262
 
263
  snapshot_path = os.path.join(CONFIG["OUTPUT_DIR"], f"snapshot_{frame_count}_{label}.jpg")
264
  cv2.imwrite(snapshot_path, frame)
 
273
 
274
  frame_count += 1
275
 
 
 
 
276
  video.release()
277
  os.remove(video_path)
278
+
279
+ if not violations:
280
+ logger.info("No violations detected, skipping score calculation and reporting")
281
+ return {
282
+ "violations": [],
283
+ "snapshots": [],
284
+ "score": 100,
285
+ "salesforce_record_id": None,
286
+ "violation_details_url": ""
287
+ }
288
+
289
+ score = calculate_safety_score(violations)
290
  pdf_path, pdf_url, pdf_file = generate_violation_pdf(violations, score)
291
  report_id, final_pdf_url = push_report_to_salesforce(violations, score, pdf_path, pdf_file)
292
 
 
295
  "snapshots": snapshots,
296
  "score": score,
297
  "salesforce_record_id": report_id,
298
+ "violation_details_url": final_pdf_url
 
 
299
  }
300
  except Exception as e:
301
+ logger.error(f"Error processing video: {e}")
302
  return {
303
  "violations": [],
304
  "snapshots": [],
305
+ "score": 100,
306
  "salesforce_record_id": None,
307
+ "violation_details_url": ""
 
 
308
  }
309
 
310
  # ==========================
 
312
  # ==========================
313
  def gradio_interface(video_file):
314
  if not video_file:
315
+ return "No file uploaded.", "", "No file uploaded.", "", ""
316
  try:
317
  with open(video_file, "rb") as f:
318
  video_data = f.read()
 
320
 
321
  violation_table = "No violations detected."
322
  if result["violations"]:
323
+ header = "| Violation | Timestamp | Confidence | Bounding Box | Violation Details |\n"
324
+ separator = "|---------------|-----------|------------|--------------------------|-------------------------|\n"
325
  rows = []
326
  for v in result["violations"]:
327
+ violation_name = v["violation"].replace("no_", "").replace("unsafe_", "")
328
+ row = f"| {violation_name:<13} | {v['timestamp']:.2f}s | {v['confidence']:.2f} | {v['bounding_box']} | {result['violation_details_url']} |"
 
 
 
 
 
 
329
  rows.append(row)
330
  violation_table = header + separator + "\n".join(rows)
331
 
332
  snapshots_text = "No snapshots captured."
333
  if result["snapshots"]:
334
  snapshots_text = "\n".join(
335
+ f"- Snapshot for {s['violation'].replace('no_', '').replace('unsafe_', '')} at frame {s['frame']}: ![]({s['snapshot_base64']})"
336
  for s in result["snapshots"]
337
  )
338
 
 
341
  f"Safety Score: {result['score']}%",
342
  snapshots_text,
343
  f"Salesforce Record ID: {result['salesforce_record_id'] or 'N/A'}",
344
+ result["violation_details_url"] or "N/A"
 
345
  )
346
  except Exception as e:
347
  logger.error(f"Error in Gradio interface: {e}", exc_info=True)
348
+ return f"Error: {str(e)}", "", "Error in processing.", "", ""
349
 
350
  interface = gr.Interface(
351
  fn=gradio_interface,
352
+ inputs=gr.Video(label="Upload Site Video"),
353
  outputs=[
354
  gr.Markdown(label="Detected Safety Violations"),
355
  gr.Textbox(label="Compliance Score"),
356
  gr.Markdown(label="Snapshots"),
357
  gr.Textbox(label="Salesforce Record ID"),
358
+ gr.Textbox(label="Violation Details URL")
 
359
  ],
360
  title="Worksite Safety Violation Analyzer",
361
+ description="Upload site videos to detect safety violations (e.g., no helmet, no harness, unsafe posture)."
362
  )
363
 
364
  if __name__ == "__main__":