Spaces:
Sleeping
Sleeping
| 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` / `png` images. | |
| - 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.pt`** or 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: | |
| ```python | |
| 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: | |
| ```python | |
| 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 | |
| ```bash | |
| 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`). | | |
| ```bash | |
| export HF_REPO_ID="your-username/crop-segformer-b2" | |
| streamlit run app.py | |
| ``` | |
| --- | |
| ## π Hugging Face Spaces deployment (Docker SDK) | |
| 1. Create a new Space β **SDK: Docker**. | |
| 2. Push these files to the Space repository. | |
| 3. Provide the weights using **one** of: | |
| - **Commit `best.pt` to the Space** (use Git LFS for large files): | |
| ```bash | |
| 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` (and `HF_TOKEN` if private). No `best.pt` in the Space needed. | |
| 4. The `README.md` front matter pins `sdk: docker` and `app_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: | |
| ```bash | |
| 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, set `INPUT_SIZE` and adjust | |
| `IMAGENET_MEAN`/`IMAGENET_STD` in `predictor.py` to match. | |
| - Postprocessing: argmax over upsampled logits, resized back to the original | |
| image resolution. | |
| - Weights are loaded with `strict=False` so minor key mismatches log a warning | |
| rather than crash; verify the warnings are empty for a correct checkpoint. | |