DSatishchandra commited on
Commit
c704816
·
verified ·
1 Parent(s): 55d76c3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -0
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cv2
3
+ import os
4
+ import numpy as np
5
+ from datetime import datetime
6
+ import matplotlib.pyplot as plt
7
+ from services.detection_service import detect_faults_solar, detect_faults_windmill
8
+ from services.anomaly_service import track_faults, predict_fault
9
+ from models.solar_model import load_solar_model
10
+ from models.windmill_model import load_windmill_model
11
+ from config.settings import VIDEO_FOLDER
12
+
13
+ # Initialize global state
14
+ logs = []
15
+ fault_counts = []
16
+ frame_numbers = []
17
+ total_detected = 0
18
+
19
+ # Custom CSS to match the screenshot
20
+ css = """
21
+ <style>
22
+ .main-header {
23
+ text-align: center;
24
+ font-size: 24px;
25
+ font-weight: bold;
26
+ color: #333;
27
+ margin-bottom: 10px;
28
+ }
29
+ .status {
30
+ text-align: center;
31
+ font-size: 16px;
32
+ color: #333;
33
+ margin-bottom: 20px;
34
+ }
35
+ .section-title {
36
+ font-size: 16px;
37
+ font-weight: bold;
38
+ color: #333;
39
+ text-transform: uppercase;
40
+ margin-bottom: 10px;
41
+ }
42
+ .section-box {
43
+ border: 1px solid #4A90E2;
44
+ padding: 10px;
45
+ border-radius: 5px;
46
+ margin-bottom: 20px;
47
+ }
48
+ .log-entry {
49
+ font-size: 14px;
50
+ color: #333;
51
+ margin-bottom: 5px;
52
+ }
53
+ .metrics-text {
54
+ font-size: 14px;
55
+ color: #333;
56
+ margin-bottom: 5px;
57
+ }
58
+ </style>
59
+ """
60
+
61
+ def process_video(video_path, detection_type):
62
+ global logs, fault_counts, frame_numbers, total_detected
63
+ cap = cv2.VideoCapture(video_path)
64
+ if not cap.isOpened():
65
+ return "Error: Could not open video file.", None, None, None, None, None
66
+
67
+ model = load_solar_model() if detection_type == "Solar Panel" else load_windmill_model()
68
+ frame_count = 0
69
+
70
+ # Clear previous state for a new video
71
+ logs.clear()
72
+ fault_counts.clear()
73
+ frame_numbers.clear()
74
+ total_detected = 0
75
+
76
+ while cap.isOpened():
77
+ ret, frame = cap.read()
78
+ if not ret:
79
+ break
80
+
81
+ frame_count += 1
82
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
83
+
84
+ # Detect faults
85
+ faults = detect_faults_solar(model, frame_rgb) if detection_type == "Solar Panel" else detect_faults_windmill(model, frame_rgb)
86
+ num_faults = len(faults)
87
+
88
+ # Draw bounding boxes and labels
89
+ for fault in faults:
90
+ x, y = int(fault['location'][0]), int(fault['location'][1])
91
+ cv2.rectangle(frame_rgb, (x-30, y-30), (x+30, y+30), (255, 0, 0), 2)
92
+ cv2.putText(frame_rgb, f"{fault['type']}", (x, y-40),
93
+ cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
94
+
95
+ # Update state
96
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
97
+ log_entry = f"{timestamp} - Frame {frame_count} - Faults: {num_faults}"
98
+ logs.append(log_entry)
99
+ total_detected += num_faults
100
+ fault_counts.append(num_faults)
101
+ frame_numbers.append(frame_count)
102
+
103
+ # Limit to last 100 frames
104
+ if len(frame_numbers) > 100:
105
+ frame_numbers.pop(0)
106
+ fault_counts.pop(0)
107
+
108
+ # Prepare outputs
109
+ video_output = frame_rgb
110
+ metrics = f"faults: {num_faults}<br>total_detected: {total_detected}"
111
+ live_logs = "<br>".join(logs[-20:]) # Show last 20 logs for brevity
112
+ last_5_events = "<br>".join(logs[-5:]) if logs else "No events yet"
113
+ prediction = "Potential fault escalation detected!" if predict_fault(fault_counts) else ""
114
+
115
+ # Generate trends graph
116
+ fig, ax = plt.subplots(figsize=(6, 3))
117
+ ax.plot(frame_numbers, fault_counts, marker='o', color='blue')
118
+ ax.set_title("Faults Over Time", fontsize=10)
119
+ ax.set_xlabel("Frame", fontsize=8)
120
+ ax.set_ylabel("Count", fontsize=8)
121
+ ax.grid(True)
122
+ ax.tick_params(axis='both', which='major', labelsize=6)
123
+ plt.tight_layout()
124
+
125
+ return video_output, metrics, live_logs, last_5_events, fig, prediction
126
+
127
+ # Gradio interface
128
+ with gr.Blocks(css=css) as demo:
129
+ gr.Markdown('<div class="main-header">THERMAL FAULT DETECTION DASHBOARD</div>')
130
+ gr.Markdown('<div class="status">🟢 RUNNING</div>')
131
+
132
+ with gr.Row():
133
+ with gr.Column(scale=3):
134
+ with gr.Box():
135
+ gr.Markdown('<div class="section-title">LIVE VIDEO FEED</div>', unsafe_allow_html=True)
136
+ video_output = gr.Image(label="", interactive=False)
137
+ with gr.Column(scale=1):
138
+ with gr.Box():
139
+ gr.Markdown('<div class="section-title">LIVE METRICS</div>', unsafe_allow_html=True)
140
+ metrics_output = gr.Markdown(label="", unsafe_allow_html=True)
141
+ prediction_output = gr.Markdown(label="")
142
+
143
+ with gr.Row():
144
+ with gr.Column(scale=1):
145
+ with gr.Box():
146
+ gr.Markdown('<div class="section-title">LIVE LOGS</div>', unsafe_allow_html=True)
147
+ logs_output = gr.Markdown(label="", unsafe_allow_html=True)
148
+ with gr.Box():
149
+ gr.Markdown('<div class="section-title">LAST 5 CAPTURED EVENTS</div>', unsafe_allow_html=True)
150
+ events_output = gr.Markdown(label="", unsafe_allow_html=True)
151
+ with gr.Column(scale=2):
152
+ with gr.Box():
153
+ gr.Markdown('<div class="section-title">DETECTION TRENDS</div>', unsafe_allow_html=True)
154
+ gr.Markdown('<div style="font-size: 14px; font-weight: bold; margin-bottom: 10px;">Faults Over Time</div>', unsafe_allow_html=True)
155
+ trends_output = gr.Plot(label="")
156
+
157
+ # Sidebar for settings
158
+ with gr.Row():
159
+ with gr.Column():
160
+ video_files = [f for f in os.listdir(VIDEO_FOLDER) if f.endswith('.mp4')]
161
+ video_input = gr.Dropdown(choices=video_files, label="Select Video")
162
+ detection_type = gr.Dropdown(choices=["Solar Panel", "Windmill"], label="Detection Type")
163
+ submit_btn = gr.Button("Start Processing")
164
+
165
+ # Connect inputs to outputs
166
+ submit_btn.click(
167
+ fn=process_video,
168
+ inputs=[video_input, detection_type],
169
+ outputs=[video_output, metrics_output, logs_output, events_output, trends_output, prediction_output],
170
+ _js="() => [document.querySelector('input[type=\"file\"]').value, document.querySelector('select[name=\"detection_type\"]').value]"
171
+ )
172
+
173
+ demo.launch()