Problem Statement

Avocados continue to ripen after harvest, making it difficult for consumers to determine their exact ripeness from appearance alone. People often rely on subjective methods such as gently squeezing the fruit, but this judgment varies depending on individual experience. As a result, avocados are often eaten too early or left until they become overripe and are discarded.

D-avocado addresses this problem by providing a consistent, AI-based way to determine avocado ripeness and estimate when it will reach the user's preferred eating stage.

Solution Overview

D-avocado is an AI-powered mobile application that analyzes a photo of an avocado to classify its visual ripeness into five stages (1–5) and predict the number of days remaining until the user's preferred ripeness stage.

The system combines AI-based ripeness classification with temperature-aware D-day prediction. Users can set their preferred ripeness stage once, scan avocados without repeatedly entering their preferences, view previous scan results, and receive notifications before the target ripeness is reached.

Key Features

  • Ripeness Classification — Classifies an avocado into five ripeness stages from a single photo and provides per-stage prediction probabilities.
  • D-day Prediction — Predicts how many days remain until the avocado reaches the user's preferred ripeness stage.
  • Temperature-aware Prediction — Adjusts D-day estimation according to storage temperature.
  • Personalized Preferences — Allows users to set their preferred ripeness stage and notification preferences.
  • Push Notifications — Notifies users when an avocado is approaching its target ripeness.
  • Scan History — Stores previous scan results and allows users to review their avocado ripening history.

Technologies Used

  • iOS: Swift, SwiftUI, Xcode
  • Backend: Java 21, Spring Boot 3.4.2
  • AI Service: Python, FastAPI, PyTorch
  • AI Models: ResNet-18, Google Cloud Vertex AI AutoML
  • Database: PostgreSQL, Google Cloud SQL
  • Image Storage: Google Cloud Storage
  • Infrastructure: Google Cloud Run, Artifact Registry
  • Image Preprocessing: SAM-based background segmentation
  • Authentication: JWT
  • Push Notifications: FCM/APNs

Target Users

D-avocado is designed for consumers who regularly purchase avocados and have difficulty determining when they are ready to eat.

The primary target user is someone who buys several avocados at once and wants to know whether they will be ready for a specific meal or occasion. The service is particularly useful for users who want a more objective alternative to manually checking avocado firmness and who want advance notification before their preferred ripeness window arrives.


🥑 Inspiration

Everyone who cooks knows the avocado gamble: you buy one, forget it, and by the time you cut it open it's either rock-hard or brown mush. The ripe window is only a day or two, and it's almost impossible to judge from the outside. We wanted to turn that guesswork into a number — take one photo, and know not just how ripe your avocado is, but exactly how many days until it's perfect for you.

What it does

You photograph an avocado. An AI model classifies its ripening stage on a 1–5 scale and — factoring in your room temperature and the ripeness you prefer — predicts a D-day: the number of days until it reaches your target. Every scan is saved to a history, and the app sends a push notification before the peak day so you actually eat it in time.

How we built it

We split the system by responsibility across three pieces:

  • iOS app (Swift / Xcode) — camera, results, history, settings.
  • Spring Boot backend (Cloud Run) — auth, user settings, scan persistence, image storage, notifications. It owns everything except the intelligence.
  • AI service (FastAPI on Cloud Run) — background-removal crop → ripeness classification → D-day math.

A hard rule shaped the whole design: Spring never computes ripeness or D-day. It stores exactly what the AI returns. This meant we could re-fit our formula, swap the model, or change the segmenter without touching the backend a single line.

The D-day comes from a temperature-dependent coefficient. We fit a $Q_{10}$ (rate-doubling-per-10°C) curve between two measured anchors:

$$|\beta(T)| = |\beta_{20}| \cdot Q_{10}^{\frac{20 - T}{10}}, \quad |\beta_{10}| = 4.003,\ |\beta_{20}| = 1.750,\ Q_{10} = \frac{4.003}{1.750} \approx 2.287$$

and the remaining days are simply

$$\text{days_to_target} = |\beta(T)| \cdot (\text{target_stage} - \text{predicted_stage})$$

Negative values are kept, not clipped — a negative D-day means the avocado is already overripe, which the app needs to warn about.

Infrastructure is all Google Cloud: Cloud Run (both services, scale-to-zero), Cloud SQL (PostgreSQL), Cloud Storage (private bucket, TTL-signed image URLs), Artifact Registry for containers, and Vertex AI AutoML for the final classifier.

Challenges we ran into

  • Train–Inference Mismatch. Our classifier was trained on clean lightbox photos, so on real phone pictures it collapsed to "stage 1, confidence ≈ 1.0." We fixed it with inference-time preprocessing: at inference we run SAM-based segmentation to cut the avocado out of its cluttered background before classifying, shrinking the distribution gap between training and real-world data. We also moved the classifier to a Vertex AI AutoML model, behind an env flag so reverting is a one-line change.

  • Cloud Run signed URLs. Locally, signing image URLs worked; in production it threw 403 signBlob denied. On Cloud Run there's no local private key, so signing must go through the IAM API — which needs roles/iam.serviceAccountTokenCreator. It only surfaced after we enabled cropping, because until then the signed field was always null.

  • Latency vs. quality. High-quality segmentation costs ~50–100s per scan and OOM-crashed at 4 GB until we moved to 8 GB / 2 vCPU — a real trade-off we're still tuning.

  • ML pitfalls: splitting by individual fruit (not by image) to avoid leakage, and handling right-censored samples that never reached overripe when deriving ground-truth days.

What we learned

Clean responsibility boundaries paid for themselves over and over — because β and D-day lived only in the AI service, we changed the formula and the entire model without a single backend redeploy. We learned how much of ML is deployment and domain gap, not modeling, and got hands-on with the full GCP stack: Cloud Run, Cloud SQL, GCS, Vertex AI, Artifact Registry, and cross-project IAM.

What's next

  • Better temperature modeling. We only have measured ripening data at 10°C and 20°C, so in-between temperatures are currently estimated by interpolation — which still carries about 20% error. Reducing that is our top priority.
  • Higher classification accuracy — more real-world training data and model tuning.
  • Push notifications are already shipped; next we'll let users log the actual outcome to continuously refit the D-day coefficients.

Built With

Share this project:

Updates

Submission history