Skip to content

MITDEVPRO/fruta-vision

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fruta-vision

MVP en Python para medir calibre (mm) y color de fruta a partir de una foto, orientado a packing agrícola. Primer objetivo: cítricos/mandarina; diseño extensible a uva de mesa.

Cómo funciona

  1. Escala: se detecta un marcador ArUco (diccionario DICT_4X4_50) de lado conocido (default 50 mm) apoyado en el mismo plano que la fruta. Del tamaño del marcador en píxeles se deriva mm/px.
  2. Segmentación (dos backends, --segmentador):
    • hsv (default): máscara por saturación (la fruta es saturada; el fondo neutro y el marcador no) + morfología + contornos externos. Rápido y sin dependencias, pero exige fondo neutro.
    • yolo: YOLOv8-seg preentrenado en COCO (clases orange/apple/ banana — cubre mandarina sin entrenar nada). Funciona con fondo real de packing. Requiere pip install "fruta-vision[yolo]"; los pesos (models/yolov8n-seg.pt, 6.7 MB) se descargan solos si faltan. Ambos backends comparten el mismo filtro (exclusión del marcador, área mínima, orden izquierda→derecha) y el resto del pipeline.
  3. Calibre: diámetro del círculo mínimo envolvente × mm/px → código de calibre según tabla de mandarina (bandas simplificadas sin traslape basadas en UNECE FFV-14; configurable en src/fruta_vision/measure.py).
  4. Color: HSV medio dentro del contorno (borde erosionado para no promediar con el fondo), CCI (Citrus Color Index = 1000·a/(L·b) en CIELAB) y clase de madurez: naranja | pintona | quiebre | verde.
  5. Salida: imagen anotada por foto + results.csv con una fila por fruta.

Uso

python3.11 -m venv .venv
.venv/bin/pip install -e ".[dev]"

# generar imágenes de muestra sintéticas
PYTHONPATH=src .venv/bin/python scripts/make_samples.py

# procesar un directorio (o una imagen individual)
.venv/bin/fruta-vision data/samples --marker-mm 50 --out out

# con fondo real (packing): backend YOLO preentrenado
.venv/bin/pip install "ultralytics>=8.2"
.venv/bin/fruta-vision foto_packing.jpg --segmentador yolo --out out

# regenerar la muestra con naranjas reales (recorta de foto USDA/Wikimedia)
PYTHONPATH=src .venv/bin/python scripts/make_real_sample.py

Salidas en out/: <imagen>_annotated.jpg y results.csv con columnas image, fruit_id, diameter_mm, diameter_eq_mm, area_mm2, circularity, calibre, color_class, hue_mean, saturation_mean, value_mean, cci, mm_per_px.

Para imprimir un marcador:

import cv2
from fruta_vision.aruco import generate_marker

cv2.imwrite("marker_50mm.png", generate_marker(marker_id=0, side_px=400))
# imprimir a 50 x 50 mm exactos y pegarlo sobre superficie rígida

Checks

.venv/bin/pytest -q
.venv/bin/ruff check src tests scripts
.venv/bin/black --check src tests scripts

Supuestos y decisiones (MVP)

  • Foto cenital con la fruta y el marcador en el mismo plano y sin oclusiones entre frutas. No se corrige perspectiva ni distorsión de lente (siguiente iteración: homografía con 4 marcadores o calibración de cámara).
  • Fondo neutro (mesa blanca/gris/negra): la segmentación es por saturación, robusta y sin modelo entrenado. Con fondo complejo se necesitaría un modelo de segmentación (p. ej. SAM/YOLO-seg).
  • Frutas separadas entre sí; no hay watershed para racimos/contacto. Para uva de mesa en racimo, la siguiente iteración es watershed sobre distancia + mínimos locales.
  • La tabla de calibres es de mandarina y las bandas están simplificadas para no traslapar (la norma UNECE permite traslape entre códigos). Ajustar CALIBRE_MANDARINA a la norma del cliente/exportadora; las uvas reportan diámetro en mm y quedan fuera de esa tabla, por diseño.
  • Umbrales de matiz para la clase de madurez (color.py) son aproximados; calibrar con fruta real y luz del packing (idealmente caja de luz D65).
  • data/samples/ contiene imágenes sintéticas (círculos + ArUco real) generadas con scripts/make_samples.py, porque no hay fotos reales aún. Los tests validan diámetro con tolerancia 3 % y el signo del CCI.
  • El diámetro reportado es el del círculo mínimo envolvente (equivale al calibre ecuatorial si la foto es cenital); también se reporta el diámetro equivalente por área como control.

Estructura

src/fruta_vision/
  aruco.py      # detección ArUco y escala mm/px
  segment.py    # máscara HSV y contornos de fruta
  measure.py    # calibre, área, circularidad y tabla de calibres
  color.py      # HSV medio, CCI y clase de madurez
  annotate.py   # imagen anotada
  pipeline.py   # orquestación + CSV
  cli.py        # entrada de línea de comandos
  synthetic.py  # escenas sintéticas (tests y muestras)
tests/          # 21 tests sobre escenas sintéticas de escala conocida
scripts/make_samples.py
data/samples/   # muestras sintéticas

Nota de entorno

En esta máquina el editable install (pip install -e .) no agrega src a sys.path (el .pth no se procesa); por eso pytest usa pythonpath = ["src"] y el CLI se instala con pip install . normal. Si editas el código fuente, reinstala con .venv/bin/pip install -q --force-reinstall --no-deps ..

About

MVP visión: calibre (mm) y color de fruta por foto con marcador ArUco — cítricos/mandarina, extensible a uva de mesa

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages