Spaces:
Sleeping
Sleeping
metadata
title: Crop vs No Crop Segmentation
emoji: πΎ
colorFrom: green
colorTo: yellow
sdk: docker
app_port: 8501
pinned: false
πΎ Crop vs No-Crop Segmentation
A production-ready Streamlit app that performs binary semantic segmentation with a fine-tuned NVIDIA SegFormer-B2 model, deployed on Hugging Face Spaces using the Docker SDK.
| Class | Meaning | Mask color |
|---|---|---|
| 0 | Background / No Crop | Dark gray |
| 1 | Crop | Bright yellow |
Inference is CPU-optimized, so it runs on free Hugging Face Spaces.
β¨ Features
- Upload
jpg/jpeg/pngimages. - One-click Run Segmentation with a progress spinner.
- Three-panel output: Original Β· Predicted Mask Β· Crop Overlay (semi-transparent magenta over crop regions), all at identical size.
- Download Result β exports all three panels combined horizontally as
prediction_result.png. - Model is loaded once via
@st.cache_resource. - Weights load from a local
best.ptor directly from the Hugging Face Hub. - Automatic GPU/CPU device selection; inference under
torch.no_grad(). - Friendly error handling for invalid/corrupted uploads, missing weights, and inference failures.
π§ How the model is built
The architecture is rebuilt from the nvidia/mit-b2 backbone config with
num_labels=2, and the fine-tuned weights are loaded on top:
MODEL_NAME = "nvidia/mit-b2"
config = SegformerConfig.from_pretrained(MODEL_NAME, num_labels=2)
model = SegformerForSemanticSegmentation(config)
model.load_state_dict(torch.load("best.pt", map_location="cpu"), strict=False)
The checkpoint is expected to be a plain state dict:
torch.save(model.state_dict(), "best.pt")
π Folder structure
crop-segmentation/
βββ app.py # Streamlit UI + workflow
βββ predictor.py # Model build (mit-b2) + best.pt loading + inference
βββ utils.py # Image loading, mask/overlay/combine, PNG export
βββ requirements.txt # Python dependencies
βββ Dockerfile # HF Spaces Docker build (Python 3.10, CPU torch)
βββ README.md # This file (with HF Spaces front matter)
βββ .gitignore
βββ .dockerignore
βββ best.pt # Fine-tuned weights (provide your own)
βββ assets/ # Screenshots / static assets
π» Local installation
git clone <your-repo-url>
cd crop-segmentation
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# CPU torch (optional but recommended for parity with deployment)
pip install torch==2.11.0 torchvision==0.26.0 \
--index-url https://download.pytorch.org/whl/cpu
pip install -r requirements.txt
# Make sure best.pt is present, or set HF_REPO_ID (see below)
streamlit run app.py
Open http://localhost:8501.
Loading weights
Two options, controlled by environment variables:
| Variable | Purpose |
|---|---|
| (none) | Use a local best.pt next to the app. |
HF_REPO_ID |
Download best.pt from this HF model repo, e.g. your-username/crop-segformer-b2. |
HF_TOKEN |
Token for a private weights repo (optional). |
INPUT_SIZE |
Square inference size (default 512). |
export HF_REPO_ID="your-username/crop-segformer-b2"
streamlit run app.py
π Hugging Face Spaces deployment (Docker SDK)
- Create a new Space β SDK: Docker.
- Push these files to the Space repository.
- Provide the weights using one of:
- Commit
best.ptto the Space (use Git LFS for large files):git lfs install git lfs track "*.pt" git add .gitattributes best.pt git commit -m "Add weights" git push - Load from a model repo β in the Space Settings β Variables, set
HF_REPO_ID(andHF_TOKENif private). Nobest.ptin the Space needed.
- Commit
- The
README.mdfront matter pinssdk: dockerandapp_port: 8501, so the Space serves the Streamlit app on port 8501 automatically.
The Space will build the Docker image, install dependencies (CPU torch), and launch:
streamlit run app.py --server.port=8501 --server.address=0.0.0.0
πΌοΈ Example screenshots
Replace these placeholders with real screenshots in
assets/.
| Upload | Results (3 panels) |
|---|---|
assets/screenshot_upload.png |
assets/screenshot_results.png |
βοΈ Notes & assumptions
- Preprocessing: convert to RGB β resize to
INPUT_SIZEβToTensorβ ImageNet normalization (mean=[0.485,0.456,0.406],std=[0.229,0.224,0.225]). If your fine-tuning used different stats or size, setINPUT_SIZEand adjustIMAGENET_MEAN/IMAGENET_STDinpredictor.pyto match. - Postprocessing: argmax over upsampled logits, resized back to the original image resolution.
- Weights are loaded with
strict=Falseso minor key mismatches log a warning rather than crash; verify the warnings are empty for a correct checkpoint.