nagasurendra commited on
Commit
82996c6
·
verified ·
1 Parent(s): fbd4a06

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -226
app.py CHANGED
@@ -162,249 +162,217 @@ def generate_report(
162
  inference_times: List[float],
163
  io_times: List[float]
164
  ) -> str:
165
- log_entries.append("Generating report...")
166
- report_path = os.path.join(OUTPUT_DIR, f"drone_analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.tex")
 
 
167
  timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
168
 
169
- # Prepare items for the breakdown
170
- items = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  for item in metrics.get("items", []):
172
  percentage = (item["count"] / metrics["total_detections"] * 100) if metrics["total_detections"] > 0 else 0
173
- items.append(f"\\item {item['type']}: {item['count']} ({percentage:.2f}\\%)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- # Prepare image rows with embedded images
176
- image_rows = []
177
  for detection in all_detections[:100]:
178
- image_basename = os.path.basename(detection['path'])
179
- image_rows.append(
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
- log_rows.append(
191
- f"{detection['frame']:06d} & {detection['timestamp']} & "
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
- log_entries_str.append(f"\\item {entry}")
200
-
201
- # Calculate average times
202
- avg_frame_time = sum(frame_times) / len(frame_times) if frame_times else 0
203
- avg_resize_time = sum(resize_times) / len(resize_times) if resize_times else 0
204
- avg_inference_time = sum(inference_times) / len(inference_times) if inference_times else 0
205
- avg_io_time = sum(io_times) / len(io_times) if io_times else 0
206
-
207
- # LaTeX template with escaped curly braces
208
- latex_template = r"""
209
- \documentclass[a4paper,12pt]{{article}}
210
- \usepackage[utf8]{{inputenc}}
211
- \usepackage[T1]{{fontenc}}
212
- \usepackage{{geometry}}
213
- \geometry{{margin=1in}}
214
- \usepackage{{graphicx}}
215
- \usepackage{{booktabs}}
216
- \usepackage{{longtable}}
217
- \usepackage{{hyperref}}
218
- \usepackage{{xcolor}}
219
- \usepackage{{parskip}}
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
- with open(report_path, 'w') as f:
403
- f.write(report_content)
404
- log_entries.append(f"Report saved: {report_path}")
 
 
 
 
 
 
405
  return report_path
406
  except Exception as e:
407
- log_entries.append(f"Error: Failed to save report: {str(e)}")
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):