import streamlit as st
from PIL import Image
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import load_model
import io
import random
import time
from huggingface_hub import hf_hub_download
# Load model from Hugging Face Model Hub
model_path = hf_hub_download(repo_id="koulsahil/LandCoverClassification_EuroSat", filename="eurosat_rgb_model.h5")
model = tf.keras.models.load_model(model_path)
# Define the class labels (replace with your EuroSAT classes)
class_labels = [
"AnnualCrop", "Forest", "HerbaceousVegetation", "Highway", "Industrial",
"Pasture", "PermanentCrop", "Residential", "River", "SeaLake"
]
# Function to preprocess the image for the model
def preprocess_image(image):
# Convert image to RGB if it has an alpha channel (4 channels)
if image.mode == 'RGBA':
image = image.convert('RGB')
image = image.resize((64, 64)) # Resize to match EuroSAT input size
image = np.array(image) / 255.0 # Normalize pixel values
image = np.expand_dims(image, axis=0) # Add batch dimension
return image
# Function to make predictions
def predict(image):
processed_image = preprocess_image(image)
predictions = model.predict(processed_image)
predicted_class = class_labels[np.argmax(predictions)]
confidence = np.max(predictions)
return predicted_class, confidence
def create_map_animation():
st.markdown("""
""", unsafe_allow_html=True)
# Set the page title and favicon (emoji as the icon)
st.set_page_config(
page_title="Land Cover Classification", # Title of the app
page_icon="š", # Use the world emoji as the icon
)
# Custom CSS for styling
st.markdown("""
""", unsafe_allow_html=True)
# Sidebar for project information
import streamlit as st
with st.sidebar:
st.title("About the Project š")
st.write("""
Hi, Iām **Sahil!** I built this web app to classify satellite images using Neural Networks,
This app leverages a **custom VGG16 deep learning model** trained on the **EuroSAT dataset** to classify land cover types in satellite images.
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.
### How to Use:
1. **Select an Image**:
- Drag and drop one of the **sample image thumbnails** to the upload section to quickly test the model.
- 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.
- Alternatively, **upload your own satellite image** by dragging and dropping it into the upload section.
2. **Make a Prediction**:
- 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**.
3. **Interpret the Results**:
- The app will show the **top predicted class** and its confidence level.
- You can also view the **top 3 predictions** to understand the model's certainty across multiple classes.
### GitHub Repository:
Explore the code, dataset, and model training process on GitHub:
[GitHub Repository](https://koulmesahil.github.io/) | [LinkedIn](https://www.linkedin.com/in/sahilkoul123/)
""")
# Main layout
st.title("Land Cover Classification from Satellite Images ")
create_map_animation()
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.š")
# Define sample images
sample_images = {
"Highway": "sample_images/Highway_1004.jpg",
"Annual Crop": "sample_images/AnnualCrop_102.jpg",
"Forest": "sample_images/Forest_1019.jpg",
"Herbaceous Vegetation": "sample_images/HerbaceousVegetation_1024.jpg",
"Industrial": "sample_images/Industrial_1015.jpg",
"Pasture": "sample_images/Pasture_1023.jpg",
"Sea Lake": "sample_images/SeaLake_1017.jpg",
"River": "sample_images/River_1014.jpg",
"Permenant Crop": "sample_images/PermanentCrop_1004.jpg",
"Residential": "sample_images/Residential_1019.jpg",
# Add more sample images here
}
# Thumbnail Section
st.write("### Sample Image Thumbnails")
cols = st.columns(len(sample_images)) # Create columns for thumbnails
for idx, (label, image_path) in enumerate(sample_images.items()):
with cols[idx]:
# Display the thumbnail
image = Image.open(image_path)
image.thumbnail((100, 100)) # Resize the image to a smaller thumbnail
st.image(image, use_container_width=True, caption=None)
# Dropdown menu for sample images
#st.write("### Select an Image from Dropdown")
selected_image_label = st.selectbox("Choose a category to view a random image:", ["Pick a category"] + list(sample_images.keys()))
if selected_image_label != "Pick a category":
image_path = sample_images[selected_image_label]
with open(image_path, "rb") as file:
uploaded_file = file.read()
st.session_state.uploaded_file = uploaded_file
st.session_state.selected_image_label = selected_image_label
# Add a "Select Random" button
if st.button("Random Selection"):
random_label, random_image_path = random.choice(list(sample_images.items()))
with open(random_image_path, "rb") as file:
uploaded_file = file.read()
st.session_state.uploaded_file = uploaded_file
st.session_state.selected_image_label = random_label
st.success(f"Randomly selected image: **{random_label}**")
# JavaScript & CSS to dynamically change the border color
st.markdown(
"""
""",
unsafe_allow_html=True,
)
st.write("### Upload Your Image")
uploaded_file = st.file_uploader(
"Drag and drop an image here",
type=["jpg", "jpeg", "png"],
key="uploader",
accept_multiple_files=False,
help="Upload an image to classify its land cover type."
)
if uploaded_file:
st.markdown(
"""
""",
unsafe_allow_html=True,
)
# Display the uploaded/selected image and make predictions
if uploaded_file is not None:
try:
file_type = uploaded_file.type
if file_type not in ["image/jpeg", "image/png"]:
st.error("Unsupported file type. Please upload a JPG or PNG image.")
else:
image = Image.open(uploaded_file)
st.session_state.uploaded_file = uploaded_file.getvalue()
st.session_state.selected_image_label = "Uploaded Image"
except Exception as e:
st.error(f"Error loading image: {e}")
# Display the uploaded/selected image and make predictions
if "uploaded_file" in st.session_state:
image = Image.open(io.BytesIO(st.session_state.uploaded_file))
# Display the image with a smaller size
st.image(image, caption=f"Selected Image: {st.session_state.selected_image_label}", width=300)
# Show balloons effect after the prediction is done
with st.spinner("Analyzing the image..."):
time.sleep(1) # Simulate processing delay
predicted_class, confidence = predict(image)
st.balloons() # Display balloons when prediction is complete
# Display the prediction results in a more prominent section
st.markdown("## Prediction Results")
st.success(f"**Predicted Class:** {predicted_class}")
st.info(f"**Confidence:** {confidence * 100:.2f}%")
# Visualize confidence as a progress bar with a label
st.markdown("**Confidence Level:**")
st.progress(float(confidence))
# Show top 3 predictions
st.markdown("### Top 3 Predictions")
processed_image = preprocess_image(image)
predictions = model.predict(processed_image)
top_indices = np.argsort(predictions[0])[-3:][::-1] # Get top 3 predictions
for i in top_indices:
st.write(f"- **{class_labels[i]}**: {predictions[0][i] * 100:.2f}%")
# Footer
st.markdown("---")
st.markdown("""
[GitHub Repository](https://koulmesahil.github.io/) | [LinkedIn](https://www.linkedin.com/in/sahilkoul123/)
""")