IDSL_Road_Safety / utils.py
lokesh341's picture
Update utils.py
d4a9f88 verified
import matplotlib.pyplot as plt
import numpy as np
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
import os
from datetime import datetime
from reportlab.platypus import Table, TableStyle
def create_percentage_circle(percentage, title):
"""
Create a circular progress bar for percentage visualization.
"""
fig, ax = plt.subplots(figsize=(4, 4))
ax.set_aspect("equal")
circle = plt.Circle((0.5, 0.5), 0.4, color="lightgray")
ax.add_patch(circle)
theta = np.linspace(0, 360 * (percentage / 100), 100)
x = 0.5 + 0.4 * np.cos(np.radians(theta))
y = 0.5 + 0.4 * np.sin(np.radians(theta))
ax.plot(x, y, color="blue", linewidth=20)
ax.text(0.5, 0.5, f"{percentage:.1f}%", ha="center", va="center", fontsize=20)
ax.set_title(title, fontsize=12)
ax.axis("off")
output_path = f"screenshots/circle_{int(percentage)}_{int(np.random.randint(1000))}.png"
plt.savefig(output_path, bbox_inches="tight")
plt.close()
return output_path
def generate_pdf_report(summary, screenshots, output_path, zip_path, circle_path):
"""
Generate a PDF report with summary, object counts, charts, screenshots, and video ZIP link.
"""
c = canvas.Canvas(output_path, pagesize=letter)
width, height = letter
# Title page
c.setFont("Helvetica-Bold", 22)
c.drawCentredString(width / 2, height - 80, "Road Safety Analysis Report")
c.setFont("Helvetica", 14)
c.drawCentredString(width / 2, height - 110, f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
c.showPage()
# Summary section
c.setFont("Helvetica-Bold", 16)
c.drawString(50, height - 60, "Analysis Summary")
c.setFont("Helvetica", 12)
y = height - 90
for line in summary.split('\n'):
if line.strip():
c.drawString(70, y, line.strip())
y -= 20
if y < 50:
c.showPage()
y = height - 50
c.showPage()
# Object Counts section
c.setFont("Helvetica-Bold", 16)
c.drawString(50, height - 60, "Object Counts")
c.setFont("Helvetica", 12)
y = height - 90
data = [["Object", "Count"]]
lines = [line for line in summary.split('\n') if line.strip().startswith("- ") and "Object Counts" not in line]
counts = {}
for line in lines:
if ": " in line:
key, value = line.split(": ", 1)
key = key.replace("-", "").strip()
try:
counts[key] = int(value)
except ValueError:
counts[key] = 0
for obj in ["Motorcycles", "Persons", "Cars", "Traffic Lights", "Signs", "Trucks"]:
data.append([obj, counts.get(obj, 0)])
table = Table(data, colWidths=[150, 50], rowHeights=25)
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), '#ECF0F1'),
('TEXTCOLOR', (0, 0), (-1, 0), '#2C3E50'),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
('FONTSIZE', (0, 0), (-1, -1), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), '#FFFFFF'),
('GRID', (0, 0), (-1, -1), 1, '#BDC3C7')
]))
table.wrapOn(c, width, height)
table.drawOn(c, 50, y - 180)
y -= 230
c.showPage()
# Charts section
if os.path.exists(circle_path):
c.setFont("Helvetica-Bold", 16)
c.drawString(50, height - 60, "Visualizations")
c.setFont("Helvetica", 12)
y = height - 90
# Pedestrian Confidence Metric
if os.path.exists(circle_path):
img = ImageReader(circle_path)
img_width = 200
img_height = img_width * (img.getSize()[1] / img.getSize()[0])
c.drawImage(circle_path, 50, y - img_height, width=img_width, height=img_height)
c.drawString(50, y - img_height - 20, "Pedestrian Confidence Metric")
y -= img_height + 40
# Object Distribution Pie Chart
pie_chart_path = [s for s in screenshots if "pie_chart" in s.lower()]
if pie_chart_path:
pie_chart_path = pie_chart_path[0]
if os.path.exists(pie_chart_path):
img = ImageReader(pie_chart_path)
img_width = 500
img_height = img_width * (img.getSize()[1] / img.getSize()[0])
if y - img_height < 50:
c.showPage()
y = height - 50
c.drawImage(pie_chart_path, 50, y - img_height, width=img_width, height=img_height)
c.drawString(50, y - img_height - 20, "Object Distribution Pie Chart")
y -= img_height + 40
c.showPage()
# Incident Screenshots section (top 15 HD)
if screenshots:
c.setFont("Helvetica-Bold", 16)
c.drawString(50, height - 60, "Top 15 HD Incident Screenshots")
c.setFont("Helvetica", 12)
y = height - 90
for i, screenshot in enumerate(screenshots[:15]):
if os.path.exists(screenshot) and "pie_chart" not in screenshot.lower() and "circle" not in screenshot.lower():
img = ImageReader(screenshot)
img_width = 350
img_height = img_width * (img.getSize()[1] / img.getSize()[0])
if y - img_height < 50:
c.showPage()
y = height - 50
c.drawImage(screenshot, 50, y - img_height, width=img_width, height=img_height)
c.drawString(50, y - img_height - 20, f"Incident {i+1}")
y -= img_height + 40
# Video ZIP download section
if os.path.exists(zip_path):
c.showPage()
c.setFont("Helvetica-Bold", 16)
c.drawString(50, height - 60, "Download Annotated HD Video")
c.setFont("Helvetica", 12)
c.drawString(70, height - 90, f"Download the annotated video: {os.path.basename(zip_path)}")
c.save()