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)