Skip to content

Repository files navigation

title Capstone Backend
emoji πŸ“š
colorFrom gray
colorTo gray
sdk docker
pinned false

Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference

Tomato Plant Flower Classification API

A FastAPI backend for detecting and classifying tomato plant flowers by growth stage using ML.

Features

  • Image Classification: Upload images of tomato plants to detect flowers and classify their growth stage
  • Video Classification: Process entire videos frame-by-frame for comprehensive flower analysis ⭐ NEW
  • Annotated Media: Automatically generates and stores images/videos with bounding boxes and labels
  • GPS Extraction: Automatically extracts location from image EXIF metadata
  • Database Storage: Stores all classifications with annotated media for later retrieval (GridFS for large videos)
  • Heatmap Data: Returns all location and classification data for frontend heatmap visualization
  • Frame-by-Frame Analysis: Detailed statistics for each video frame with aggregated summaries

Software Architecture

The API follows a three-tier architecture deployed on the cloud. The presentation layer consists of RESTful endpoints built with FastAPI, handling HTTP requests and responses with automatic OpenAPI documentation. The business logic layer processes images by extracting GPS coordinates from EXIF metadata and running ML classification to detect and classify flowers by growth stage. The data layer uses MongoDB Atlas, a cloud-hosted NoSQL database that stores all classifications and images (as base64) persistently. The entire application is deployed on Render.com as a containerized service, making it scalable and accessible from anywhere. Images flow through the system: uploaded via API, processed for GPS and classification, then stored in MongoDB where they can be retrieved later for heatmap visualization or individual queries.

Flower Stages

Stage Name Description
0 Bud Early flower bud stage
1 Anthesis Active flowering stage
2 Post-Anthesis After flowering, fruit development

Quick Start

1. Install Dependencies

pip install -r requirements.txt

2. Configure Environment

The .env file is already configured with MongoDB credentials. If you need to update it, edit .env:

# .env file
MONGODB_URL=mongodb+srv://username:password@cluster.mongodb.net/flower_classifications
MONGODB_DATABASE=flower_classifications
PORT=8000

Note: The .env file is in .gitignore and won't be committed to git.

3. Run Tests

# Run all integration tests (recommended)
python test_integration.py

# Run specific tests
python test_integration.py --test model      # Test YOLO model only
python test_integration.py --test database   # Test MongoDB only
python test_integration.py --test e2e        # Test end-to-end flow
python test_integration.py --test api        # Test API endpoints (requires running server)

# Run original pytest suite
pytest tests/test_api.py -v

# Test video classification (NEW)
python test_video_api.py

# Test live deployed API
curl https://capstone-077z.onrender.com/

4. Start the Server

# The .env file is automatically loaded
uvicorn app.main:app --reload

The API will be available at http://localhost:8000

Note: MongoDB URL is loaded from .env file.

API Endpoints

Image Classification

POST /api/classify

Upload an image for flower classification.

Request:

  • file: Image file (JPEG, PNG, etc.)
  • latitude (optional): Manual GPS latitude
  • longitude (optional): Manual GPS longitude

Response:

{
  "id": "uuid",
  "image_path": "/api/images/uuid",
  "location": {
    "latitude": 37.7749,
    "longitude": -122.4194
  },
  "timestamp": "2025-12-03T10:30:00Z",
  "flowers": [
    {
      "bounding_box": [100, 150, 200, 250],
      "stage": 1,
      "confidence": 0.95
    }
  ],
  "flower_count": 5,
  "stage_summary": {"0": 2, "1": 2, "2": 1}
}

GET /api/heatmap-data

Get all classification data for heatmap visualization.

Response:

{
  "total_records": 10,
  "data_points": [
    {
      "id": "uuid",
      "latitude": 37.7749,
      "longitude": -122.4194,
      "timestamp": "2025-12-03T10:30:00Z",
      "flowers": [...],
      "total_flowers": 5,
      "stage_counts": {"0": 2, "1": 2, "2": 1}
    }
  ]
}

