Sarvamangalak commited on
Commit
ad79ebd
·
verified ·
1 Parent(s): 99a891f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +340 -2
app.py CHANGED
@@ -8,6 +8,9 @@ import torch
8
  import numpy as np
9
  import cv2
10
  import sqlite3
 
 
 
11
  import pandas as pd
12
  import matplotlib.pyplot as plt
13
  import easyocr
@@ -1879,6 +1882,253 @@ def process_image(img):
1879
  )
1880
 
1881
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1882
  # ============================================================
1883
  # REFRESH DASHBOARD
1884
  # ============================================================
@@ -2112,8 +2362,96 @@ with gr.Blocks(
2112
  )
2113
 
2114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2115
  # ========================================================
2116
- # TAB 2 - AGENTIC AI DASHBOARD
2117
  # ========================================================
2118
 
2119
  with gr.Tab(
@@ -2267,7 +2605,7 @@ analytics operation.
2267
  )
2268
 
2269
  # ========================================================
2270
- # TAB 3 - ADMIN / DATABASE
2271
  # ========================================================
2272
 
2273
  with gr.Tab(
 
8
  import numpy as np
9
  import cv2
10
  import sqlite3
11
+ import os
12
+ import tempfile
13
+ import uuid
14
  import pandas as pd
15
  import matplotlib.pyplot as plt
16
  import easyocr
 
1882
  )
1883
 
1884
 
