{"id":20961534,"url":"https://github.com/pseusys/hogweedgo","last_synced_at":"2026-07-16T20:31:42.038Z","repository":{"id":37830325,"uuid":"404533897","full_name":"pseusys/HogWeedGo","owner":"pseusys","description":null,"archived":false,"fork":false,"pushed_at":"2023-02-27T23:37:04.000Z","size":50820,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-04T21:10:49.057Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://pseusys.github.io/HogWeedGo/","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pseusys.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-09T00:20:24.000Z","updated_at":"2024-04-28T19:44:49.000Z","dependencies_parsed_at":"2025-01-20T00:45:00.586Z","dependency_job_id":"d86ca605-6c56-499c-b004-3dd53f209451","html_url":"https://github.com/pseusys/HogWeedGo","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/pseusys/HogWeedGo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseusys%2FHogWeedGo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseusys%2FHogWeedGo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseusys%2FHogWeedGo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseusys%2FHogWeedGo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pseusys","download_url":"https://codeload.github.com/pseusys/HogWeedGo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseusys%2FHogWeedGo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279087282,"owners_count":26100357,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T02:14:10.886Z","updated_at":"2026-07-16T20:31:42.023Z","avatar_url":"https://github.com/pseusys.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HogWeedGo\n\n[![SERVER](https://github.com/pseusys/HogWeedGo/actions/workflows/server.yml/badge.svg)](https://github.com/pseusys/HogWeedGo/actions/workflows/server.yml)\n[![CLIENT](https://github.com/pseusys/HogWeedGo/actions/workflows/client.yml/badge.svg)](https://github.com/pseusys/HogWeedGo/actions/workflows/client.yml)\n[![ML-HELPER](https://github.com/pseusys/HogWeedGo/actions/workflows/ml-helper.yml/badge.svg)](https://github.com/pseusys/HogWeedGo/actions/workflows/ml-helper.yml)\n[![REPORT](https://github.com/pseusys/HogWeedGo/actions/workflows/report.yml/badge.svg)](https://github.com/pseusys/HogWeedGo/actions/workflows/report.yml)\n\nA crowd-sourced monitoring system for *Heracleum sosnowskyi* (Sosnowsky's hogweed) — an invasive, phototoxic plant species spreading across northern Europe. Built as a bachelor's thesis project; **presented at the ETU MOEVM Scientific and Technical Seminar (2022)** and published in the proceedings (pp. 12–15). Full thesis report available as a [thesis report PDF](https://github.com/pseusys/HogWeedGo/releases/download/v0.0.1-report/report.pdf).\n\nThe system integrates a **geospatial REST backend**, a **cross-platform mobile client**, and an **on-device ML classifier**, forming a complete pipeline from field observation to expert review.\n\n---\n\n## Architecture\n\n```text\n┌───────────────────────────────────────────────────────────┐\n│                        HogWeedGo                          │\n│                                                           │\n│   ┌──────────────┐     REST/JSON      ┌───────────────┐   │\n│   │  Flutter     │ ◄────────────────► │ Django +      │   │\n│   │  Mobile App  │                    │ PostGIS       │   │\n│   │  (iOS/Android│                    │ Server        │   │\n│   │  + TFLite    │                    │               │   │\n│   │  classifier) │                    │ PostgreSQL DB │   │\n│   └──────────────┘                    └───────────────┘   │\n│                                                           │\n│   ┌──────────────────────────────────────────────────┐    │\n│   │  ML Helper (Jupyter)                             │    │\n│   │  MobileNetV2 transfer learning → .tflite export  │    │\n│   └──────────────────────────────────────────────────┘    │\n└───────────────────────────────────────────────────────────┘\n```\n\nThere are two classes of users: **volunteers** (field observers, drones, etc.) who submit geo-tagged photo reports, and **experts** (ecologists, administrators) who review, annotate, and manage reports through a web interface. The mobile client also runs an on-device classifier to guide the user before submission.\n\n---\n\n## Components\n\n### Server — `server/`\n\n**Stack:** Python 3, Django, Django REST Framework, PostGIS, Docker, Nginx\n\nThe server exposes a documented REST API ([OpenAPI 3.0 spec](./HogWeedGo.openapi.yml)) covering:\n\n- **Authentication** — email-verified registration with time-limited OTP codes; token-based session auth with rate limiting\n- **Reports** — geo-tagged submissions with multi-photo upload, status lifecycle (`RECEIVED` → `APPROVED` / `INVALID`), and comment threads\n- **Geospatial storage** — geographic `PointField` (PostGIS) with address annotation\n- **Expert web interface** — custom Django Admin with report management, user administration, and statistics\n- **Backup/restore** — serialization modes supporting full database export and import, including media files (base64-encoded)\n\nProduction deployment uses Nginx + Gunicorn behind TLS, with auto-generated self-signed certificates and a config generation script. A Docker image is published automatically to GHCR on every push to `main`.\n\n![Web interface — reports list](report/images/reports-page-real.png)\n![Web interface — report detail](report/images/report-page-real.png)\n\n### Client — `client/`\n\n**Stack:** Dart, Flutter (iOS + Android)\n\nThe mobile client provides:\n\n- Interactive map displaying all submitted reports\n- Geo-tagged photo report submission with on-device ML pre-classification\n- User account management (profile photo, password, email change with OTP)\n- Real-time report status tracking\n\n![Main map view](report/images/main-screen-real.png)\n![Report submission](report/images/report-screen-real.png)\n![User account](report/images/account-screen-real.png)\n\n### ML Helper — `ml-helper/`\n\n**Stack:** Python, TensorFlow/Keras, Jupyter, scikit-learn\n\nA Jupyter notebook pipeline for training and exporting the on-device plant classifier. See the [ML Helper README](./ml-helper/README.md) for full details.\n\n**Model:** MobileNetV2 (ImageNet pretrained) with two-phase transfer learning  \n**Dataset:** 21,300 images across 3 classes, sourced from iNaturalist and OpenImages  \n**Accuracy:** \u003e92% on held-out test set  \n**Output:** `.tflite` model for direct embedding in the Flutter client  \n\n![Head training — frozen base](report/images/head-training.png)\n![Fine-tuning — top 80% unfrozen](report/images/full-training.png)\n\n---\n\n## CI/CD\n\nFour independent GitHub Actions workflows provide full automation:\n\n- **`server.yml`** — (1) runs unit tests against a live PostgreSQL+PostGIS instance; (2) builds the full Docker stack and runs the Postman API test suite via Newman; (3) publishes the Docker image to GHCR; (4) updates the bundled release artifact\n- **`client.yml`** — builds the Flutter Android APK\n- **`ml-helper.yml`** — fetches the released `.tflite` model and runs the classifier test suite against the held-out CSV dataset\n- **`report.yml`** — compiles the LaTeX thesis report and publishes it as a release asset\n\n---\n\n## Getting Started\n\n### Run the server locally (Docker)\n\n1. Download `bundled-server.zip` from the [releases page](https://github.com/pseusys/HogWeedGo/releases), unpack it, and open a shell there.\n2. Run `./config-generator.sh [YOUR_DOMAIN]` to generate environment configs.\n3. Run `docker-compose -f ./docker-compose.yml --env-file=./system-config.env up`.\n\nSee [server/README.md](./server/README.md) for full configuration reference (ports, SMTP mocking, HTTPS certificates, superuser credentials).\n\n### Build the server from source\n\n```bash\ncd server\n./config-generator.sh localhost\n# Install dependencies and initialize the database:\n./init-local.sh ./config.env server\n# Run the test suite:\n./init-local.sh ./config.env test\n```\n\n### Build the mobile client\n\n```bash\ncd client\nflutter pub get\nflutter build apk   # Android\nflutter build ios   # iOS\n```\n\n### Train the ML model\n\nSee [ml-helper/README.md](./ml-helper/README.md).\n\n---\n\n## Repository Structure\n\n```text\nHogWeedGo/\n├── server/          # Django backend (API, admin interface, PostGIS models)\n├── client/          # Flutter mobile client (iOS + Android)\n├── ml-helper/       # Jupyter training pipeline + TFLite export\n├── report/          # LaTeX bachelor's thesis source\n└── HogWeedGo.openapi.yml  # OpenAPI 3.0 API specification\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpseusys%2Fhogweedgo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpseusys%2Fhogweedgo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpseusys%2Fhogweedgo/lists"}