GET /api/classifications/{id}

Get a specific classification by ID.

GET /api/images/{id}

Get the annotated image for a classification.

Response: JPEG image with:

  • Bounding boxes around each detected flower
  • Stage labels (Bud, Anthesis, Post-Anthesis)
  • Confidence scores

Note: Only annotated images are stored to save database space.

DELETE /api/classifications/{id}

Delete a classification and its image.

Video Classification ⭐ NEW

POST /api/classify-video

Upload a video for frame-by-frame flower classification.

Request:

  • file: Video file (MP4, AVI, MOV, etc.)
  • latitude (optional): Manual GPS latitude
  • longitude (optional): Manual GPS longitude
  • include_frame_details (optional): Include per-frame statistics (default: false)

Response:

{
  "id": "uuid",
  "video_path": "/api/videos/uuid",
  "location": {"latitude": 37.7749, "longitude": -122.4194},
  "timestamp": "2025-12-08T10:30:00Z",
  "total_frames": 300,
  "fps": 30.0,
  "duration_seconds": 10.0,
  "total_detections": 450,
  "average_flowers_per_frame": 1.5,
  "stage_summary": {"0": 150, "1": 200, "2": 100},
  "frame_statistics": null
}

GET /api/videos/{id}

Download the annotated video with bounding boxes and labels on each frame.

GET /api/video-classifications/{id}

Get video classification metadata and statistics.

GET /api/video-classifications

List all video classifications.

DELETE /api/video-classifications/{id}

Delete a video classification and its associated video.

πŸ“– For detailed video API documentation, see VIDEO_API_GUIDE.md

πŸ§ͺ Test video endpoints with: python test_video_api.py

API Documentation

Live API: https://capstone-077z.onrender.com

For local development:

Quick Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    External Clients                          β”‚
β”‚  (Frontend, API Clients, Browser)                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚ HTTP/REST
                           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Hugging Space (FastAPI Application)            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  API Routes:                                         β”‚   β”‚
β”‚  β”‚  - POST /api/classify (Images)                      β”‚   β”‚
β”‚  β”‚  - POST /api/classify-video (Videos - Sync)         β”‚   β”‚
β”‚  β”‚  - POST /api/classify-video-async (Videos - Async)  β”‚   β”‚
β”‚  β”‚  - GET /api/heatmap-data                            β”‚   β”‚
β”‚  β”‚  - GET /api/classifications/{id}                     β”‚   β”‚
β”‚  β”‚  - GET /api/images/{id}                             β”‚   β”‚
β”‚  β”‚  - GET /api/videos/{id}                              β”‚   β”‚
β”‚  β”‚  - GET /api/jobs/{id} (Job Status)                  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Services:                                           β”‚   β”‚
β”‚  β”‚  - ML Model (YOLOv8 - Images & Videos)              β”‚   β”‚
β”‚  β”‚  - Image/Video Processing (EXIF GPS, Annotation)     β”‚   β”‚
β”‚  β”‚  - ProcessPoolExecutor (Async Video Workers)         β”‚   β”‚
β”‚  β”‚  - MongoDB Client (Motor + GridFS)                  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚ MongoDB Connection
                           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              MongoDB Atlas (Cloud Database)                  β”‚
β”‚  - Stores image classifications (base64)                    β”‚
β”‚  - Stores video classifications (GridFS)                    β”‚
β”‚  - Stores job tracking records                               β”‚
β”‚  - Persistent storage                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

capstone/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ main.py              # FastAPI application and routes (images + videos)
β”‚   β”œβ”€β”€ database_mongodb.py  # MongoDB + GridFS setup
β”‚   β”œβ”€β”€ config.py            # Environment variable configuration
β”‚   β”œβ”€β”€ models.py            # Pydantic request/response models
β”‚   β”œβ”€β”€ ml_model.py          # YOLO model integration (images + videos)
β”‚   └── utils.py             # EXIF GPS extraction utilities
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── test_api.py          # Pytest test suite
β”œβ”€β”€ ml_model.pt              # YOLOv8 trained model
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ Dockerfile               # Docker configuration for Render
β”œβ”€β”€ test_integration.py      # Integration tests
β”œβ”€β”€ test_video_api.py        # Video API test suite (NEW)
β”œβ”€β”€ VIDEO_API_GUIDE.md       # Video classification documentation (NEW)
└── README.md