1885
+
1886
+ # ============================================================
1887
+ # VIDEO PROCESSING
1888
+ # ============================================================
1889
+
1890
+ def process_video(video_path, frame_skip=5, max_frames=0):
1891
+ """Process an uploaded traffic video and create an annotated output video."""
1892
+
1893
+ if video_path is None:
1894
+ return None, "Please upload a video.", "0", "0", "₹0", get_dashboard()
1895
+
1896
+ cap = None
1897
+ writer = None
1898
+
1899
+ try:
1900
+ cap = cv2.VideoCapture(video_path)
1901
+
1902
+ if not cap.isOpened():
1903
+ return None, "Unable to open the uploaded video.", "0", "0", "₹0", get_dashboard()
1904
+
1905
+ fps = cap.get(cv2.CAP_PROP_FPS)
1906
+ if not fps or fps <= 0:
1907
+ fps = 25.0
1908
+
1909
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
1910
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
1911
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
1912
+
1913
+ if width <= 0 or height <= 0:
1914
+ return None, "Invalid video dimensions.", "0", "0", "₹0", get_dashboard()
1915
+
1916
+ try:
1917
+ frame_skip = max(1, int(frame_skip))
1918
+ except Exception:
1919
+ frame_skip = 5
1920
+
1921
+ try:
1922
+ max_frames = max(0, int(max_frames))
1923
+ except Exception:
1924
+ max_frames = 0
1925
+
1926
+ output_path = os.path.join(
1927
+ tempfile.gettempdir(),
1928
+ f"traffic_result_{uuid.uuid4().hex}.mp4"
1929
+ )
1930
+
1931
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v")
1932
+ writer = cv2.VideoWriter(
1933
+ output_path,
1934
+ fourcc,
1935
+ fps,
1936
+ (width, height)
1937
+ )
1938
+
1939
+ if not writer.isOpened():
1940
+ return None, "Unable to create the processed output video.", "0", "0", "₹0", get_dashboard()
1941
+
1942
+ ev_count = 0
1943
+ non_ev_count = 0
1944
+ discount_total = 0
1945
+ detected_plates = 0
1946
+ processed_frames = 0
1947
+ frame_number = 0
1948
+
1949
+ # Prevent repeated database records for the same known plate
1950
+ # across multiple frames of this uploaded video.
1951
+ video_seen_plates = set()
1952
+
1953
+ output_lines = [
1954
+ "VIDEO TRAFFIC ANALYSIS",
1955
+ "",
1956
+ f"Input frames: {total_frames if total_frames > 0 else 'Unknown'}",
1957
+ f"Processing every {frame_skip} frame(s)",
1958
+ ""
1959
+ ]
1960
+
1961
+ while True:
1962
+ ret, frame = cap.read()
1963
+
1964
+ if not ret:
1965
+ break
1966
+
1967
+ if max_frames > 0 and frame_number >= max_frames:
1968
+ break
1969
+
1970
+ # Write unprocessed frames unchanged.
1971
+ if frame_number % frame_skip != 0:
1972
+ writer.write(frame)
1973
+ frame_number += 1
1974
+ continue
1975
+
1976
+ processed_frames += 1
1977
+
1978
+ rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
1979
+ image = Image.fromarray(rgb_frame)
1980
+
1981
+ inputs = processor(
1982
+ images=image,
1983
+ return_tensors="pt"
1984
+ )
1985
+
1986
+ with torch.no_grad():
1987
+ outputs = model(**inputs)
1988
+
1989
+ target_sizes = torch.tensor(
1990
+ [[image.size[1], image.size[0]]]
1991
+ )
1992
+
1993
+ results = processor.post_process_object_detection(
1994
+ outputs,
1995
+ threshold=0.30,
1996
+ target_sizes=target_sizes
1997
+ )[0]
1998
+
1999
+ draw = ImageDraw.Draw(image)
2000
+
2001
+ for i, box in enumerate(results["boxes"]):
2002
+ x1, y1, x2, y2 = map(int, box.tolist())
2003
+
2004
+ x1 = max(0, min(x1, image.width - 1))
2005
+ y1 = max(0, min(y1, image.height - 1))
2006
+ x2 = max(0, min(x2, image.width))
2007
+ y2 = max(0, min(y2, image.height))
2008
+
2009
+ if x2 <= x1 or y2 <= y1:
2010
+ continue
2011
+
2012
+ plate = image.crop((x1, y1, x2, y2))
2013
+
2014
+ status = classify_plate_color(plate)
2015
+ plate_number = read_license_plate(plate)
2016
+ detected_plates += 1
2017
+
2018
+ normalized_plate = str(plate_number).strip().upper()
2019
+ should_count = True
2020
+
2021
+ if normalized_plate not in ("", "UNKNOWN", "OCR_UNAVAILABLE"):
2022
+ if normalized_plate in video_seen_plates:
2023
+ should_count = False
2024
+ else:
2025
+ video_seen_plates.add(normalized_plate)
2026
+
2027
+ if should_count:
2028
+ saved = save_vehicle(plate_number, status)
2029
+
2030
+ if saved not in ("Duplicate", "Error"):
2031
+ if status == "EV":
2032
+ ev_count += 1
2033
+ discount_total += EV_DISCOUNT
2034
+ else:
2035
+ non_ev_count += 1
2036
+
2037
+ output_lines.extend([
2038
+ f"Vehicle {ev_count + non_ev_count}",
2039
+ f"Plate: {plate_number}",
2040
+ f"Status: {status}",
2041
+ f"Discount: ₹{EV_DISCOUNT if status == 'EV' else 0}",
2042
+ ""
2043
+ ])
2044
+
2045
+ if status == "EV":
2046
+ outline_color = "green"
2047
+ label = f"{plate_number} | EV | ₹{EV_DISCOUNT}"
2048
+ else:
2049
+ outline_color = "red"
2050
+ label = f"{plate_number} | Non-EV"
2051
+
2052
+ draw.rectangle(
2053
+ [x1, y1, x2, y2],
2054
+ outline=outline_color,
2055
+ width=4
2056
+ )
2057
+
2058
+ text_y = max(0, y1 - 22)
2059
+
2060
+ draw.rectangle(
2061
+ [
2062
+ x1,
2063
+ text_y,
2064
+ min(image.width, x1 + 330),
2065
+ y1
2066
+ ],
2067
+ fill="black"
2068
+ )
2069
+
2070
+ draw.text(
2071
+ (x1 + 3, text_y + 3),
2072
+ label,
2073
+ fill=outline_color
2074
+ )
2075
+
2076
+ output_frame = cv2.cvtColor(
2077
+ np.array(image),
2078
+ cv2.COLOR_RGB2BGR
2079
+ )
2080
+
2081
+ writer.write(output_frame)
2082
+ frame_number += 1
2083
+
2084
+ cap.release()
2085
+ cap = None
2086
+
2087
+ writer.release()
2088
+ writer = None
2089
+
2090
+ if processed_frames == 0:
2091
+ return None, "No frames were processed.", "0", "0", "₹0", get_dashboard()
2092
+
2093
+ total_unique = ev_count + non_ev_count
2094
+ ev_percentage = (
2095
+ ev_count / total_unique * 100
2096
+ if total_unique > 0 else 0
2097
+ )
2098
+
2099
+ output_lines.extend([
2100
+ "VIDEO SUMMARY",
2101
+ f"Processed frames: {processed_frames}",
2102
+ f"Detected plate instances: {detected_plates}",
2103
+ f"Unique vehicles recorded: {total_unique}",
2104
+ f"EV vehicles: {ev_count}",
2105
+ f"Non-EV vehicles: {non_ev_count}",
2106
+ f"EV percentage: {ev_percentage:.2f}%",
2107
+ f"Total EV discount: ₹{discount_total}"
2108
+ ])
2109
+
2110
+ return (
2111
+ output_path,
2112
+ "\n".join(output_lines),
2113
+ str(ev_count),
2114
+ str(non_ev_count),
2115
+ f"₹{discount_total}",
2116
+ get_dashboard()
2117
+ )
2118
+
2119
+ except Exception as e:
2120
+ print("Video processing error:", e)
2121
+
2122
+ if cap is not None:
2123
+ cap.release()
2124
+
2125
+ if writer is not None:
2126
+ writer.release()
2127
+
2128
+ return None, f"Video processing error: {str(e)}", "0", "0", "₹0", get_dashboard()
2129
+
2130
+
2131
+
2132
  # ============================================================
