File size: 7,687 Bytes
7b8e5d9
 
 
 
 
 
 
 
c704816
 
 
 
 
 
7b8e5d9
 
 
 
 
c704816
7b8e5d9
c704816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7b8e5d9
c704816
 
7b8e5d9
c704816
 
 
7b8e5d9
c704816
 
7b8e5d9
c704816
 
 
 
 
 
7b8e5d9
c704816
 
 
 
7b8e5d9
c704816
7b8e5d9
c704816
 
 
7b8e5d9
c704816
 
7b8e5d9
c704816
7b8e5d9
c704816
7b8e5d9
c704816
 
 
 
 
 
 
7b8e5d9
c704816
 
 
 
7b8e5d9
c704816
 
7b8e5d9
c704816
 
 
7b8e5d9
c704816
 
 
 
 
 
 
 
 
 
 
7b8e5d9
c704816
7b8e5d9
 
c704816
 
 
5da267c
7b8e5d9
5da267c
7b8e5d9
5da267c
c704816
5da267c
7b8e5d9
5da267c
7b8e5d9
 
5da267c
c704816
 
 
5da267c
7b8e5d9
5da267c
7b8e5d9
5da267c
 
7b8e5d9
5da267c
7b8e5d9
5da267c
c704816
5da267c
7b8e5d9
5da267c
7b8e5d9
 
5da267c
c704816
7b8e5d9
c704816
 
7b8e5d9
 
 
 
c704816
7b8e5d9
c704816
 
 
 
 
 
 
7b8e5d9
c704816
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import gradio as gr  # Import Gradio for building the interactive UI
import cv2  # Import OpenCV for video processing and annotation
import os  # Import os for file handling
import numpy as np  # Import NumPy for array operations
from datetime import datetime  # Import datetime for timestamp generation
import matplotlib.pyplot as plt  # Import Matplotlib for plotting trends

# Import custom modules for fault detection, model loading, and settings
from services.detection_service import detect_faults_solar, detect_faults_windmill
from services.anomaly_service import track_faults, predict_fault
from models.solar_model import load_solar_model
from models.windmill_model import load_windmill_model
from config.settings import VIDEO_FOLDER

# Initialize global state to track faults across frames
logs = []  # List to store log entries
fault_counts = []  # List to store fault counts per frame
frame_numbers = []  # List to store frame numbers
total_detected = 0  # Counter for total faults detected

# Custom CSS to style the dashboard, mimicking the screenshot's blue borders and layout
css = """
<style>
.main-header {
    text-align: center;
    font-size: 24px;
    font-weight: bold;
    color: #333;
    margin-bottom: 10px;
}
.status {
    text-align: center;
    font-size: 16px;
    color: #333;
    margin-bottom: 20px;
}
.section-title {
    font-size: 16px;
    font-weight: bold;
    color: #333;
    text-transform: uppercase;
    margin-bottom: 10px;
}
.section-box {
    border: 1px solid #4A90E2;
    padding: 10px;
    border-radius: 5px;
    margin-bottom: 20px;
}
.log-entry {
    font-size: 14px;
    color: #333;
    margin-bottom: 5px;
}
.metrics-text {
    font-size: 14px;
    color: #333;
    margin-bottom: 5px;
}
</style>
"""

