An automated deep learning system that detects and classifies solar panel defects from drone and field inspection images using PyTorch.
🔗 Live Deployment: View Live App Demo
Solar panels are exposed to harsh outdoor elements year-round. Over time, they accumulate dust, get covered by snow, get hit by debris, or experience internal electrical failures.
If these issues aren't caught early:
- Energy Loss: Dirty or covered panels produce zero to low electricity, costing operators thousands of dollars.
- Safety Risks: Physical or electrical damages can form localized hot-spots that permanently burn the panels or even trigger fires.
- The Manual Bottleneck: Manually inspecting massive solar farms (often containing thousands of panels) using drones or handheld thermal cameras is incredibly slow, tedious, and error-prone.
This project automates solar panel inspections by training a deep learning model to instantly classify images into 6 distinct categories:
- Clean: Normal, healthy panels operating at peak performance.
- Dusty: Panels covered in dirt or dust; requires scheduled cleaning.
- Bird-drop: Localized organic blockages that can cause micro-hotspots.
- Snow-Covered: Panels blocked completely by snow; requires immediate clearing.
- Physical-Damage: Panels with visible cracks, broken glass, or frame issues.
- Electrical-damage: Critical internal cell failures (such as hot-spots or short circuits).
Here is the interactive Streamlit interface where field operators can drag-and-drop solar panel images to get instant diagnostic results and actionable alerts.
The confusion matrix showing how well the final model differentiates between different types of defects:

The model was evaluated on a Validation split (20% of the total dataset) consisting of 177 images.
| Class | Precision | Recall | F1-Score | Support (Validation Images) |
|---|---|---|---|---|
| Bird-drop | 0.92 | 0.83 | 0.87 | 41 |
| Clean | 0.77 | 0.89 | 0.83 | 38 |
| Dusty | 0.91 | 0.79 | 0.85 | 38 |
| Electrical-damage | 0.76 | 0.90 | 0.83 | 21 |
| Physical-Damage | 0.77 | 0.71 | 0.74 | 14 |
| Snow-Covered | 0.92 | 0.92 | 0.92 | 25 |
| Overall Accuracy | - | - | 0.85 | 177 |
For solar operators, a False Negative (missing a damaged panel) is much more expensive than a False Positive (inspecting a panel that turns out to be fine). Therefore, the fine-tuned model exhibits strong Recall on critical defect classes like Electrical-damage (90% Recall) and Clean (89% Recall), ensuring operators are reliably warned when a panel's performance or safety is compromised.
Building this pipeline involved a systematic journey through research, experimentation, and production engineering:
graph TD
A[Raw Image Data ./data] -->|Explore & Split| B[Stratified Split 80/20]
B --> C[Custom SolarDataset PIL Resize & RGB conversion]
C --> D[ResNet50 Transfer Learning Stage 1: Freeze Backbone & Warm-up Head]
D --> E[ResNet50 Fine-tuning Stage 2: Unfreeze Layer 4 with Differential LR]
E --> F[Final Model solar_panel_resnet50_best.pt]
We started with 885 raw images. To evaluate true generalization, we used a stratified Train/Validation split (80/20) via train_test_split. Using stratified splits ensures that the ratio of rare defects remains identical in both training and validation sets, protecting the model against lucky or unlucky splits.
We standardized our preprocessing to ImageNet normalization across all pipelines (training, validation, and Streamlit inference). We implemented a custom SolarDataset wrapper that opens images in PIL, converts them to RGB, and resizes them to
Because categories like Physical-Damage had far fewer samples than Clean, we mitigated overfitting and imbalance by:
- Computing and applying balanced class weights during model training inside
nn.CrossEntropyLoss. - Adding a Dropout layer (p=0.5) to regularize the classification head.
- Freezing BatchNorm running statistics (
freeze_bn) of the backbone to prevent statistic drift during training.
We utilized a ResNet50 backbone pre-trained on ImageNet.
-
Stage 1 (Warm-up): Froze the base backbone and trained the custom classification head (Linear 128 + ReLU + Dropout) with a learning rate of
$10^{-3}$ for 20 epochs. -
Stage 2 (Fine-tuning): Unfroze
layer4of the ResNet50 backbone and trained it with a tiny learning rate ($10^{-5}$ ) while training the classifier head at$10^{-4}$ for 15 epochs, restoring the best model weights based on validation loss.
solar-panel-pytorch/
├── .gitignore
├── .python-version
├── pyproject.toml # Project dependencies & tool configurations
├── README.md # You are here!
├── requirements.txt # Pinned python packages for compatibility
├── train.py # Main execution script to train the model
├── models/ # Saved models (solar_panel_resnet50_best.pt - not pushed to Git)
├── notebooks/
│ └── main.ipynb # Step-by-step exploration notebook (imports from src)
└── src/ # Custom Python modules
├── dataset.py # SolarDataset class & transforms
├── model.py # SolarResNet model definition
└── engine.py # train_one_epoch & validate helper loops
-
Clone the repository and navigate inside:
cd "Solar-Panel-Pytorch"
-
Set up a Python Virtual Environment:
python -m venv venv # On Windows: venv\Scripts\activate # On Mac/Linux: source venv/bin/activate
-
Install Dependencies:
pip install -r requirements.txt # Alternatively, if using uv: uv pip install -r requirements.txt -
Train the Model:
python train.py
- Drone Camera Integration: Package the classification system as a lightweight API (using FastAPI) to receive real-time streaming inputs directly from drone hardware during field flights.
- Active Learning Pipeline: Automatically collect uncertain or misclassified samples for human review and continuous model retraining.
- Monitoring Dashboard: Build a centralized monitoring dashboard to track inspection history, defect statistics, and maintenance alerts across solar farms.
- Multi-Defect Detection: Support simultaneous detection of multiple defects in a single solar panel image.