ML Model Integration

The app/ml_model.py file implements YOLOv8 from Ultralytics for flower detection and classification. The model is automatically downloaded from Hugging Face Hub to ensure you always have the latest version.

Model Interface

def classify_image(image_bytes: bytes, confidence_threshold: float = 0.25) -> List[Dict]:
    """
    Returns list of detections:
    [
        {
            "bounding_box": [x_min, y_min, x_max, y_max],
            "stage": 0|1|2,
            "confidence": 0.0-1.0
        }
    ]
    """

Features

  • Hugging Face Integration: Automatically downloads latest model from deenp03/tomato_pollination_stage_classifier
  • Model Caching: Model is loaded once and cached for subsequent requests
  • Automatic Updates: Always uses the latest model version from Hugging Face
  • Fallback Support: Falls back to local model if Hugging Face is unavailable
  • Confidence Threshold: Adjustable threshold for filtering detections (default: 0.25)
  • Automatic RGB Conversion: Handles various image formats (RGBA, grayscale, etc.)
  • GPU Support: Automatically uses GPU if available, falls back to CPU

Testing the Model

Run the integration test to verify the model downloads and works:

# Test all components including Hugging Face download
python test_integration.py

# Or test just the model
python test_integration.py --test model

The first run will download the model from Hugging Face (~50MB, takes 5-10 seconds). Subsequent runs use the cached model and are much faster.

Database

Uses MongoDB Atlas for persistent cloud storage. Images are stored as base64 in MongoDB documents.

Setting Up MongoDB Atlas

  1. Go to https://www.mongodb.com/cloud/atlas/register
  2. Create a free cluster (M0 tier, 512MB storage)
  3. Create a database user and get your connection string
  4. Configure network access to allow connections
  5. Set environment variable with your connection string

Local Development

Set the MongoDB connection string as an environment variable:

export MONGODB_URL="mongodb+srv://username:password@cluster.mongodb.net/flower_classifications"

Then start the server:

uvicorn app.main:app --reload

Deployment

This API is deployed on Render.com with MongoDB Atlas for persistent storage.

Live Deployment

API URL: https://capstone-077z.onrender.com

The API is fully deployed and operational. All data is stored in MongoDB Atlas.

Deploying Your Own Instance

  1. Set up MongoDB Atlas:

  2. Deploy to Render.com:

    • Push code to GitHub
    • Create new Web Service on Render
    • Set MONGODB_URL environment variable with your connection string
    • Deploy!
    • Everytime your GitHub repo is updated, Render will redeploy

Architecture

  • Frontend: Can be deployed on Vercel or any static hosting
  • Backend API: Deployed on Render.com (this repository)
  • Database: MongoDB Atlas (cloud-hosted MongoDB)
  • Storage: Images stored as base64 in MongoDB documents

Environment Variables

# Required - MongoDB connection string
MONGODB_URL=mongodb+srv://username:password@cluster.mongodb.net/flower_classifications?appName=FreeTier

# Optional
MONGODB_DATABASE=flower_classifications  # Defaults to this if not specified
PORT=8000  # Server port (auto-set by Render, uses $PORT)
CORS_ORIGINS=*  # Allowed frontend origins (comma-separated, * for all)

Setting Environment Variables on Render

  1. Go to Render dashboard β†’ Your service
  2. Click "Environment" tab
  3. Add MONGODB_URL with your connection string
  4. Add any other variables as needed
  5. Service will auto-redeploy

About

API for Vision Model which Determines Plant Pollination State

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages