Detección de Flores con YOLOv8: Entrenamiento Eficiente en Dataset de 8000+ Imágenes

Dataset de Flores

12 tipos de flores con más de 8000 imágenes en total. A continuación se presenta una guía completa que abarca desde la preparcaión de datos, entrenamiento del modelo, evaluación y visualización de resultados. Utilizaremos YOLOv8 para la tarea de detección de objetos y proporcionaremos scripts útiles para optimizar el procesamiento de datos y el entrenamiento.

1. Configuración del Entorno

Primero, asegúrate de tener instaladas las librerías necesarias. Ejecuta los sigueintes comandos:

pip install ultralytics
pip install torch torchvision
pip install opencv-python
pip install pandas
pip install matplotlib

2. Estructura del Dataset

Supongamos que la estructura de tu dataset es la siguiente:

flores_dataset/
├── imagenes/
│   ├── entrenamiento/
│   └── validacion/
├── etiquetas/
│   ├── entrenamiento/
│   └── validacion/

Cada imagen debe tener su archivo de etiquetas correspondiente con el mismo nombre, por ejemplo flor_001.jpg y flor_001.txt.

3. Archivo de Configuración

Crea un archivo llamado config_flores.yaml con el siguiente contenido:

# Configuración del Dataset de Detección de Flores

# Ruta al directorio del dataset
path: ./flores_dataset

# Directorios de imágenes para entrenamiento y validación
train: imagenes/entrenamiento
val: imagenes/validacion

# Directorios de etiquetas para entrenamiento y validación
train_labels: etiquetas/entrenamiento
val_labels: etiquetas/validacion

# Número de clases
nc: 12

# Nombres de las clases
names:
  0: rosa
  1: tulipan
  2: margarita
  3: girasol
  4: lirio
  5: orquidea
  6: diente_leon
  7: peonia
  8: clavel
  9: iris
  10: jacinto
  11: pensamiento

4. Entrenamiento del Modelo

Para entrenar el modelo de detección con YOLOv8, utiliza el siguiente comando:

yolo detect train data=config_flores.yaml model=yolov8n.pt epochs=100 imgsz=512

Parámetros:

  • data: Ruta al archivo de configuración YAML.
  • model: Modelo preentrenado de YOLOv8 (variantes disponibles: yolov8s, yolov8m, yolov8l, yolov8x).
  • epochs: Número de épocas de entrenamiento.
  • imgsz: Tamaño de las imágenes de entrada.

5. Evaluación del Modelo

Una vez completado el entrenamiento, evalúa el rendimiento del modelo en el conjunto de validación:

yolo detect val data=config_flores.yaml model=runs/detect/train/weights/best.pt imgsz=512

6. Visualización de Predicciones

El siguiente script en Python permite visualizar los resultados de la detección:

import cv2
import numpy as np
from ultralytics import YOLO

# Cargar el modelo entrenado
detector = YOLO('runs/detect/train/weights/best.pt')

# Ruta de la imagen de prueba
imagen_ruta = 'flores_dataset/imagenes/validacion/flor_001.jpg'
imagen = cv2.imread(imagen_ruta)

# Ejecutar predicción
predicciones = detector(imagen)

