PrashanthB461 commited on
Commit
e2e7a3f
·
verified ·
1 Parent(s): 7a7e825

Create utils.py

Browse files
Files changed (1) hide show
  1. utils.py +157 -0
utils.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import cv2
3
+ import numpy as np
4
+ from reportlab.lib.pagesizes import letter
5
+ from reportlab.pdfgen import canvas
6
+ from reportlab.lib.units import inch
7
+ from io import BytesIO
8
+ import base64
9
+ import asyncio
10
+ import logging
11
+ from simple_salesforce import Salesforce
12
+ import tenacity
13
+ from config import CONFIG
14
+ import dlib
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ async def preprocess_frame(frame):
19
+ frame = cv2.resize(frame, CONFIG["TARGET_RESOLUTION"], interpolation=cv2.INTER_LINEAR)
20
+ frame = cv2.convertScaleAbs(frame, alpha=1.2, beta=20)
21
+ return frame
22
+
23
+ def draw_detections(frame, detections):
24
+ result_frame = frame.copy()
25
+ for det in detections:
26
+ label = det.get("violation", "Unknown")
27
+ confidence = det.get("confidence", 0.0)
28
+ x, y, w, h = det.get("bounding_box", [0, 0, 0, 0])
29
+ worker_id = det.get("worker_id", "Unknown")
30
+ x1, y1 = int(x - w/2), int(y - h/2)
31
+ x2, y2 = int(x + w/2), int(y + h/2)
32
+ color = CONFIG["CLASS_COLORS"].get(label, (0, 0, 255))
33
+ cv2.rectangle(result_frame, (x1, y1), (x2, y2), color, 3)
34
+ display_text = f"{CONFIG['DISPLAY_NAMES'].get(label, label)} (Worker {worker_id})"
35
+ text_size = cv2.getTextSize(display_text, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)[0]
36
+ cv2.rectangle(result_frame, (x1, y1-text_size[1]-10), (x1+text_size[0]+10, y1), (0, 0, 0), -1)
37
+ cv2.putText(result_frame, display_text, (x1+5, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
38
+ cv2.putText(result_frame, f"Conf: {confidence:.2f}", (x1+5, y2+20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
39
+ return result_frame
40
+
41
+ def calculate_safety_score(violations):
42
+ penalties = {
43
+ "no_helmet": 25, "no_harness": 30, "unsafe_posture": 20,
44
+ "unsafe_zone": 35, "improper_tool_use": 25
45
+ }
46
+ worker_violations = {}
47
+ for v in violations:
48
+ worker_id = v.get("worker_id", "Unknown")
49
+ worker_violations.setdefault(worker_id, set()).add(v.get("violation", "Unknown"))
50
+ total_penalty = sum(sum(penalties.get(v, 0) for v in worker_violations[wid]) for wid in worker_violations)
51
+ return max(0, 100 - total_penalty)
52
+
53
+ async def generate_violation_pdf(violations, score, output_dir):
54
+ try:
55
+ pdf_filename = f"violations_{int(asyncio.get_event_loop().time())}.pdf"
56
+ pdf_path = os.path.join(output_dir, pdf_filename)
57
+ pdf_file = BytesIO()
58
+ c = canvas.Canvas(pdf_file, pagesize=letter)
59
+ c.setFont("Helvetica-Bold", 16)
60
+ c.drawString(1 * inch, 10 * inch, "Worksite Safety Violation Report")
61
+ c.setFont("Helvetica", 12)
62
+ c.drawString(1 * inch, 9.5 * inch, f"Date: {asyncio.get_event_loop().time():.0f}")
63
+ c.setFont("Helvetica-Bold", 14)
64
+ c.drawString(1 * inch, 8.7 * inch, f"Safety Compliance Score: {score}%")
65
+ c.setFont("Helvetica", 10)
66
+ y_position = 8.2 * inch
67
+ worker_violations = {}
68
+ for v in violations:
69
+ worker_id = v.get("worker_id", "Unknown")
70
+ worker_violations.setdefault(worker_id, []).append(v)
71
+ for worker_id, worker_vios in worker_violations.items():
72
+ c.drawString(1 * inch, y_position, f"Worker {worker_id}:")
73
+ y_position -= 0.2 * inch
74
+ for v in worker_vios:
75
+ display_name = CONFIG["DISPLAY_NAMES"].get(v.get("violation", "Unknown"), "Unknown")
76
+ c.drawString(1.2 * inch, y_position, f" - {display_name} at {v.get('timestamp', 0.0):.2f}s (Conf: {v.get('confidence', 0.0):.2f})")
77
+ y_position -= 0.2 * inch
78
+ if y_position < 1 * inch:
79
+ c.showPage()
80
+ y_position = 10 * inch
81
+ c.save()
82
+ pdf_file.seek(0)
83
+ with open(pdf_path, "wb") as f:
84
+ f.write(pdf_file.getvalue())
85
+ return pdf_path, f"{CONFIG['PUBLIC_URL_BASE']}{pdf_filename}", pdf_file
86
+ except Exception as e:
87
+ logger.error(f"Error generating PDF: {e}")
88
+ return "", "", None
89
+
90
+ @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(2))
91
+ async def connect_to_salesforce():
92
+ sf = Salesforce(**CONFIG["SF_CREDENTIALS"])
93
+ logger.info("Connected to Salesforce")
94
+ return sf
95
+
96
+ async def upload_pdf_to_salesforce(sf, pdf_file, record_id):
97
+ try:
98
+ encoded_pdf = base64.b64encode(pdf_file.getvalue()).decode('utf-8')
99
+ content_version = sf.ContentVersion.create({
100
+ "Title": f"Safety_Violation_Report_{int(asyncio.get_event_loop().time())}",
101
+ "PathOnClient": f"safety_violation_{int(asyncio.get_event_loop().time())}.pdf",
102
+ "VersionData": encoded_pdf,
103
+ "FirstPublishLocationId": record_id
104
+ })
105
+ result = sf.query(f"SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id = '{content_version['id']}'")
106
+ return f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{content_version['id']}"
107
+ except Exception as e:
108
+ logger.error(f"Error uploading PDF to Salesforce: {e}")
109
+ return ""
110
+
111
+ async def push_report_to_salesforce(violations, score, pdf_path, pdf_file):
112
+ try:
113
+ sf = await connect_to_salesforce()
114
+ violations_text = "".join(
115
+ f"Worker {v.get('worker_id', 'Unknown')}: {CONFIG['DISPLAY_NAMES'].get(v.get('violation', 'Unknown'), 'Unknown')} at {v.get('timestamp', 0.0):.2f}s (Conf: {v.get('confidence', 0.0):.2f})\n"
116
+ for v in violations
117
+ ) or "No violations detected."
118
+ record_data = {
119
+ "Compliance_Score__c": score,
120
+ "Violations_Found__c": len(violations),
121
+ "Violations_Details__c": violations_text,
122
+ "Status__c": "Pending",
123
+ "PDF_Report_URL__c": f"{CONFIG['PUBLIC_URL_BASE']}{os.path.basename(pdf_path)}" if pdf_path else ""
124
+ }
125
+ record = sf.Safety_Video_Report__c.create(record_data)
126
+ if pdf_file:
127
+ uploaded_url = await upload_pdf_to_salesforce(sf, pdf_file, record["id"])
128
+ if uploaded_url:
129
+ sf.Safety_Video_Report__c.update(record["id"], {"PDF_Report_URL__c": uploaded_url})
130
+ return record["id"], uploaded_url or record_data["PDF_Report_URL__c"]
131
+ except Exception as e:
132
+ logger.error(f"Salesforce record creation failed: {e}")
133
+ return "N/A", "Salesforce integration failed."
134
+
135
+ @tenacity.retry(
136
+ stop=tenacity.stop_after_attempt(3),
137
+ wait=tenacity.wait_fixed(1),
138
+ retry=tenacity.retry_if_exception_type((IOError, OSError))
139
+ )
140
+ def verify_and_open_video(video_path):
141
+ if not os.path.exists(video_path) or os.path.getsize(video_path) == 0:
142
+ raise ValueError(f"Invalid video file: {video_path}")
143
+ cap = cv2.VideoCapture(video_path)
144
+ if not cap.isOpened():
145
+ raise ValueError("Could not open video file.")
146
+ return cap
147
+
148
+ def blur_faces(frame):
149
+ detector = dlib.get_frontal_face_detector()
150
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
151
+ faces = detector(gray)
152
+ for face in faces:
153
+ x, y, w, h = face.left(), face.top(), face.width(), face.height()
154
+ roi = frame[y:y+h, x:x+w]
155
+ roi = cv2.GaussianBlur(roi, (23, 23), 30)
156
+ frame[y:y+h, x:x+w] = roi
157
+ return frame