Views
No views yet
| # | Class | Definition |
|---|---|---|
| 1 | Green | 100% green |
| 2 | Breakers | less than 10% colour |
| 3 | Turning | 10–40% colour |
| 4 | Pink | 40–80% colour |
| 5 | Light Red | 80–90% red |
| 6 | Red | more than 90% red |
| Subset | Images | Precision | Recall | mAP50 | mAP50-95 |
|---|---|---|---|---|---|
| Combined (drone+mobile) | 98 | 0.581 | 0.498 | 0.507 | 0.388 |
| Drone-only | 22 | 0.421 | 0.691 | 0.535 | 0.317 |
| Mobile-only | 76 | 0.509 | 0.503 | 0.482 | 0.386 |
yield_estimation.py converts detected/tracked fruit counts into an estimated kg figure using a
configurable average-fruit-weight table (DEFAULT_AVG_FRUIT_WEIGHT_G, default 120 g/fruit for all
classes — tomatoes reach most of their final size by the Breakers stage, so ripeness itself
changes weight only modestly). This default is not calibrated to any specific farm/cultivar —
before trusting an absolute kg number in production, weigh a sample of counted fruit and adjust
the table accordingly.model.track(..., persist=True)) to assign a persistent track
ID to each physical fruit, then counts unique track IDs, not raw per-frame detections. The demo
app's Video tab reports both numbers side by side so you can see the overcount ratio directly.1from ultralytics import YOLO
2model = YOLO("model.pt")
3result = model.predict("photo.jpg", conf=0.25, imgsz=1024)[0]
4result.show() # or result.plot() for a numpy array
5
6from yield_estimation import counts_from_detections, estimate_yield_from_counts
7class_names = [result.names[int(c)] for c in result.boxes.cls.tolist()]
8counts = counts_from_detections(class_names)
9print(estimate_yield_from_counts(counts).as_dict())app.py's run_video function (uses
model.track(..., persist=True, tracker="bytetrack.yaml") + summarize_tracked_video).