File size: 6,114 Bytes
adfbf25
e81860f
bf0e73e
 
 
35aea9a
 
e81860f
35aea9a
e81860f
35aea9a
 
e81860f
35aea9a
e81860f
 
35aea9a
 
 
 
 
4cd65a2
 
e81860f
4cd65a2
bf0e73e
35aea9a
 
 
 
 
4cd65a2
35aea9a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4cd65a2
 
 
 
 
 
 
 
 
 
ddfd276
 
 
 
35aea9a
ddfd276
 
35aea9a
 
 
 
4cd65a2
bf0e73e
35aea9a
bf0e73e
 
 
35aea9a
4cd65a2
35aea9a
bf0e73e
 
35aea9a
 
 
bf0e73e
35aea9a
 
2948299
35aea9a
4cd65a2
35aea9a
 
 
bf0e73e
 
 
 
 
35aea9a
 
4cd65a2
35aea9a
 
 
4cd65a2
 
35aea9a
 
 
 
4cd65a2
35aea9a
 
bf0e73e
35aea9a
 
bf0e73e
 
4cd65a2
e81860f
 
bf0e73e
e81860f
35aea9a
 
 
 
 
 
 
4cd65a2
35aea9a
bf0e73e
35aea9a
 
 
bf0e73e
 
35aea9a
 
bf0e73e
 
 
35aea9a
bf0e73e
35aea9a
bf0e73e
35aea9a
bf0e73e
35aea9a
 
4cd65a2
 
 
 
 
 
 
 
 
 
 
 
 
bf0e73e
35aea9a
e81860f
 
35aea9a
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
import streamlit as st
import cv2
import numpy as np
import tempfile
import os
import torch
from ultralytics import YOLO

# Set page config
st.set_page_config(page_title="Solar Panel Fault Detection", layout="wide")
st.title("Solar Panel Fault Detection (Optimized)")
st.write("Upload a thermal video (MP4) to detect thermal, dust, and power generation faults.")

# Load YOLO model
@st.cache_resource
def load_model():
    model = YOLO("yolov5s.pt")  # Replace with your custom-trained model if available
    return model

model = load_model()

# Fault detection with frame & location tracking
def detect_faults(frame, results, frame_number):
    faults = {"Thermal Fault": False, "Dust Fault": False, "Power Generation Fault": False}
    fault_locations = []
    annotated_frame = frame.copy()

    for result in results:
        boxes = result.boxes
        for box in boxes:
            x1, y1, x2, y2 = map(int, box.xyxy[0])
            conf = float(box.conf[0])
            cls = int(box.cls[0])

            roi = frame[y1:y2, x1:x2]
            if roi.size == 0:
                continue
            mean_intensity = np.mean(roi)

            if mean_intensity > 200:
                faults["Thermal Fault"] = True
                color = (255, 0, 0)
                label = "Thermal Fault"
            elif mean_intensity < 100:
                faults["Dust Fault"] = True
                color = (0, 255, 0)
                label = "Dust Fault"
            else:
                continue

            # Track location
            fault_locations.append({
                "frame": frame_number,
                "label": label,
                "confidence": round(conf, 2),
                "intensity": round(mean_intensity, 2),
                "box": (x1, y1, x2, y2)
            })

            # Annotate
            overlay = annotated_frame.copy()
            alpha = 0.3
            cv2.rectangle(overlay, (x1, y1), (x2, y2), color, -1)
            cv2.addWeighted(overlay, alpha, annotated_frame, 1 - alpha, 0, annotated_frame)
            cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, 2)
            cv2.putText(annotated_frame, f"{label} ({mean_intensity:.1f})", (x1, y1 - 10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)

    if faults["Thermal Fault"] or faults["Dust Fault"]:
        faults["Power Generation Fault"] = True

    return annotated_frame, faults, fault_locations

# Video processing
def process_video(video_path):
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        st.error("Failed to open video.")
        return None, None, None

    fps = int(cap.get(cv2.CAP_PROP_FPS))
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    output_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
    out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))

    frame_count = 0
    video_faults = {"Thermal Fault": False, "Dust Fault": False, "Power Generation Fault": False}
    all_fault_locations = []
    process_every_n_frames = fps  # 1 frame per second

    with st.spinner("Processing video..."):
        progress = st.progress(0)
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break

            if frame_count % process_every_n_frames == 0:
                resized = cv2.resize(frame, (640, 480))
                frame_rgb = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
                results = model(frame_rgb, verbose=False)

                annotated_frame, faults, locations = detect_faults(frame, results, frame_count)
                all_fault_locations.extend(locations)

                for fault in video_faults:
                    video_faults[fault] |= faults[fault]
            else:
                annotated_frame = frame

            out.write(annotated_frame)
            frame_count += 1
            progress.progress(min(frame_count / total_frames, 1.0))

    cap.release()
    out.release()
    return output_path, video_faults, all_fault_locations

# File uploader
uploaded_file = st.file_uploader("Upload a thermal video", type=["mp4"])

if uploaded_file:
    temp_input_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
    with open(temp_input_path, "wb") as f:
        f.write(uploaded_file.read())

    st.video(temp_input_path)

    output_path, video_faults, fault_locations = process_video(temp_input_path)

    if output_path:
        st.subheader("Detection Results")
        st.video(output_path)
        st.write("### Detected Faults:")
        for fault, detected in video_faults.items():
            color = "red" if detected else "green"
            st.markdown(f"- **{fault}**: <span style='color:{color}'>{'Detected' if detected else 'Not Detected'}</span>", unsafe_allow_html=True)

        if any(video_faults.values()):
            st.subheader("Recommendations")
            if video_faults["Thermal Fault"]:
                st.write("- Check for overheating components.")
            if video_faults["Dust Fault"]:
                st.write("- Clean dust from solar panel surface.")
            if video_faults["Power Generation Fault"]:
                st.write("- Investigate potential efficiency issues.")
        else:
            st.success("No faults detected. The system seems to be functioning properly.")

        # Display fault locations
        if fault_locations:
            st.subheader("πŸ“ Fault Locations in Video")
            st.dataframe([
                {
                    "Frame": loc["frame"],
                    "Fault Type": loc["label"],
                    "Confidence": loc["confidence"],
                    "Intensity": loc["intensity"],
                    "Box": f"{loc['box']}"
                } for loc in fault_locations
            ])

        os.unlink(output_path)
    os.unlink(temp_input_path)

st.markdown("---")
st.caption("Built with Streamlit + YOLOv5 (Ultralytics) for fast fault detection.")