Project Info
Inspiration
Food waste is a huge problem. College campuses in the United States generate an estimated 22 million pounds of food waste annually. Every day in dining halls, students take food they don't end up eating, and most schools have very little visibility into what those leftovers actually are. They might know how much food they purchased or how much waste was thrown away overall, but they usually don't know which specific foods students consistently leave on their plates.
What it does
Foodprint is an AI-powered dining hall waste-tracking system that analyzes leftover food on student plates. A Raspberry Pi camera monitors plates, Overshoot detects when a full plate is present, and Gemini analyzes captured images to identify leftover foods. The system combines this data with scraped dining hall menus using Browserbase and stores the results in a database. Staff can then view waste trends, meal-specific waste patterns, recent plate events, and actionable insights through a dashboard, helping them understand what foods are being wasted most frequently.
How we built it
We built Foodprint using a Raspberry Pi camera stream, Python, FastAPI, SQLite, and OpenCV. Overshoot handles full-plate detection, while Gemini generates detailed leftover descriptions from captured images. Browserbase and Stagehand automatically scrape dining hall menus and store them as structured data. The backend aggregates waste events and serves analytics through a FastAPI dashboard, allowing dining hall staff to explore trends and menu-specific waste patterns.
Challenges we ran into
One of our biggest challenges was how classifying against the entire Berkeley Dining menu was far too broad a problem, which pushed us to scope classification down to one dining hall and meal period at a time. Scraping the menu data itself was its own challenge, since the site is JS-rendered and filter-based, requiring Browserbase and Stagehand instead of a simple static scrape.
Accomplishments we're proud of
We're proud that we built a working end-to-end pipeline in a short timeframe, taking a live Pi camera feed all the way through AI-based food classification to a working dashboard. We solved the dynamic menu problem by using Browserbase to automatically scrape Berkeley Dining's daily menus, and we designed two physical deployment options, a conveyor belt mount and a trash can mount, so the system could realistically fit different dining hall layouts.
What we learned
Working on Foodprint taught us a lot about the gap between planning hardware on paper and actually wiring it up, since things like camera mounting and color format only became obvious once we had real components in hand. We also learned that scoping a problem well matters as much as the model you choose, which is why we narrowed classification down to one dining hall and meal period at a time.
What's next
Our next goal is to move beyond generic leftover descriptions and improve menu-item-level identification accuracy. We also would love to bring this to life and expand it to dining halls across the world so that we can help universities reduce food waste at scale by turning everyday dining hall activity into actionable sustainability insights.
foodprint
foodprint is a dining hall waste-tracking system for plate-level feedback.
It combines:
- a Raspberry Pi camera stream
- Overshoot for full-plate detection
- Gemini for leftover description
- Browserbase for daily menu scraping
- a FastAPI dashboard for dining hall staff
The goal is to show what students are actually leaving on their plates, meal by meal, so dining teams can make better decisions about portions, menus, and purchasing.
What It Does
foodprint has four main parts:
-
camera_server.pyRuns on the Raspberry Pi and exposes the camera as an MJPEG stream at/video. -
watch_pi_camera.pyRuns on a Mac or laptop, watches the Pi stream, uses Overshoot to decide when a full plate is in view, captures an image, sends the image to Gemini for leftover analysis, and stores the result infoodprint.db. -
browserbase_crossroads_menu_agent.mjsUses Browserbase + Stagehand to scrape Berkeley Dining menus into JSON files inmenus/. -
dining_waste_tracker_gemini.py+staff_dashboard.htmlServes the staff dashboard and APIs for menu logs, waste trends, recent plate events, and waste by meal.
Architecture
Raspberry Pi Camera
-> Flask MJPEG stream
-> watch_pi_camera.py
-> Overshoot: plate present / no plate
-> Gemini: leftover description from image
-> SQLite: foodprint.db
-> FastAPI dashboard
-> staff_dashboard.html
-> dining hall analytics
Browserbase
-> scrape Berkeley Dining menus
-> menus/*.json
-> dashboard menu log import
Repository Layout
- camera_server.py
- watch_pi_camera.py
- dining_waste_tracker_gemini.py
- staff_dashboard.html
- browserbase_crossroads_menu_agent.mjs
- requirements.txt
- package.json
menus/captures/foodprint.db
Requirements
Python
Install:
python3 -m pip install -r requirements.txt
Key Python dependencies:
fastapiuvicornopencv-pythongoogle-generativeairequestslivekit
Node
Install:
npm install
Key Node dependencies:
@browserbasehq/stagehandzod
Environment Variables
Set the API keys you need before running the watcher or scraper:
export OVERSHOOT_API_KEY="your_overshoot_key"
export GEMINI_API_KEY="your_gemini_key"
export BROWSERBASE_API_KEY="your_browserbase_key"
Optional:
export GEMINI_MODEL="gemini-1.5-flash"
export DINING_HALL="Crossroads"
export FOODPRINT_DB_PATH="foodprint.db"
export BROWSERBASE_MODEL="google/gemini-2.5-flash"
1. Run the Pi Camera Server
Run this on the Raspberry Pi:
pip3 install flask picamera2 opencv-python
python3 camera_server.py
The stream should be available at:
http://raspberrypi.local:8080/video
If colors look wrong, try setting:
PI_COLOR_MODE=raw python3 camera_server.py
Valid values:
rawrgb_to_bgrbgr_to_rgb
2. Scrape the Dining Menu
Scrape Crossroads:
npm run scrape:crossroads-menu
Scrape all supported halls:
npm run scrape:all-menus
Output is written to menus/*.json.
3. Run the Plate Watcher
Run this on your laptop or Mac:
python3 watch_pi_camera.py \
--url http://raspberrypi.local:8080/video \
--dining-hall Crossroads \
--db-path foodprint.db \
--show-window
What it does:
- waits until a full plate is clearly in frame
- uses Overshoot only for plate detection
- captures an image into
captures/ - sends the image to Gemini for leftover analysis
- normalizes leftovers into tracked items such as
Banana,Bread, orYogurt - stores the event in
foodprint.db
4. Run the Dashboard
Start the backend:
python3 dining_waste_tracker_gemini.py
Open the dashboard:
http://localhost:8000/staff
The dashboard includes:
- daily menu log
- waste by meal
- daily trend graph
- dining hall menu waste
- recent plate events with thumbnails
- insights
Current Detection Behavior
The watcher is intentionally conservative:
- Overshoot only answers: is a real full plate present?
- Gemini describes leftovers from the captured image
- menu matching is not forced
- if the exact dish is unclear, generic leftovers are preserved
Examples:
banana slices->Bananabread with spread->Breadwhite creamy substance-> oftenYogurtor another generic dairy-style label if that is all that is visually supported
This is deliberate. It is better to keep a generic truthful label than invent the wrong menu item.
Data Storage
Captured events are stored in SQLite at foodprint.db.
Main tables:
plate_eventsleftover_items
Captured images and metadata sidecars are stored in:
captures/*.jpgcaptures/*.json
Dashboard Data Rules
Daily Menu Logstays based on scraped or manual menu items.Dining Hall Menu Wasteswitches to real DB-backed waste data as soon as at least one real plate event exists for the selected hall and window.- The dashboard will stop showing test placeholder waste rows once real captured data exists.
Common Commands
Run watcher:
python3 watch_pi_camera.py --url http://raspberrypi.local:8080/video --dining-hall Crossroads --db-path foodprint.db --show-window
Run dashboard:
python3 dining_waste_tracker_gemini.py
Scrape menus:
npm run scrape:all-menus
Clear the database:
sqlite3 foodprint.db "DELETE FROM leftover_items; DELETE FROM plate_events;"
Notes
- The Pi camera stream must be stable before the watcher starts.
- If
watch_pi_camera.pytimes out waiting for frames, confirmhttp://raspberrypi.local:8080/videoworks in a browser first. - If Overshoot fails to connect, the issue is usually network or WebRTC connectivity, not the Pi stream.
- If
GEMINI_API_KEYis missing, the watcher falls back to the generic Overshoot leftover prompt.
Related Docs
Analysis
View
Metric
- 4
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- FastAPIIn code
- HTMLIn code
- PythonIn code
- Google GeminiClaimed
3 of 4 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
No AI coding agent signals were found in this repository.
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
156 KB
Source files
9
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
anishka-v/food-print
14 files · 264 KB · @ d59f12f
Structure
Interface
1 file · 7%Screens, components and styles rendered to the user.
Application logic
5 files · 36%Domain rules, services and shared utilities.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python76%
- HTML17%
- Markdown7%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
requirements.txt
pypi · 10- fastapi
- google-generativeai
- livekit
- numpy
- opencv-python
- Pillow
- python-dotenv
- python-multipart
- requests
- uvicorn
package.json
npm · 2- @browserbasehq/stagehand
- zod
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.