# Dibujar resultados
for resultado in predicciones:
    cajas = resultado.boxes.xyxy
    confianzas = resultado.boxes.conf
    ids_clase = resultado.boxes.cls

    for caja, conf, id_clase in zip(cajas, confianzas, ids_clase):
        x1, y1, x2, y2 = map(int, caja)
        nombre_clase = detector.names[int(id_clase)]
        puntuacion = float(conf)

        # Dibujar rectángulo
        cv2.rectangle(imagen, (x1, y1), (x2, y2), (0, 255, 0), 2)
        etiqueta = f'{nombre_clase}: {puntuacion:.2f}'
        cv2.putText(imagen, etiqueta, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

# Mostrar imagen
cv2.imshow('Resultado de Detección', imagen)
cv2.waitKey(0)
cv2.destroyAllWindows()

7. Scripts de Utilidad

7.1 Script de Aumantación de Datos

import os
import cv2
from imgaug import augmenters as iaa

def augmenter_datos(imagen_ruta, directorio_salida, cantidad=5):
    img = cv2.imread(imagen_ruta)

    secuencia = iaa.Sequential([
        iaa.Fliplr(0.5),
        iaa.Affine(rotate=(-15, 15)),
        iaa.Multiply((0.7, 1.3))
    ])

    for i in range(cantidad):
        img_aumentada = secuencia(image=img)
        nuevo_nombre = os.path.join(directorio_salida, 
            f"{os.path.splitext(os.path.basename(imagen_ruta))[0]}_aug{i}.jpg")
        cv2.imwrite(nuevo_nombre, img_aumentada)

# Rutas del dataset
dir_imagenes = 'flores_dataset/imagenes/entrenamiento'
dir_salida = 'flores_dataset/imagenes_aumentadas'

os.makedirs(dir_salida, exist_ok=True)

archivos_imagen = [os.path.join(dir_imagenes, f) for f in os.listdir(dir_imagenes) if f.endswith('.jpg')]

for archivo in archivos_imagen:
    augmenter_datos(archivo, dir_salida)

7.2 Script de Verificación de Datos

import os

def verificar_integridad(directorio_imagenes, directorio_etiquetas):
    archivos_img = set(os.listdir(directorio_imagenes))
    archivos_etiq = set(os.listdir(directorio_etiquetas))

    etiquetas_faltantes = archivos_img - {f.replace('.txt', '.jpg') for f in archivos_etiq}
    imagenes_faltantes = {f.replace('.txt', '.jpg') for f in archivos_etiq} - archivos_img

    if etiquetas_faltantes:
        print("Etiquetas faltantes para:")
        for archivo in etiquetas_faltantes:
            print(f"  - {archivo}")

    if imagenes_faltantes:
        print("Imágenes faltantes para:")
        for archivo in imagenes_faltantes:
            print(f"  - {archivo}")

    if not etiquetas_faltantes and not imagenes_faltantes:
        print("Verificación completada: todos los datos están correctos.")

dir_imagenes = 'flores_dataset/imagenes/entrenamiento'
dir_etiquetas = 'flores_dataset/etiquetas/entrenamiento'

verificar_integridad(dir_imagenes, dir_etiquetas)

7.3 Script de Evaluación del Modelo

import os
import cv2
import json
from ultralytics import YOLO
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval

def evaluar_rendimiento(ruta_modelo, configuracion, archivo_anotaciones):
    modelo = YOLO(ruta_modelo)
    coco_gt = COCO(archivo_anotaciones)
    predicciones = []

    for img_id in coco_gt.getImgIds():
        info_img = coco_gt.loadImgs(img_id)[0]
        ruta_img = os.path.join(configuracion['path'], info_img['file_name'])
        img = cv2.imread(ruta_img)

        resultados = modelo(img)

        for res in resultados:
            cajas = res.boxes.xyxy
            confs = res.boxes.conf
            clases = res.boxes.cls

            for caja, conf, clase in zip(cajas, confs, clases):
                x1, y1, x2, y2 = map(int, caja)
                ancho, alto = x2 - x1, y2 - y1
                predicciones.append({
                    "image_id": img_id,
                    "category_id": int(clase) + 1,
                    "bbox": [x1, y1, ancho, alto],
                    "score": float(conf)
                })

    with open('evaluacion_resultados.json', 'w') as f:
        json.dump(predicciones, f)

    coco_dt = coco_gt.loadRes('evaluacion_resultados.json')
    evaluador = COCOeval(coco_gt, coco_dt, 'bbox')
    evaluador.evaluate()
    evaluador.accumulate()
    evaluador.summarize()

ruta_modelo = 'runs/detect/train/weights/best.pt'
configuracion = {
    'path': './flores_dataset',
    'annotations': 'anotaciones/instances_val.json'
}
archivo_anot = os.path.join(configuracion['path'], configuracion['annotations'])

evaluar_rendimiento(ruta_modelo, configuracion, archivo_anot)

7.4 Script de Guardado de Predicciones

import os
import cv2
import json
from ultralytics import YOLO

def guardar_predicciones(ruta_modelo, directorio_imagenes, directorio_salida):
    modelo = YOLO(ruta_modelo)
    os.makedirs(directorio_salida, exist_ok=True)

    lista_imagenes = [os.path.join(directorio_imagenes, f) for f in os.listdir(directorio_imagenes) if f.endswith('.jpg')]

    resultados_totales = []
    for ruta_img in lista_imagenes:
        img = cv2.imread(ruta_img)
        preds = modelo(img)

        for pred in preds:
            cajas = pred.boxes.xyxy
            confs = pred.boxes.conf
            clases = pred.boxes.cls

            for caja, conf, clase in zip(cajas, confs, clases):
                x1, y1, x2, y2 = map(int, caja)
                ancho, alto = x2 - x1, y2 - y1
                resultados_totales.append({
                    "image_path": ruta_img,
                    "category_id": int(clase),
                    "bbox": [x1, y1, ancho, alto],
                    "score": float(conf)
                })

    with open(os.path.join(directorio_salida, 'predicciones.json'), 'w') as f:
        json.dump(resultados_totales, f)

modelo_ruta = 'runs/detect/train/weights/best.pt'
img_dir = 'flores_dataset/imagenes/validacion'
salida_dir = 'flores_dataset/resultados_prediccion'

guardar_predicciones(modelo_ruta, img_dir, salida_dir)

7.5 Script de Inferencia

import cv2
from ultralytics import YOLO

def ejecutar_inferencia(ruta_modelo, ruta_imagen):
    modelo = YOLO(ruta_modelo)
    imagen = cv2.imread(ruta_imagen)

    resultados = modelo(imagen)

    for res in resultados:
        cajas = res.boxes.xyxy
        confs = res.boxes.conf
        clases = res.boxes.cls

        for caja, conf, clase in zip(cajas, confs, clases):
            x1, y1, x2, y2 = map(int, caja)
            etiqueta = modelo.names[int(clase)]
            puntuacion = float(conf)

            cv2.rectangle(imagen, (x1, y1), (x2, y2), (0, 255, 0), 2)
            texto = f'{etiqueta}: {puntuacion:.2f}'
            cv2.putText(imagen, texto, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

    cv2.imshow('Inferencia', imagen)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

modelo_path = 'runs/detect/train/weights/best.pt'
imagen_path = 'flores_dataset/imagenes/validacion/flor_001.jpg'

ejecutar_inferencia(modelo_path, imagen_path)

Etiquetas: YOLOv8 object-detection Python computer-vision deep-learning

Publicado el 6-12 17:11