Loading…
Loading…
An image classifier that looks at a photo of fresh produce and predicts what it is and whether it looks fresh or spoiled. It is a fine-tuned version of google/vit-base-patch16-224, trained on v3loc1ty/kafwain-produce-freshness.
It reaches 99.68% accuracy on its evaluation set. That set comes from the same kind of images as the training data, so expect lower accuracy on real-world photos (see Limitations).
The model is a prototype for Kafwain, a student startup in Qatar that connects local farms with restaurants through one order, one chilled delivery and one invoice. In Kafwain, the model's job is to help staff check produce when farms drop off orders, flagging items that may be spoiled so a person can look at them.
| Developed by | The Kafwain team (Doha, Qatar) |
| Model type | Vision Transformer (ViT-Base, patch size 16) for image classification |
| Fine-tuned from | google/vit-base-patch16-224 (pre-trained on ImageNet-21k, fine-tuned on ImageNet-1k at 224×224) |
| Parameters | 85.8M (float32, Safetensors) |
| Input | One RGB image, resized to 224×224 by the image processor |
| Output | A probability for each label (see Labels) |
| License | Apache-2.0 |
| Status | Prototype; not yet tested on Kafwain's own photos |
The model predicts one of these labels. Each label combines a produce type with a freshness state.
| ID | Label | Meaning |
|---|---|---|
| [FILL: 0] | [FILL: label name] | [FILL: e.g. fresh apple] |
| [FILL: 1] | [FILL: label name] | [FILL: e.g. spoiled apple] |
| … | … | … |
[FILL: copy the label list from id2label in this repo's config.json.]
Produce types not in this list are not supported. The model will still return one of the labels above, often with high confidence (see Limitations).
Primary use: an assistant for the pickup check. At Kafwain's pickup point, staff photograph produce as farms drop it off. The model flags items that may be spoiled, and a person makes the final decision to accept or reject them.
Other uses:
Intended users: Kafwain operations staff (through the Kafwain app) and developers building or testing the feature.
Do not use this model for:
Quick start with a pipeline:
from transformers import pipeline
classifier = pipeline("image-classification", model="v3loc1ty/kafwain-produce-freshness-vit")
print(classifier("produce_photo.jpg"))
Recommended use, with a confidence threshold so uncertain photos go to a person:
import torch
from PIL import Image
from transformers import AutoImageProcessor, AutoModelForImageClassification
model_id = "v3loc1ty/kafwain-produce-freshness-vit"
processor = AutoImageProcessor.from_pretrained(model_id)
model = AutoModelForImageClassification.from_pretrained(model_id)
image = Image.open("produce_photo.jpg").convert("RGB")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
probs = model(**inputs).logits.softmax(dim=-1)[0]
score, idx = probs.max(dim=-1)
label = model.config.id2label[idx.item()]
THRESHOLD = 0.80 # starting value; tune it on your own photos
if score.item() < THRESHOLD:
print("Unsure: send to a person to check")
else:
print(f"{label} ({score.item():.1%})")
Photo tips: one item or a close-up of a few items, filling most of the frame, in good even light, on a plain background.
Trained and evaluated on v3loc1ty/kafwain-produce-freshness.
| Built from | [FILL: source datasets and links, e.g. public fresh/rotten fruit datasets] |
| Images | [FILL: total number of images] |
| Splits | [FILL: train / evaluation (and test, if any) sizes, and how the split was made] |
| Images per label | [FILL: counts, or "roughly balanced"] |
| Preprocessing | ViT image processor: resize to 224×224 and normalize. [FILL: any augmentation used] |
Fine-tuned with the Hugging Face Trainer.
| Hyperparameter | Value |
|---|---|
| Learning rate | 5e-05 |
| Train batch size | 32 |
| Eval batch size | 64 |
| Seed | 42 |
| Optimizer | AdamW (torch fused), betas (0.9, 0.999), epsilon 1e-08 |
| Learning-rate schedule | Linear, 300 warmup steps |
| Epochs | 4 |
| Mixed precision | Native AMP |
| Hardware and training time | [FILL: e.g. 1× T4 GPU, about N minutes] |
Framework versions: Transformers 5.22.2 · PyTorch 2.15.0+cu132 · Datasets 5.1.0 · Tokenizers 0.23.3
| Epoch | Training loss | Validation loss | Accuracy |
|---|---|---|---|
| 1 | 0.0560 | 0.0240 | 0.9932 |
| 2 | 0.0429 | 0.0162 | 0.9965 |
| 3 | 0.0329 | 0.0126 | 0.9963 |
| 4 | 0.0197 | 0.0123 | 0.9968 |
Final: loss 0.0123, accuracy 99.68% on [FILL: evaluation split name and number of images].
[FILL: precision, recall and F1 for each label, and a confusion matrix. Overall accuracy can hide a weak label, especially a rare one.]
The model hasn't yet been tested on Kafwain's own photos taken at a pickup point. This will be added after the pilot. Until then, treat 99.68% as an upper bound, not the expected real-world accuracy.
Base model:
@misc{dosovitskiy2020image,
title = {An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale},
author = {Alexey Dosovitskiy and Lucas Beyer and Alexander Kolesnikov and Dirk Weissenborn and Xiaohua Zhai and Thomas Unterthiner and Mostafa Dehghani and Matthias Minderer and Georg Heigold and Sylvain Gelly and Jakob Uszkoreit and Neil Houlsby},
year = {2020},
eprint = {2010.11929},
archivePrefix = {arXiv}
}
Source datasets: [FILL: credit and cite each dataset used to build v3loc1ty/kafwain-produce-freshness, following its license.]
The Kafwain team: [FILL: contact email or link]
google/vit-base-patch16-224