An image-based plastic classification system. Upload or photograph a plastic item and get its resin type, health/safety info, recycling instructions, and eco-friendly alternatives — powered by a fine-tuned EfficientNet-B0 model and the Gemini API.
- Classifies plastics into 6 types: HDPE, LDPE, PET, PP, PS, PVC
- Returns confidence score and full probability distribution across all 6 classes
- Provides static structured info: common uses, health concerns, recyclability, decomposition time
- Generates disposal suggestions via the Gemini 2.0 Flash API (with a static fallback if unavailable)
- Flags low-confidence predictions (below 70%) with an uncertainty warning
- Supports both file upload (drag & drop) and live webcam capture
| Layer | Technology |
|---|---|
| Backend | FastAPI + uvicorn (Python 3.10+) |
| ML | PyTorch + torchvision — EfficientNet-B0 |
| AI Suggestions | Google Gemini 2.0 Flash API |
| Image Processing | Pillow (PIL) |
| Frontend | HTML5 + CSS3 + Vanilla JS |
| Config | pydantic-settings + python-dotenv |
replastify/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI app + startup
│ │ ├── config.py # Settings (model path, thresholds, Gemini key)
│ │ ├── routes/predict.py # POST /predict, GET /health, GET /plastic-types
│ │ ├── services/
│ │ │ ├── classifier.py # Model loading + inference
│ │ │ ├── gemini.py # Gemini API integration (async, fallback)
│ │ │ └── plastic_info.py # Static knowledge base for all 6 types
│ │ └── utils/image_utils.py # Image validation + preprocessing
│ ├── models/
│ │ └── best_efficientnet_b0.pth # Trained model weights (~17 MB)
│ ├── .env # API keys (gitignored)
│ └── requirements.txt
├── frontend/
│ ├── index.html
│ ├── css/style.css
│ └── js/app.js
├── notebooks/
│ ├── 01_data_exploration.py
│ ├── 02_split_dataset.py
│ ├── 03_train_model.py # 2-stage transfer learning pipeline
│ └── 04_evaluate_model.py # Metrics, confusion matrix, visualizations
├── data/
│ ├── raw/ # Original labeled images (gitignored)
│ └── processed/ # train / val / test splits (gitignored)
└── docs/
├── results_summary.md # Concise metrics summary
└── results_analysis.md # Detailed model evaluation report
Prerequisites: Python 3.10+, pip
# 1. Clone and enter the repo
git clone <repo-url>
cd replastify
# 2. Create and activate virtual environment
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# 3. Install dependencies
pip install -r backend/requirements.txt
# 4. Configure environment
cp backend/.env.example backend/.env
# Edit backend/.env — add your GEMINI_API_KEY (optional; static fallback works without it)
# 5. Run the server
cd backend
uvicorn app.main:app --reload --port 8000- App: http://localhost:8000
- API docs (Swagger): http://localhost:8000/docs
The backend serves the frontend as static files — no separate frontend server needed.
| Property | Value |
|---|---|
| Architecture | EfficientNet-B0 (ImageNet pretrained) |
| Custom head | Dropout(0.4) → Linear(1280→256) → ReLU → Dropout(0.3) → Linear(256→6) |
| Input | 224×224×3 (resize 256, center crop 224, ImageNet normalization) |
| Classes | HDPE, LDPE, PET, PP, PS, PVC |
| Training | 2-stage: frozen backbone (10 epochs) then partial unfreeze (up to 20 epochs) |
| Optimizer | AdamW with CosineAnnealing LR schedule |
| Model file | backend/models/best_efficientnet_b0.pth (~17 MB) |
The trained model file is gitignored (large binary). To run the app, retrain using the notebooks on a GPU or obtain the weights from the project author.
| Metric | EfficientNet-B0 | ResNet50 (baseline) |
|---|---|---|
| Test Accuracy | 88.94% | 87.23% |
| Macro F1 | 0.8641 | 0.8278 |
| Cohen's Kappa | 0.8636 | 0.8422 |
| Top-3 Accuracy | 97.45% | 97.87% |
| PP F1 (worst class) | 0.6061 | 0.4286 |
Macro F1 is the primary metric — it weights all 6 classes equally and is more meaningful than accuracy on the imbalanced dataset. EfficientNet-B0 is deployed.
Note on PP: Polypropylene has the lowest F1 (0.606) due to limited training data (119 images, 6.5% of dataset). The API appends an extra verification reminder for PP predictions.
Upload a plastic image (jpg/png/webp, max 10 MB). Returns classification results, static plastic info, and disposal suggestions.
Request: multipart/form-data with field file
Response:
{
"prediction": {
"plastic_type": "PET",
"full_name": "Polyethylene Terephthalate",
"resin_code": 1,
"confidence": 0.94,
"is_uncertain": false,
"uncertainty_message": null,
"top3": [{"type": "PET", "confidence": 0.94}, ...],
"all_probabilities": {"PET": 0.94, "HDPE": 0.03, ...}
},
"info": {
"common_uses": [...],
"recyclability": "Widely recycled",
"recyclability_score": 5,
"health_concerns": "...",
"decomposition_years": 450,
"warning": null,
"fun_fact": "..."
},
"suggestions": {
"recycling_tips": [...],
"reuse_ideas": [...],
"eco_alternatives": [...],
"environmental_note": "...",
"source": "ai"
}
}suggestions.source is "ai" when Gemini responds successfully, "static" when the fallback is used.
Returns model load status, class count, and whether Gemini is enabled.
Returns the full static knowledge base for all 6 supported plastic types.
Full interactive API documentation: http://localhost:8000/docs
| Split | Images |
|---|---|
| Train | 1,834 (~80%) |
| Val | 226 (~10%) |
| Test | 235 (~10%) |
| Total | 2,295 |
- 6 classes: HDPE, LDPE, PET, PP, PS, PVC (the "Other" category was excluded — insufficient samples)
- Source: curated academic plastic classification dataset
- Split: stratified 80/10/10, seed=42
- Class imbalance handled via
WeightedRandomSamplerduring training
# backend/.env
GEMINI_API_KEY=your_key_here # Leave empty to use static suggestions only
All other settings (model path, confidence threshold, file size limit) are in backend/app/config.py.
- PP classification is limited — F1=0.606 due to only 119 training images. Verify PP items by checking the resin code (#5) on the packaging.
- Test set is small — 235 images total, 16 for PP. Metric estimates have moderate variance.
- Distribution gap — Model was trained on curated images. Real-world phone photos (varied lighting, dirty/crushed plastics, complex backgrounds) will likely reduce accuracy by 5–15%.
- No "Other"/"Mixed" class — Items that aren't clearly HDPE, LDPE, PET, PP, PS, or PVC will be misclassified as the closest match.
- No calibration testing — Softmax confidence scores are not calibrated; a 90% confidence prediction is not guaranteed to be correct 90% of the time.


