Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -162,249 +162,217 @@ def generate_report(
|
|
162 |
inference_times: List[float],
|
163 |
io_times: List[float]
|
164 |
) -> str:
|
165 |
-
|
166 |
-
|
|
|
|
|
167 |
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
168 |
|
169 |
-
#
|
170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
for item in metrics.get("items", []):
|
172 |
percentage = (item["count"] / metrics["total_detections"] * 100) if metrics["total_detections"] > 0 else 0
|
173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
|
175 |
-
# Prepare image rows with embedded images
|
176 |
-
image_rows = []
|
177 |
for detection in all_detections[:100]:
|
178 |
-
|
179 |
-
|
180 |
-
f"{detection['frame']:06d} & {detection['label']} & "
|
181 |
-
f"({detection['gps'][0]:.6f}, {detection['gps'][1]:.6f}) & "
|
182 |
-
f"{detection['timestamp']} & {detection['conf']:.2f} & "
|
183 |
-
f"\\includegraphics[width=4cm, height=3cm, keepaspectratio]{{{image_basename}}} \\\\"
|
184 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
|
186 |
-
# Prepare flight log rows
|
187 |
-
log_rows = []
|
188 |
for detection in all_detections[:100]:
|
189 |
log_path = f"flight_logs/flight_log_{detection['frame']:06d}.csv"
|
190 |
-
|
191 |
-
|
192 |
-
f"{detection['gps'][0]:.6f} & {detection['gps'][1]:.6f} & "
|
193 |
-
f"5.0 & 12 & 60 & \\texttt{{{log_path}}} \\\\"
|
194 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
196 |
-
# Prepare log entries
|
197 |
-
log_entries_str = []
|
198 |
for entry in log_entries[-10:]:
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
\
|
210 |
-
\
|
211 |
-
\
|
212 |
-
\
|
213 |
-
\
|
214 |
-
\
|
215 |
-
\
|
216 |
-
\
|
217 |
-
\
|
218 |
-
\
|
219 |
-
|
220 |
-
\setlength{{\parskip}}{{0.5em}}
|
221 |
-
\usepackage{{noto}}
|
222 |
-
\graphicspath{{{{./captured_frames/}}}}
|
223 |
-
|
224 |
-
\begin{{document}}
|
225 |
-
|
226 |
-
% Title and project details
|
227 |
-
\section*{{NHAI Drone Survey Analysis Report}}
|
228 |
-
|
229 |
-
\subsection*{{Project Details}}
|
230 |
-
\begin{{itemize}}
|
231 |
-
\item \textbf{{Project Name:}} NH-44 Delhi-Hyderabad Section (Package XYZ)
|
232 |
-
\item \textbf{{Highway Section:}} Km 100 to Km 150
|
233 |
-
\item \textbf{{State:}} Telangana
|
234 |
-
\item \textbf{{Region:}} South
|
235 |
-
\item \textbf{{Survey Date:}} \today
|
236 |
-
\item \textbf{{Drone Service Provider:}} ABC Drone Services Pvt. Ltd.
|
237 |
-
\item \textbf{{Technology Service Provider:}} XYZ AI Analytics Ltd.
|
238 |
-
\item \textbf{{Work Order Reference:}} Data Lake WO-\today-XYZ
|
239 |
-
\item \textbf{{Report Prepared By:}} Nagasurendra, Data Analyst
|
240 |
-
\item \textbf{{Report Date:}} \today
|
241 |
-
\end{{itemize}}
|
242 |
-
|
243 |
-
\section{{Introduction}}
|
244 |
-
This report consolidates drone survey results for NH-44 (Km 100--150) under Operations \& Maintenance, per NHAI Policy Circular No. 18.98/2024, detecting potholes and cracks using YOLOv8 for Monthly Progress Report integration.
|
245 |
-
|
246 |
-
\section{{Drone Survey Metadata}}
|
247 |
-
\begin{{itemize}}
|
248 |
-
\item \textbf{{Drone Speed:}} 5 m/s
|
249 |
-
\item \textbf{{Drone Height:}} 60 m
|
250 |
-
\item \textbf{{Camera Sensor:}} RGB, 12 MP
|
251 |
-
\item \textbf{{Recording Type:}} JPEG, 90° nadir
|
252 |
-
\item \textbf{{Image Overlap:}} 85\%
|
253 |
-
\item \textbf{{Flight Pattern:}} Single lap, ROW centered
|
254 |
-
\item \textbf{{Geotagging:}} Enabled
|
255 |
-
\item \textbf{{Satellite Lock:}} 12 satellites
|
256 |
-
\item \textbf{{Terrain Follow Mode:}} Enabled
|
257 |
-
\end{{itemize}}
|
258 |
-
|
259 |
-
\section{{Quality Check Results}}
|
260 |
-
\begin{{itemize}}
|
261 |
-
\item \textbf{{Resolution:}} 4000x3000 (12 MP)
|
262 |
-
\item \textbf{{Overlap:}} 85\%
|
263 |
-
\item \textbf{{Camera Angle:}} 90° nadir
|
264 |
-
\item \textbf{{Drone Speed:}} $\leq$ 5 m/s
|
265 |
-
\item \textbf{{Geotagging:}} 100\% compliant
|
266 |
-
\item \textbf{{QC Status:}} Passed
|
267 |
-
\end{{itemize}}
|
268 |
-
|
269 |
-
\section{{AI/ML Analytics}}
|
270 |
-
\begin{{itemize}}
|
271 |
-
\item \textbf{{Total Frames Processed:}} {frame_count}
|
272 |
-
\item \textbf{{Detection Frames:}} {detection_frame_count} ({detection_percentage:.2f}\%)
|
273 |
-
\item \textbf{{Total Detections:}} {total_detections}
|
274 |
-
\item \textbf{{Breakdown:}}
|
275 |
-
\begin{{itemize}}
|
276 |
-
{items}
|
277 |
-
\end{{itemize}}
|
278 |
-
\item \textbf{{Processing Time:}} {total_time:.2f} seconds
|
279 |
-
\item \textbf{{Average Frame Time:}} {avg_frame_time:.2f} ms
|
280 |
-
\item \textbf{{Average Resize Time:}} {avg_resize_time:.2f} ms
|
281 |
-
\item \textbf{{Average Inference Time:}} {avg_inference_time:.2f} ms
|
282 |
-
\item \textbf{{Average I/O Time:}} {avg_io_time:.2f} ms
|
283 |
-
\item \textbf{{Timestamp:}} {timestamp_str}
|
284 |
-
\item \textbf{{Summary:}} Potholes and cracks detected in high-traffic segments.
|
285 |
-
\end{{itemize}}
|
286 |
-
|
287 |
-
\section{{Output File Structure}}
|
288 |
-
\begin{{itemize}}
|
289 |
-
\item ZIP file contains:
|
290 |
-
\begin{{itemize}}
|
291 |
-
\item \texttt{{drone_analysis_report_{timestamp}.pdf}}: This report
|
292 |
-
\item \texttt{{outputs/processed_output.mp4}}: Processed video with annotations
|
293 |
-
\item \texttt{{outputs/chart_{timestamp}.png}}: Detection trend chart
|
294 |
-
\item \texttt{{outputs/map_{timestamp}.png}}: Issue locations map
|
295 |
-
\item \texttt{{captured_frames/detected_<frame>.jpg}}: Geotagged images for detected issues
|
296 |
-
\item \texttt{{flight_logs/flight_log_<frame>.csv}}: Flight logs matching image frames
|
297 |
-
\end{{itemize}}
|
298 |
-
\item \textbf{{Note:}} Images and logs share frame numbers (e.g., \texttt{{detected_000001.jpg}} corresponds to \texttt{{flight_log_000001.csv}}).
|
299 |
-
\end{{itemize}}
|
300 |
-
|
301 |
-
\section{{Geotagged Images}}
|
302 |
-
\begin{{itemize}}
|
303 |
-
\item \textbf{{Total Images:}} {total_images}
|
304 |
-
\item \textbf{{Storage:}} Data Lake \texttt{{/project_xyz/images/{date_str}}}
|
305 |
-
\end{{itemize}}
|
306 |
-
|
307 |
-
\begin{{longtable}}{{c l c c c p{{4cm}}}}
|
308 |
-
\toprule
|
309 |
-
\textbf{{Frame}} & \textbf{{Issue Type}} & \textbf{{GPS (Lat, Lon)}} & \textbf{{Timestamp}} & \textbf{{Confidence}} & \textbf{{Image}} \\
|
310 |
-
\midrule
|
311 |
-
\endhead
|
312 |
-
{image_rows}
|
313 |
-
\bottomrule
|
314 |
-
\end{{longtable}}
|
315 |
-
|
316 |
-
\section{{Flight Logs}}
|
317 |
-
\begin{{itemize}}
|
318 |
-
\item \textbf{{Total Logs:}} {total_logs}
|
319 |
-
\item \textbf{{Storage:}} Data Lake \texttt{{/project_xyz/flight_logs/{date_str}}}
|
320 |
-
\end{{itemize}}
|
321 |
-
|
322 |
-
\begin{{longtable}}{{c c c c c c c l}}
|
323 |
-
\toprule
|
324 |
-
\textbf{{Frame}} & \textbf{{Timestamp}} & \textbf{{Latitude}} & \textbf{{Longitude}} & \textbf{{Speed (m/s)}} & \textbf{{Satellites}} & \textbf{{Altitude (m)}} & \textbf{{Log Path}} \\
|
325 |
-
\midrule
|
326 |
-
\endhead
|
327 |
-
{log_rows}
|
328 |
-
\bottomrule
|
329 |
-
\end{{longtable}}
|
330 |
-
|
331 |
-
\section{{Processed Video}}
|
332 |
-
\begin{{itemize}}
|
333 |
-
\item \textbf{{Path:}} \texttt{{outputs/processed_output.mp4}}
|
334 |
-
\item \textbf{{Frames:}} {output_frames}
|
335 |
-
\item \textbf{{FPS:}} {output_fps:.2f}
|
336 |
-
\item \textbf{{Duration:}} {output_duration:.2f} seconds
|
337 |
-
\end{{itemize}}
|
338 |
-
|
339 |
-
\section{{Visualizations}}
|
340 |
-
\begin{{itemize}}
|
341 |
-
\item \textbf{{Detection Trend Chart:}} \texttt{{outputs/chart_{timestamp}.png}}
|
342 |
-
\item \textbf{{Issue Locations Map:}} \texttt{{outputs/map_{timestamp}.png}}
|
343 |
-
\end{{itemize}}
|
344 |
-
|
345 |
-
\section{{Processing Timestamps}}
|
346 |
-
\begin{{itemize}}
|
347 |
-
\item \textbf{{Total Processing Time:}} {total_time:.2f} seconds
|
348 |
-
\item \textbf{{Log Entries (Last 10):}}
|
349 |
-
\begin{{itemize}}
|
350 |
-
{log_entries}
|
351 |
-
\end{{itemize}}
|
352 |
-
\end{{itemize}}
|
353 |
-
|
354 |
-
\section{{Stakeholder Validation}}
|
355 |
-
\begin{{itemize}}
|
356 |
-
\item \textbf{{AE/IE Comments:}} [Pending]
|
357 |
-
\item \textbf{{PD/RO Comments:}} [Pending]
|
358 |
-
\end{{itemize}}
|
359 |
-
|
360 |
-
\section{{Recommendations}}
|
361 |
-
\begin{{itemize}}
|
362 |
-
\item Repair potholes in high-traffic segments.
|
363 |
-
\item Seal cracks to prevent degradation.
|
364 |
-
\item Schedule follow-up survey.
|
365 |
-
\end{{itemize}}
|
366 |
-
|
367 |
-
\section{{Data Lake References}}
|
368 |
-
\begin{{itemize}}
|
369 |
-
\item \textbf{{Images:}} \texttt{{/project_xyz/images/{date_str}}}
|
370 |
-
\item \textbf{{Flight Logs:}} \texttt{{/project_xyz/flight_logs/{date_str}}}
|
371 |
-
\item \textbf{{Video:}} \texttt{{/project_xyz/videos/processed_output_{date_str_no_dash}.mp4}}
|
372 |
-
\item \textbf{{DAMS Dashboard:}} \texttt{{/project_xyz/dams/{date_str}}}
|
373 |
-
\end{{itemize}}
|
374 |
-
|
375 |
-
\end{{document}}
|
376 |
-
"""
|
377 |
-
|
378 |
-
# Format the LaTeX template
|
379 |
-
report_content = latex_template.format(
|
380 |
-
frame_count=frame_count,
|
381 |
-
detection_frame_count=detection_frame_count,
|
382 |
-
detection_percentage=(detection_frame_count / frame_count * 100) if frame_count > 0 else 0,
|
383 |
-
total_detections=metrics['total_detections'],
|
384 |
-
items="\n ".join(items),
|
385 |
-
total_time=total_time,
|
386 |
-
avg_frame_time=avg_frame_time,
|
387 |
-
avg_resize_time=avg_resize_time,
|
388 |
-
avg_inference_time=avg_inference_time,
|
389 |
-
avg_io_time=avg_io_time,
|
390 |
-
timestamp_str=metrics.get('timestamp', 'N/A'),
|
391 |
-
timestamp=timestamp,
|
392 |
-
total_images=len(detected_issues),
|
393 |
-
total_logs=len(detected_issues),
|
394 |
-
date_str=datetime.now().strftime('%Y-%m-%d'),
|
395 |
-
date_str_no_dash=datetime.now().strftime('%Y%m%d'),
|
396 |
-
image_rows="\n ".join(image_rows),
|
397 |
-
log_rows="\n ".join(log_rows),
|
398 |
-
log_entries="\n ".join(log_entries_str)
|
399 |
-
)
|
400 |
|
401 |
try:
|
402 |
-
|
403 |
-
|
404 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
return report_path
|
406 |
except Exception as e:
|
407 |
-
log_entries.append(f"Error: Failed to
|
408 |
return ""
|
409 |
|
410 |
def process_video(video, resize_width=4000, resize_height=3000, frame_skip=5):
|
|
|
162 |
inference_times: List[float],
|
163 |
io_times: List[float]
|
164 |
) -> str:
|
165 |
+
# Generating LaTeX-based PDF report
|
166 |
+
log_entries.append("Generating LaTeX report...")
|
167 |
+
report_path = os.path.join(OUTPUT_DIR, f"drone_analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf")
|
168 |
+
tex_path = os.path.join(OUTPUT_DIR, f"drone_analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.tex")
|
169 |
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
170 |
|
171 |
+
# LaTeX document content
|
172 |
+
report_content = [
|
173 |
+
r"\documentclass[a4paper,12pt]{article}",
|
174 |
+
r"\usepackage[utf8]{inputenc}",
|
175 |
+
r"\usepackage[T1]{fontenc}",
|
176 |
+
r"\usepackage{geometry}",
|
177 |
+
r"\geometry{margin=1in}",
|
178 |
+
r"\usepackage{graphicx}",
|
179 |
+
r"\graphicspath{{./}}",
|
180 |
+
r"\usepackage{booktabs}",
|
181 |
+
r"\usepackage{longtable}",
|
182 |
+
r"\usepackage{enumitem}",
|
183 |
+
r"\usepackage{hyperref}",
|
184 |
+
r"\hypersetup{colorlinks=true,linkcolor=blue,filecolor=blue,urlcolor=blue}",
|
185 |
+
r"\usepackage{amsmath}",
|
186 |
+
r"\usepackage{caption}",
|
187 |
+
r"\usepackage{pdfpages}",
|
188 |
+
r"\usepackage{times}", # Using Times font
|
189 |
+
r"\begin{document}",
|
190 |
+
r"\title{NHAI Drone Survey Analysis Report}",
|
191 |
+
r"\author{Nagasurendra, Data Analyst}",
|
192 |
+
r"\date{\today}",
|
193 |
+
r"\maketitle",
|
194 |
+
r"\tableofcontents",
|
195 |
+
r"\newpage",
|
196 |
+
r"\section{Project Details}",
|
197 |
+
r"\begin{itemize}",
|
198 |
+
r"\item \textbf{Project Name}: NH-44 Delhi-Hyderabad Section (Package XYZ)",
|
199 |
+
r"\item \textbf{Highway Section}: Km 100 to Km 150",
|
200 |
+
r"\item \textbf{State}: Telangana",
|
201 |
+
r"\item \textbf{Region}: South",
|
202 |
+
rf"\item \textbf{Survey Date}: {datetime.now().strftime('%Y-%m-%d')}",
|
203 |
+
r"\item \textbf{Drone Service Provider}: ABC Drone Services Pvt. Ltd.",
|
204 |
+
r"\item \textbf{Technology Service Provider}: XYZ AI Analytics Ltd.",
|
205 |
+
rf"\item \textbf{Work Order Reference}: Data Lake WO-{datetime.now().strftime('%Y-%m-%d')}-XYZ",
|
206 |
+
r"\item \textbf{Report Prepared By}: Nagasurendra, Data Analyst",
|
207 |
+
rf"\item \textbf{Report Date}: {datetime.now().strftime('%Y-%m-%d')}",
|
208 |
+
r"\end{itemize}",
|
209 |
+
r"\section{Introduction}",
|
210 |
+
r"This report consolidates drone survey results for NH-44 (Km 100--150) under Operations \& Maintenance, per NHAI Policy Circular No. 18.98/2024, detecting potholes and cracks using YOLOv8 for Monthly Progress Report integration.",
|
211 |
+
r"\section{Drone Survey Metadata}",
|
212 |
+
r"\begin{itemize}",
|
213 |
+
r"\item \textbf{Drone Speed}: 5 m/s",
|
214 |
+
r"\item \textbf{Drone Height}: 60 m",
|
215 |
+
r"\item \textbf{Camera Sensor}: RGB, 12 MP",
|
216 |
+
r"\item \textbf{Recording Type}: JPEG, 90$^\circ$ nadir",
|
217 |
+
r"\item \textbf{Image Overlap}: 85\%",
|
218 |
+
r"\item \textbf{Flight Pattern}: Single lap, ROW centered",
|
219 |
+
r"\item \textbf{Geotagging}: Enabled",
|
220 |
+
r"\item \textbf{Satellite Lock}: 12 satellites",
|
221 |
+
r"\item \textbf{Terrain Follow Mode}: Enabled",
|
222 |
+
r"\end{itemize}",
|
223 |
+
r"\section{Quality Check Results}",
|
224 |
+
r"\begin{itemize}",
|
225 |
+
r"\item \textbf{Resolution}: 4000x3000 (12 MP)",
|
226 |
+
r"\item \textbf{Overlap}: 85\%",
|
227 |
+
r"\item \textbf{Camera Angle}: 90$^\circ$ nadir",
|
228 |
+
r"\item \textbf{Drone Speed}: $\leq$ 5 m/s",
|
229 |
+
r"\item \textbf{Geotagging}: 100\% compliant",
|
230 |
+
r"\item \textbf{QC Status}: Passed",
|
231 |
+
r"\end{itemize}",
|
232 |
+
r"\section{AI/ML Analytics}",
|
233 |
+
rf"Total Frames Processed: {frame_count}\par",
|
234 |
+
rf"Detection Frames: {detection_frame_count} ({detection_frame_count/frame_count*100:.2f}\%)\par",
|
235 |
+
rf"Total Detections: {metrics['total_detections']}\par",
|
236 |
+
r"\textbf{Breakdown:}",
|
237 |
+
r"\begin{itemize}"
|
238 |
+
]
|
239 |
+
|
240 |
for item in metrics.get("items", []):
|
241 |
percentage = (item["count"] / metrics["total_detections"] * 100) if metrics["total_detections"] > 0 else 0
|
242 |
+
report_content.append(rf"\item {item['type']}: {item['count']} ({percentage:.2f}\%)")
|
243 |
+
report_content.extend([
|
244 |
+
r"\end{itemize}",
|
245 |
+
rf"Processing Time: {total_time:.2f} seconds\par",
|
246 |
+
rf"Average Frame Time: {sum(frame_times)/len(frame_times):.2f} ms" if frame_times else r"Average Frame Time: N/A\par",
|
247 |
+
rf"Average Resize Time: {sum(resize_times)/len(resize_times):.2f} ms" if resize_times else r"Average Resize Time: N/A\par",
|
248 |
+
rf"Average Inference Time: {sum(inference_times)/len(inference_times):.2f} ms" if inference_times else r"Average Inference Time: N/A\par",
|
249 |
+
rf"Average I/O Time: {sum(io_times)/len(io_times):.2f} ms" if io_times else r"Average I/O Time: N/A\par",
|
250 |
+
rf"Timestamp: {metrics.get('timestamp', 'N/A')}\par",
|
251 |
+
r"Summary: Potholes and cracks detected in high-traffic segments.\par",
|
252 |
+
r"\section{Output File Structure}",
|
253 |
+
r"\begin{itemize}",
|
254 |
+
rf"\item \texttt{{drone\_analysis\_report\_<{timestamp}>.pdf}}: This report",
|
255 |
+
r"\item \texttt{outputs/processed\_output.mp4}: Processed video with annotations",
|
256 |
+
rf"\item \texttt{{outputs/chart\_<{timestamp}>.png}}: Detection trend chart",
|
257 |
+
rf"\item \texttt{{outputs/map\_<{timestamp}>.png}}: Issue locations map",
|
258 |
+
r"\item \texttt{captured\_frames/detected\_<frame>.jpg}: Geotagged images for detected issues",
|
259 |
+
r"\item \texttt{flight\_logs/flight\_log\_<frame>.csv}: Flight logs matching image frames",
|
260 |
+
r"\end{itemize}",
|
261 |
+
r"\textbf{Note}: Images and logs share frame numbers (e.g., \texttt{detected\_000001.jpg} corresponds to \texttt{flight\_log\_000001.csv}).",
|
262 |
+
r"\section{Geotagged Images}",
|
263 |
+
rf"Total Images: {len(detected_issues)}\par",
|
264 |
+
rf"Storage: Data Lake \texttt{{/project\_xyz/images/{datetime.now().strftime('%Y-%m-%d')}}}\par",
|
265 |
+
r"\begin{longtable}{|c|l|l|l|l|l|}",
|
266 |
+
r"\hline",
|
267 |
+
r"\textbf{Frame} & \textbf{Issue Type} & \textbf{GPS (Lat, Lon)} & \textbf{Timestamp} & \textbf{Confidence} & \textbf{Image Path} \\ \hline",
|
268 |
+
r"\endhead"
|
269 |
+
])
|
270 |
|
|
|
|
|
271 |
for detection in all_detections[:100]:
|
272 |
+
report_content.append(
|
273 |
+
rf"{detection['frame']:06d} & {detection['label']} & ({detection['gps'][0]:.6f}, {detection['gps'][1]:.6f}) & {detection['timestamp']} & {detection['conf']:.2f} & \texttt{{{os.path.basename(detection['path'])}}} \\ \hline"
|
|
|
|
|
|
|
|
|
274 |
)
|
275 |
+
report_content.append(r"\end{longtable}")
|
276 |
+
|
277 |
+
# Embedding geotagged images
|
278 |
+
report_content.append(r"\subsection{Geotagged Images Display}")
|
279 |
+
for detection in all_detections[:100]:
|
280 |
+
image_path = detection['path']
|
281 |
+
if os.path.exists(image_path):
|
282 |
+
report_content.append(rf"\begin{{figure}}[h]")
|
283 |
+
report_content.append(rf"\centering")
|
284 |
+
report_content.append(rf"\includegraphics[width=0.8\textwidth]{{{image_path}}}")
|
285 |
+
report_content.append(rf"\caption{{Frame {detection['frame']:06d}: {detection['label']} at ({detection['gps'][0]:.6f}, {detection['gps'][1]:.6f}), Confidence: {detection['conf']:.2f}}}")
|
286 |
+
report_content.append(rf"\end{{figure}}")
|
287 |
+
|
288 |
+
report_content.extend([
|
289 |
+
r"\section{Flight Logs}",
|
290 |
+
rf"Total Logs: {len(detected_issues)}\par",
|
291 |
+
rf"Storage: Data Lake \texttt{{/project\_xyz/flight\_logs/{datetime.now().strftime('%Y-%m-%d')}}}\par",
|
292 |
+
r"\begin{longtable}{|c|l|l|l|l|l|l|l|}",
|
293 |
+
r"\hline",
|
294 |
+
r"\textbf{Frame} & \textbf{Timestamp} & \textbf{Latitude} & \textbf{Longitude} & \textbf{Speed (m/s)} & \textbf{Satellites} & \textbf{Altitude (m)} & \textbf{Log Path} \\ \hline",
|
295 |
+
r"\endhead"
|
296 |
+
])
|
297 |
|
|
|
|
|
298 |
for detection in all_detections[:100]:
|
299 |
log_path = f"flight_logs/flight_log_{detection['frame']:06d}.csv"
|
300 |
+
report_content.append(
|
301 |
+
rf"{detection['frame']:06d} & {detection['timestamp']} & {detection['gps'][0]:.6f} & {detection['gps'][1]:.6f} & 5.0 & 12 & 60 & \texttt{{{os.path.basename(log_path)}}} \\ \hline"
|
|
|
|
|
302 |
)
|
303 |
+
report_content.extend([
|
304 |
+
r"\end{longtable}",
|
305 |
+
r"\section{Processed Video}",
|
306 |
+
rf"Path: \texttt{{outputs/processed\_output.mp4}}\par",
|
307 |
+
rf"Frames: {output_frames}\par",
|
308 |
+
rf"FPS: {output_fps:.2f}\par",
|
309 |
+
rf"Duration: {output_duration:.2f} seconds\par",
|
310 |
+
r"\section{Visualizations}",
|
311 |
+
rf"Detection Trend Chart: \texttt{{outputs/chart\_<{timestamp}>.png}}\par",
|
312 |
+
rf"Issue Locations Map: \texttt{{outputs/map\_<{timestamp}>.png}}\par"
|
313 |
+
])
|
314 |
+
|
315 |
+
# Including chart and map images
|
316 |
+
if chart_path and os.path.exists(chart_path):
|
317 |
+
report_content.extend([
|
318 |
+
r"\begin{figure}[h]",
|
319 |
+
r"\centering",
|
320 |
+
rf"\includegraphics[width=0.8\textwidth]{{{chart_path}}}",
|
321 |
+
r"\caption{Detection Trend Chart}",
|
322 |
+
r"\end{figure}"
|
323 |
+
])
|
324 |
+
if map_path and os.path.exists(map_path):
|
325 |
+
report_content.extend([
|
326 |
+
r"\begin{figure}[h]",
|
327 |
+
r"\centering",
|
328 |
+
rf"\includegraphics[width=0.8\textwidth]{{{map_path}}}",
|
329 |
+
r"\caption{Issue Locations Map}",
|
330 |
+
r"\end{figure}"
|
331 |
+
])
|
332 |
+
|
333 |
+
report_content.extend([
|
334 |
+
r"\section{Processing Timestamps}",
|
335 |
+
rf"Total Processing Time: {total_time:.2f} seconds\par",
|
336 |
+
r"\textbf{Log Entries (Last 10):}",
|
337 |
+
r"\begin{itemize}"
|
338 |
+
])
|
339 |
|
|
|
|
|
340 |
for entry in log_entries[-10:]:
|
341 |
+
report_content.append(rf"\item {entry}")
|
342 |
+
report_content.extend([
|
343 |
+
r"\end{itemize}",
|
344 |
+
r"\section{Stakeholder Validation}",
|
345 |
+
r"\begin{itemize}",
|
346 |
+
r"\item \textbf{AE/IE Comments}: Pending",
|
347 |
+
r"\item \textbf{PD/RO Comments}: Pending",
|
348 |
+
r"\end{itemize}",
|
349 |
+
r"\section{Recommendations}",
|
350 |
+
r"\begin{itemize}",
|
351 |
+
r"\item Repair potholes in high-traffic segments.",
|
352 |
+
r"\item Seal cracks to prevent degradation.",
|
353 |
+
r"\item Schedule follow-up survey.",
|
354 |
+
r"\end{itemize}",
|
355 |
+
r"\section{Data Lake References}",
|
356 |
+
rf"Images: \texttt{{/project\_xyz/images/{datetime.now().strftime('%Y-%m-%d')}}}\par",
|
357 |
+
rf"Flight Logs: \texttt{{/project\_xyz/flight\_logs/{datetime.now().strftime('%Y-%m-%d')}}}\par",
|
358 |
+
rf"Video: \texttt{{/project\_xyz/videos/processed\_output_{datetime.now().strftime('%Y%m%d')}.mp4}}\par",
|
359 |
+
rf"DAMS Dashboard: \texttt{{/project\_xyz/dams/{datetime.now().strftime('%Y-%m-%d')}}}\par",
|
360 |
+
r"\end{document}"
|
361 |
+
])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
|
363 |
try:
|
364 |
+
# Writing LaTeX file
|
365 |
+
with open(tex_path, 'w') as f:
|
366 |
+
f.write("\n".join(report_content))
|
367 |
+
log_entries.append(f"LaTeX report saved: {tex_path}")
|
368 |
+
|
369 |
+
# Compiling LaTeX to PDF using latexmk
|
370 |
+
import subprocess
|
371 |
+
subprocess.run(["latexmk", "-pdf", "-interaction=nonstopmode", tex_path], cwd=OUTPUT_DIR, check=True)
|
372 |
+
log_entries.append(f"PDF report generated: {report_path}")
|
373 |
return report_path
|
374 |
except Exception as e:
|
375 |
+
log_entries.append(f"Error: Failed to generate report: {str(e)}")
|
376 |
return ""
|
377 |
|
378 |
def process_video(video, resize_width=4000, resize_height=3000, frame_skip=5):
|