2133
  # REFRESH DASHBOARD
2134
  # ============================================================
 
2362
  )
2363
 
2364
 
2365
+
2366
+ # ========================================================
2367
+ # TAB 2 - VIDEO PROCESSING
2368
+ # ========================================================
2369
+
2370
+ with gr.Tab("Video Processing"):
2371
+
2372
+ gr.Markdown("## Video Traffic & EV Analysis")
2373
+
2374
+ gr.Markdown(
2375
+ "Upload a traffic video to detect license plates, "
2376
+ "classify EV/Non-EV vehicles, read plate numbers using "
2377
+ "EasyOCR, calculate EV incentives, and generate an "
2378
+ "annotated output video."
2379
+ )
2380
+
2381
+ with gr.Row(equal_height=True):
2382
+
2383
+ with gr.Column(scale=1):
2384
+
2385
+ input_video = gr.Video(
2386
+ label="Upload Traffic Video",
2387
+ sources=["upload"],
2388
+ format="mp4"
2389
+ )
2390
+
2391
+ frame_skip = gr.Slider(
2392
+ minimum=1,
2393
+ maximum=15,
2394
+ value=5,
2395
+ step=1,
2396
+ label="Process Every Nth Frame",
2397
+ info="1 = every frame; higher values reduce processing time."
2398
+ )
2399
+
2400
+ max_frames = gr.Number(
2401
+ value=0,
2402
+ precision=0,
2403
+ label="Maximum Frames",
2404
+ info="0 = process the complete video."
2405
+ )
2406
+
2407
+ video_btn = gr.Button(
2408
+ "Process Video",
2409
+ variant="primary",
2410
+ size="lg"
2411
+ )
2412
+
2413
+ with gr.Column(scale=1):
2414
+
2415
+ output_video = gr.Video(
2416
+ label="Processed Video",
2417
+ autoplay=False
2418
+ )
2419
+
2420
+ video_summary = gr.Textbox(
2421
+ label="Video Analysis Summary",
2422
+ lines=18
2423
+ )
2424
+
2425
+ with gr.Row():
2426
+
2427
+ video_ev_box = gr.Textbox(label="EV Vehicles")
2428
+ video_non_ev_box = gr.Textbox(label="Non-EV Vehicles")
2429
+ video_discount_box = gr.Textbox(label="Total Discount")
2430
+
2431
+ gr.Markdown("## Video Traffic Analytics Dashboard")
2432
+
2433
+ video_dashboard = gr.Plot(label="Video Analytics")
2434
+
2435
+ video_btn.click(
2436
+ fn=process_video,
2437
+ inputs=[
2438
+ input_video,
2439
+ frame_skip,
2440
+ max_frames
2441
+ ],
2442
+ outputs=[
2443
+ output_video,
2444
+ video_summary,
2445
+ video_ev_box,
2446
+ video_non_ev_box,
2447
+ video_discount_box,
2448
+ video_dashboard
2449
+ ]
2450
+ )
2451
+
2452
+
2453
  # ========================================================
2454
+ # TAB 3 - AGENTIC AI DASHBOARD
2455
  # ========================================================
2456
 
2457
  with gr.Tab(
 
2605
  )
2606
 
2607
  # ========================================================
2608
+ # TAB 4 - ADMIN / DATABASE
2609
  # ========================================================
2610
 
2611
  with gr.Tab(