# Function to process video frames and detect faults
def process_video(video_path, detection_type):
    global logs, fault_counts, frame_numbers, total_detected
    cap = cv2.VideoCapture(video_path)  # Open the video file
    if not cap.isOpened():
        return "Error: Could not open video file.", None, None, None, None, None

    model = load_solar_model() if detection_type == "Solar Panel" else load_windmill_model()  # Load appropriate model
    frame_count = 0

    # Clear previous state for a new video session
    logs.clear()
    fault_counts.clear()
    frame_numbers.clear()
    total_detected = 0

    while cap.isOpened():
        ret, frame = cap.read()  # Read each frame
        if not ret:
            break

        frame_count += 1
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # Convert to RGB for display

        # Detect faults using the appropriate model
        faults = detect_faults_solar(model, frame_rgb) if detection_type == "Solar Panel" else detect_faults_windmill(model, frame_rgb)
        num_faults = len(faults)

        # Draw bounding boxes and labels for detected faults
        for fault in faults:
            x, y = int(fault['location'][0]), int(fault['location'][1])
            cv2.rectangle(frame_rgb, (x-30, y-30), (x+30, y+30), (255, 0, 0), 2)  # Draw blue box
            cv2.putText(frame_rgb, f"{fault['type']}", (x, y-40), 
                       cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)  # Add fault type label

        # Update state with current frame data
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"{timestamp} - Frame {frame_count} - Faults: {num_faults}"
        logs.append(log_entry)
        total_detected += num_faults
        fault_counts.append(num_faults)
        frame_numbers.append(frame_count)

        # Limit data to last 100 frames for performance
        if len(frame_numbers) > 100:
            frame_numbers.pop(0)
            fault_counts.pop(0)

        # Prepare outputs for Gradio UI
        video_output = frame_rgb
        metrics = f"faults: {num_faults}<br>total_detected: {total_detected}"
        live_logs = "<br>".join(logs[-20:])  # Display last 20 logs
        last_5_events = "<br>".join(logs[-5:]) if logs else "No events yet"
        prediction = "Potential fault escalation detected!" if predict_fault(fault_counts) else ""

        # Generate fault trends graph
        fig, ax = plt.subplots(figsize=(6, 3))
        ax.plot(frame_numbers, fault_counts, marker='o', color='blue')
        ax.set_title("Faults Over Time", fontsize=10)
        ax.set_xlabel("Frame", fontsize=8)
        ax.set_ylabel("Count", fontsize=8)
        ax.grid(True)
        ax.tick_params(axis='both', which='major', labelsize=6)
        plt.tight_layout()

        return video_output, metrics, live_logs, last_5_events, fig, prediction

# Create Gradio Blocks interface with custom CSS
with gr.Blocks(css=css) as demo:
    gr.Markdown("### THERMAL FAULT DETECTION DASHBOARD")  # Main header
    gr.Markdown("#### 🟒 RUNNING")  # Status indicator

    with gr.Row():
        with gr.Column(scale=3):
            with gr.Column():
                gr.Markdown("**LIVE VIDEO FEED**")  # Section title
                gr.Markdown('<div class="section-box">', unsafe_allow_html=True)
                video_output = gr.Image(label="", interactive=False)  # Display video feed
                gr.Markdown('</div>', unsafe_allow_html=True)
        with gr.Column(scale=1):
            with gr.Column():
                gr.Markdown("**LIVE METRICS**")  # Section title
                gr.Markdown('<div class="section-box">', unsafe_allow_html=True)
                metrics_output = gr.Markdown(label="")  # Display metrics
                prediction_output = gr.Markdown(label="")  # Display prediction warning
                gr.Markdown('</div>', unsafe_allow_html=True)

    with gr.Row():
        with gr.Column(scale=1):
            with gr.Column():
                gr.Markdown("**LIVE LOGS**")  # Section title
                gr.Markdown('<div class="section-box">', unsafe_allow_html=True)
                logs_output = gr.Markdown(label="")  # Display live logs
                gr.Markdown('</div>', unsafe_allow_html=True)
            with gr.Column():
                gr.Markdown("**LAST 5 CAPTURED EVENTS**")  # Section title
                gr.Markdown('<div class="section-box">', unsafe_allow_html=True)
                events_output = gr.Markdown(label="")  # Display last 5 events
                gr.Markdown('</div>', unsafe_allow_html=True)
        with gr.Column(scale=2):
            with gr.Column():
                gr.Markdown("**DETECTION TRENDS**")  # Section title
                gr.Markdown('<div class="section-box">', unsafe_allow_html=True)
                gr.Markdown("**Faults Over Time**")  # Sub-title
                trends_output = gr.Plot(label="")  # Display fault trends graph
                gr.Markdown('</div>', unsafe_allow_html=True)

    # Sidebar for user inputs
    with gr.Row():
        with gr.Column():
            video_files = [f for f in os.listdir(VIDEO_FOLDER) if f.endswith('.mp4')]  # Get video files
            video_input = gr.Dropdown(choices=video_files, label="Select Video")  # Video selection
            detection_type = gr.Dropdown(choices=["Solar Panel", "Windmill"], label="Detection Type")  # Detection type
            submit_btn = gr.Button("Start Processing")  # Trigger button

    # Connect inputs to outputs with event trigger
    submit_btn.click(
        fn=process_video,
        inputs=[video_input, detection_type],
        outputs=[video_output, metrics_output, logs_output, events_output, trends_output, prediction_output],
        _js="() => [document.querySelector('input[type=\"file\"]').value, document.querySelector('select[name=\"detection_type\"]').value]"
    )

# Launch the Gradio app
demo.launch()