Skip to content

About

FastAPI backend with a ResNet50 (PyTorch) model that recognizes 62 wild plant species from a photo. PostgreSQL, SQLAlchemy and Alembic.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

Planter API

Backend for the Planter mobile app. A FastAPI application that accepts a photo, recognizes the wild plant species with a ResNet50 model (PyTorch) and returns its description from a PostgreSQL database. The model recognizes 62 species.

How it works

photo ──▶ POST /api/v1/recognize-plant/
              │
              ▼
   recognize/plant_recognition.py
   ResNet50 (224x224, 62 classes) ──▶ class index (0-61)
              │
              ▼
   `plants` table (id = index + 1)
              │
              ▼
         JSON response

Tech stack

  • FastAPI, Uvicorn
  • PyTorch / torchvision: ResNet50 with a replaced fc layer (62 classes)
  • PostgreSQL, SQLAlchemy 2, Alembic
  • pydantic-settings: configuration from a .env file
  • pandas, h5py, xlrd: loading training data

Project structure

planter-api/
├── main.py                      # FastAPI app and endpoints
├── database.py                  # SQLAlchemy engine and session
├── core/config.py               # settings (.env)
├── models/plant.py              # Plant model (plants table)
├── recognize/
│   ├── plant_recognition.py     # inference and index -> plant name map
│   └── train_model_one.py       # model training
├── database/
│   ├── migrations/              # Alembic migrations
│   └── seeders/plant_seeder.py  # data for 62 plants (PL/EN)
├── scripts/
│   ├── clear_database.py        # deletes all plants
│   └── inspect_hdf5_file.py     # inspects an .hdf5 weights file
├── tests/test_plant.py
├── alembic.ini
└── requirements.txt

Requirements

  • Python 3.10+
  • PostgreSQL
  • Model weights at result/plant_recognition_model_one.pth (not included in the repository, see Model)

Installation

git clone https://github.com/maszjan/planter-api.git
cd planter-api

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r requirements.txt

1. Configuration

Create a .env file in the project root (all fields are required):

APP_NAME=Planter API
ADMIN_EMAIL=admin@example.com
ITEMS_PER_USER=50
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_password
DB_NAME=planter

2. Database

createdb planter

# run migrations
alembic upgrade head

# fill the plants table (62 species)
python database/seeders/plant_seeder.py

3. Model weights

Place the trained weights in result/plant_recognition_model_one.pth. The path is relative to the directory from which you start the server.

4. Run the server

uvicorn main:app --host 0.0.0.0 --port 8000 --reload

Endpoints

GET /

{ "message": "Hello World" }

POST /api/v1/recognize-plant/

multipart/form-data with a file field (the photo).

curl -X POST http://localhost:8000/api/v1/recognize-plant/ \
  -F "file=@photo.jpg"

Response:

{
  "id": 18,
  "name": "Mniszek lekarski",
  "eng_name": "Dandelion",
  "scientific_name": "Taraxacum",
  "description": "...",
  "eng_description": "...",
  "image_url": null
}

Errors are returned as JSON with HTTP status 200:

Response Cause
{"error": "Plant recognition failed"} the model returned no result
{"error": "Plant not found"} no plant with the given id in the database
{"error": "Internal server error"} unexpected exception (details in the log)

Data model

The plants table: id, name (Polish), eng_name, scientific_name, description (Polish), eng_description, image_url (optional, currently empty).

The record for a class n returned by the model is looked up by id = n + 1. The order in plant_seeder.py must therefore match the index_to_name map in recognize/plant_recognition.py, and the table must be filled starting from id = 1.

Model

  • Architecture: ResNet50, 62 output classes, 224x224 input with ImageNet normalization.
  • Training: recognize/train_model_one.py (SGD, learning rate 0.001, 25 epochs, a checkpoint after every batch). It needs a local dataset in datasets/wild_plants/ (metadata.xls, .hdf5 weights, dataset/ and dataset-test/ directories), which is not part of the repository.
  • The script saves its output to models/plant_recognition_model_one.pth, while the API loads result/plant_recognition_model_one.pth, so copy the file after training.
python recognize/train_model_one.py

Logging

Logs are written to app.log in the directory where the server is started.

Tests

pip install pytest httpx
pytest

The current tests in tests/test_plant.py are outdated: they expect the response {"message": "Plant recognized"} and an endpoint /api/v1/detect-plant-disease/ that does not exist. They also require the model weights and a database.

Known limitations and ideas

  • The model always returns the most likely class. There is no confidence threshold or "not recognized" answer, so a photo of something that is not a plant still gets a result.
  • Errors are returned with status 200; HTTPException (404, 422, 500) would be cleaner.
  • There is no file type validation. Images with an alpha channel (for example PNG) may fail because .convert("RGB") is missing before inference.
  • Mapping a class to a record through id + 1 is fragile: clear_database.py does not reset the PostgreSQL sequence, so ids shift after re-seeding. Storing the class index in a separate column would be safer.
  • requirements.txt lists tensorflow and scikit-learn, which the code does not use, and lacks pytest and httpx.
  • The default sqlalchemy.url in alembic.ini contains credentials. It is overridden by .env, but it is better removed.
  • A Dockerfile and docker-compose.yml (API and PostgreSQL) would simplify deployment.
  • Predictions can be wrong, and the descriptions mention edibility, so results should not be treated as authoritative.

Related repositories

  • planter: the mobile app (Expo / React Native)

About

FastAPI backend with a ResNet50 (PyTorch) model that recognizes 62 wild plant species from a photo. PostgreSQL, SQLAlchemy and Alembic.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages