koulsahil commited on
Commit
c661aaa
·
verified ·
1 Parent(s): 96118eb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +291 -0
app.py ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from PIL import Image
3
+ import numpy as np
4
+ import tensorflow as tf
5
+ from tensorflow.keras.models import load_model
6
+ import io
7
+ import random
8
+ import time
9
+ from huggingface_hub import hf_hub_download
10
+
11
+ # Load model from Hugging Face Model Hub
12
+ model_path = hf_hub_download(repo_id="koulsahil/LandCoverClassification_EuroSat", filename="eurosat_rgb_model.h5")
13
+ model = torch.load(model_path)
14
+ model.eval()
15
+
16
+
17
+ # Define the class labels (replace with your EuroSAT classes)
18
+ class_labels = [
19
+ "AnnualCrop", "Forest", "HerbaceousVegetation", "Highway", "Industrial",
20
+ "Pasture", "PermanentCrop", "Residential", "River", "SeaLake"
21
+ ]
22
+
23
+ # Function to preprocess the image for the model
24
+ def preprocess_image(image):
25
+ # Convert image to RGB if it has an alpha channel (4 channels)
26
+ if image.mode == 'RGBA':
27
+ image = image.convert('RGB')
28
+ image = image.resize((64, 64)) # Resize to match EuroSAT input size
29
+ image = np.array(image) / 255.0 # Normalize pixel values
30
+ image = np.expand_dims(image, axis=0) # Add batch dimension
31
+ return image
32
+
33
+ # Function to make predictions
34
+ def predict(image):
35
+ processed_image = preprocess_image(image)
36
+ predictions = model.predict(processed_image)
37
+ predicted_class = class_labels[np.argmax(predictions)]
38
+ confidence = np.max(predictions)
39
+ return predicted_class, confidence
40
+
41
+
42
+
43
+
44
+ # Set the page title and favicon (emoji as the icon)
45
+ st.set_page_config(
46
+ page_title="Land Cover Classification", # Title of the app
47
+ page_icon="🌍", # Use the world emoji as the icon
48
+ )
49
+
50
+
51
+
52
+
53
+
54
+ # Custom CSS for styling
55
+ st.markdown("""
56
+ <style>
57
+ .stButton button {
58
+ background-color: #4CAF50;
59
+ color: white;
60
+ border-radius: 5px;
61
+ padding: 10px 20px;
62
+ font-size: 16px;
63
+ }
64
+ .stButton button:hover {
65
+ background-color: #45a049;
66
+ }
67
+ .stProgress > div > div > div {
68
+ background-color: #4CAF50;
69
+ }
70
+ .stMarkdown h1 {
71
+ color: #4CAF50;
72
+ }
73
+ .stMarkdown h2 {
74
+ color: #2E86C1;
75
+ }
76
+ .upload-section {
77
+ height: 150px; /* Increase the height of the upload section */
78
+ }
79
+ .thumbnail {
80
+ cursor: pointer;
81
+ border: 2px solid transparent;
82
+ transition: border 0.3s ease;
83
+ margin: 5px;
84
+ }
85
+ .thumbnail:hover {
86
+ border: 2px solid #4CAF50;
87
+ }
88
+ </style>
89
+ """, unsafe_allow_html=True)
90
+
91
+ # Sidebar for project information
92
+ import streamlit as st
93
+
94
+ with st.sidebar:
95
+ st.title("About the Project 🌍")
96
+ st.write("""
97
+ Hi, I’m **Sahil!** I built this web app to classify satellite images using Neural Networks,
98
+ This app leverages a **custom VGG16 deep learning model** trained on the **EuroSAT dataset** to classify land cover types in satellite images.
99
+ The EuroSAT dataset is a collection of **27,000 labeled satellite images** covering **10 distinct land cover classes**, such as forests, crops, industrial areas, and water bodies.
100
+
101
+
102
+ ### How to Use:
103
+ 1. **Select an Image**:
104
+ - Drag and drop one of the **sample image thumbnails** to the upload section to quickly test the model.
105
+ - Or use the dropdown menu to choose from a list of sample images, or click the select random button to choose a random image from the list.
106
+ - Alternatively, **upload your own satellite image** by dragging and dropping it into the upload section.
107
+ 2. **Make a Prediction**:
108
+ - Once an image is selected or uploaded, the model will automatically analyze it and display the **predicted land cover type** along with a **confidence score**.
109
+ 3. **Interpret the Results**:
110
+ - The app will show the **top predicted class** and its confidence level.
111
+ - You can also view the **top 3 predictions** to understand the model's certainty across multiple classes.
112
+
113
+
114
+ ### GitHub Repository:
115
+ Explore the code, dataset, and model training process on GitHub:
116
+ [GitHub Repository](https://koulmesahil.github.io/) | [LinkedIn](https://www.linkedin.com/in/sahilkoul123/)
117
+ """)
118
+
119
+ # Main layout
120
+ st.title("Land Cover Classification from Satellite Images ")
121
+ st.write("🖼️📸 Drag and drop one of the thumbnails below, select a random image from the dropdown, or upload your own image to classify its land cover type.🌍")
122
+
123
+ # Define sample images
124
+ sample_images = {
125
+ "Highway": "sample_images/Highway_1004.jpg",
126
+ "Annual Crop": "sample_images/AnnualCrop_102.jpg",
127
+ "Forest": "sample_images/Forest_1019.jpg",
128
+ "Herbaceous Vegetation": "sample_images/HerbaceousVegetation_1024.jpg",
129
+ "Industrial": "sample_images/Industrial_1015.jpg",
130
+ "Pasture": "sample_images/Pasture_1023.jpg",
131
+ "Sea Lake": "sample_images/SeaLake_1017.jpg",
132
+ "River": "sample_images/River_1014.jpg",
133
+ "Permenant Crop": "sample_images/PermanentCrop_1004.jpg",
134
+ "Residential": "sample_images/Residential_1019.jpg",
135
+ # Add more sample images here
136
+ }
137
+
138
+ # Thumbnail Section
139
+ st.write("### Sample Image Thumbnails")
140
+ cols = st.columns(len(sample_images)) # Create columns for thumbnails
141
+ for idx, (label, image_path) in enumerate(sample_images.items()):
142
+ with cols[idx]:
143
+ # Display the thumbnail
144
+ image = Image.open(image_path)
145
+ image.thumbnail((100, 100)) # Resize the image to a smaller thumbnail
146
+
147
+ st.image(image, use_container_width=True, caption=None)
148
+
149
+
150
+ # Dropdown menu for sample images
151
+ #st.write("### Select an Image from Dropdown")
152
+ selected_image_label = st.selectbox("Choose a category to view a random image:", ["Pick a category"] + list(sample_images.keys()))
153
+
154
+ if selected_image_label != "Pick a category":
155
+ image_path = sample_images[selected_image_label]
156
+ with open(image_path, "rb") as file:
157
+ uploaded_file = file.read()
158
+ st.session_state.uploaded_file = uploaded_file
159
+ st.session_state.selected_image_label = selected_image_label
160
+
161
+
162
+ # Add a "Select Random" button
163
+ if st.button("Random Selection"):
164
+ random_label, random_image_path = random.choice(list(sample_images.items()))
165
+ with open(random_image_path, "rb") as file:
166
+ uploaded_file = file.read()
167
+ st.session_state.uploaded_file = uploaded_file
168
+ st.session_state.selected_image_label = random_label
169
+ st.success(f"Randomly selected image: **{random_label}**")
170
+
171
+
172
+ # JavaScript & CSS to dynamically change the border color
173
+ st.markdown(
174
+ """
175
+ <style>
176
+ /* Base styling for the upload box */
177
+ div.stFileUploader {
178
+ height: 250px !important;
179
+ width: 100% !important;
180
+ border: 3px dashed grey !important;
181
+ padding: 40px !important;
182
+ border-radius: 10px;
183
+ transition: all 0.3s ease-in-out;
184
+ }
185
+
186
+ /* Upload text styling */
187
+ div.stFileUploader > label {
188
+ font-size: 20px !important;
189
+ font-weight: bold !important;
190
+ color: grey !important;
191
+ text-align: center !important;
192
+ }
193
+
194
+ /* JavaScript to change colors dynamically */
195
+ <script>
196
+ function updateUploaderColor() {
197
+ var uploader = document.querySelector("div.stFileUploader");
198
+ if (uploader && uploader.querySelector("input").files.length > 0) {
199
+ uploader.style.borderColor = "#4CAF50";
200
+ uploader.style.color = "#4CAF50";
201
+ } else {
202
+ uploader.style.borderColor = "grey";
203
+ uploader.style.color = "grey";
204
+ }
205
+ }
206
+
207
+ document.addEventListener("DOMContentLoaded", function() {
208
+ var fileInput = document.querySelector("div.stFileUploader input");
209
+ if (fileInput) {
210
+ fileInput.addEventListener("change", updateUploaderColor);
211
+ }
212
+ });
213
+ </script>
214
+ </style>
215
+ """,
216
+ unsafe_allow_html=True,
217
+ )
218
+
219
+ st.write("### Upload Your Image")
220
+ uploaded_file = st.file_uploader(
221
+ "Drag and drop an image here",
222
+ type=["jpg", "jpeg", "png"],
223
+ key="uploader",
224
+ accept_multiple_files=False,
225
+ help="Upload an image to classify its land cover type."
226
+ )
227
+
228
+ if uploaded_file:
229
+ st.markdown(
230
+ """
231
+ <style>
232
+ div.stFileUploader {
233
+ border-color: #4CAF50 !important;
234
+ color: #4CAF50 !important;
235
+ }
236
+ </style>
237
+ """,
238
+ unsafe_allow_html=True,
239
+ )
240
+
241
+ # Display the uploaded/selected image and make predictions
242
+ if uploaded_file is not None:
243
+ try:
244
+ file_type = uploaded_file.type
245
+ if file_type not in ["image/jpeg", "image/png"]:
246
+ st.error("Unsupported file type. Please upload a JPG or PNG image.")
247
+ else:
248
+ image = Image.open(uploaded_file)
249
+ st.session_state.uploaded_file = uploaded_file.getvalue()
250
+ st.session_state.selected_image_label = "Uploaded Image"
251
+ except Exception as e:
252
+ st.error(f"Error loading image: {e}")
253
+
254
+
255
+ # Display the uploaded/selected image and make predictions
256
+ if "uploaded_file" in st.session_state:
257
+ image = Image.open(io.BytesIO(st.session_state.uploaded_file))
258
+
259
+ # Display the image with a smaller size
260
+ st.image(image, caption=f"Selected Image: {st.session_state.selected_image_label}", width=300)
261
+
262
+ # Show balloons effect after the prediction is done
263
+ with st.spinner("Analyzing the image..."):
264
+ time.sleep(1) # Simulate processing delay
265
+ predicted_class, confidence = predict(image)
266
+ st.balloons() # Display balloons when prediction is complete
267
+
268
+ # Display the prediction results in a more prominent section
269
+ st.markdown("## Prediction Results")
270
+ st.success(f"**Predicted Class:** {predicted_class}")
271
+ st.info(f"**Confidence:** {confidence * 100:.2f}%")
272
+
273
+ # Visualize confidence as a progress bar with a label
274
+ st.markdown("**Confidence Level:**")
275
+ st.progress(float(confidence))
276
+
277
+ # Show top 3 predictions
278
+ st.markdown("### Top 3 Predictions")
279
+ processed_image = preprocess_image(image)
280
+ predictions = model.predict(processed_image)
281
+ top_indices = np.argsort(predictions[0])[-3:][::-1] # Get top 3 predictions
282
+ for i in top_indices:
283
+ st.write(f"- **{class_labels[i]}**: {predictions[0][i] * 100:.2f}%")
284
+
285
+
286
+
287
+ # Footer
288
+ st.markdown("---")
289
+ st.markdown("""
290
+ [GitHub Repository](https://koulmesahil.github.io/) | [LinkedIn](https://www.linkedin.com/in/sahilkoul123/)
291
+ """)