This project's goal is to use Sentinel-2 satellite imagery to classify land use and land cover. To do so, we use a Custom Light ResNet (Convolutional Neural Network) architecture, HTML/CSS/JS for the frontend, and Python with Flask for the backend.
My goal with this project was to learn more about computer vision, specifically Residual Networks (ResNet) and model optimization for CPU inference. It bridges the gap between remote sensing and deep learning, two fields I am passionate about.
CNN_training.ipynb- Notebook used to train the ResNet model (includes data augmentation)ModelCNN_WEBIA.keras- Saved Keras model used for inference (generate it by running the notebook)CNN_EuroSat.py- Flask backend for inferenceTemplates/html_map.html- Web interface (Leaflet)static/css_map.css- Stylesheet for the interfacestatic/js_map.js- Frontend logic (zone selection, tiling, API calls)image/scores.png- Training curves
- EuroSAT: 27,000 RGB images (64×64 pixels) from Sentinel-2 satellite.
- 10 Classes: AnnualCrop, Forest, HerbaceousVegetation, Highway, Industrial, Pasture, PermanentCrop, Residential, River, SeaLake.
- Preprocessing: Images are normalized ([0,1] range) and resized so they all have the same size.
- Source: TensorFlow Datasets
Unlike standard sequential models, this project uses a custom ResNet (Residual Network) to capture fine details.
Key features:
-
Residual Blocks: Skip connections to avoid the vanishing gradient problem and let the model learn deeper features.
-
GELU Activation: Used instead of ReLU, it converges better here.
-
Lightweight Design:
-
Starts with 32 filters (instead of the usual 64) to keep the computational cost down.
-
Total parameters: ~700k (vs 20M+ for a standard ResNet50).
-
Data Augmentation: Added directly in the training pipeline (random flip, rotation, zoom, contrast) to help the model generalize better.
The model was trained for 100 epochs with EarlyStopping and LearningRateScheduler to keep training stable.
- Test Accuracy: 96.85%
- Test Loss: 0.08816
Data augmentation removed the overfitting I had in earlier runs, and the training and validation curves now stay close to each other.
The web app doesn't need a GPU. The model is small (about 700k parameters) and the Flask backend runs the predictions directly on the CPU, tile by tile. To make the results a bit more stable, each tile is also predicted with a horizontal flip and the two probabilities are averaged (test time augmentation).
The application lets the user select a rectangle on a Leaflet map and run classification on this area.
- Frontend: Captures the selected geographical bounds.
- Tiling: The area is split into 64x64 pixel tiles, matching the Sentinel-2 resolution (~10m/px).
- Inference: The backend receives the image and runs predictions on the tiles using the Keras model.
- Visualization: The results are aggregated to show the dominant land cover and the class distribution in percentages.
- Clone this repository
- Install dependencies: With pip:
python -m venv vision
# Windows:
.\vision\Scripts\Activate.ps1
# Mac/Linux:
source vision/bin/activate
pip install --upgrade pip tensorflow numpy pillow flask flask-cors scikit-learn matplotlib seaborn ipykernel
- Inference Setup:
Ensure
ModelCNN_WEBIA.kerasis in the root folder (generated by the notebook). - Run the backend:
python CNN_EuroSat.py
- Open the interface in your browser at
http://localhost:5000/
This project started as an undergraduate final assignment and turned into a personal project about Deep Learning optimization. Moving from a simple CNN to a ResNet improved the accuracy by nearly 5%.
- Urban Differentiation: Better tell "Highway" and "River" apart using texture-specific augmentation.
- Client-Side Inference: Port the model to TensorFlow.js so the predictions can run in the browser (no Python backend needed).