Configuración de RT-DETR para Detección de Residuos Plásticos en Superficies de Agua con Vehículos Aéreos No Tripulados

Este conjunto de datos está diseñado para el entrenamiento de modelos de detección de objetos en imágenes capturadas por drones sobre cuerpos de agua. Contiene 4,487 imágenes anotadas con cinco categorías de desechos plásticos flotantes: otros plásticos, bolsas de plástico, botellas de plástico, vasos de plástico y envoltorios de plático. Las anotaciones están disponibles en formatos Pascal VOC (XML) y YOLO (TXT), facilitando su uso con frameworks populares como Ultralytics RT-DETR.

Descripción del Conjunto de Datos

Componente Detalle
Nombre Datos de detección de residuos acuáticos desde drones
Total de imágenes 4,487
Fuente de captura Drones con perspectiva aérea (lagos, ríos, mares)
Tarea principal Detección de objetos
Formatos de anotación Pascal VOC (.xml), YOLO (.txt con coordenadas normalizadas)
Categorías (5 clases) other_plastic, plastic_bag, plastic_bottle, plastic_cup, plastic_package

Estrcutura de Archivso Recomendada

Para organizar el conjunto de datos de manera eficiente, se sugiere la siguiente jerarquía:

dataset_residuos_acuaticos/
├── imagenes/
│   ├── entrenamiento/
│   ├── validacion/
│   └── prueba/
├── anotaciones_voc/          # Archivos XML para Pascal VOC
├── etiquetas_yolo/           # Archivos TXT para YOLO
└── configuracion.yaml        # Archivo de configuración para YOLOv8

Ejemplo de archivo de configuración configuracion.yaml:

ruta_entrenamiento: ./imagenes/entrenamiento
ruta_validacion: ./imagenes/validacion
ruta_prueba: ./imagenes/prueba

num_clases: 5
nombres_clases: ['otro_plastico', 'bolsa_plastico', 'botella_plastico', 'vaso_plastico', 'envoltorio_plastico']

Implementación de RT-DETR para Detección en Tiempo Real

A continuación, se detalla un flujo de trabajo completo para entrenar un modelo RT-DETR, incluyendo conversión de datos, entrenamiento y despliegue web.

Estructura del Proyecto

proyecto_deteccion_residuos/
├── datos/
│   ├── imagenes_originales/
│   ├── anotaciones_voc/
│   └── etiquetas_yolo/
├── modelos/
│   └── rtdetr_residuos.pt
├── configuraciones/
│   └── rtdetr_personalizado.yml
├── scripts/
│   ├── entrenar.py
│   ├── inferencia.py
│   └── conversion_formato.py
├── aplicacion_web/
│   ├── vistas.py
│   ├── modelos_datos.py
│   ├── urls.py
│   └── plantillas/
└── dependencias.txt

Archivo de Dependencias

torch==2.0.1
torchvision==0.15.2
ultralytics==8.2.0
opencv-python==4.8.0
numpy==1.24.3
django==4.2.7
pyecharts==2.0.0
lxml==4.9.3

Script de Conversión de VOC a YOLO

Este script transforma las anotaciones XML a formato TXT para YOLO, con lógica modificada y nombres de variables alternativos.

# scripts/conversion_formato.py
import os
from xml.etree import ElementTree as ET
from pathlib import Path

# Mapeo de clases actualizado
etiquetas_clase = ['otro_plastico', 'bolsa_plastico', 'botella_plastico', 'vaso_plastico', 'envoltorio_plastico']
mapa_clases = {etiqueta: idx for idx, etiqueta in enumerate(etiquetas_clase)}

def transformar_voc_a_yolo(origen_xml, destino_txt, carpeta_imagenes):
    Path(destino_txt).mkdir(parents=True, exist_ok=True)
    for archivo_xml in Path(origen_xml).glob("*.xml"):
        arbol = ET.parse(archivo_xml)
        raiz = arbol.getroot()

        nombre_imagen = raiz.find('filename').text
        ruta_imagen = os.path.join(carpeta_imagenes, nombre_imagen)
        if not os.path.exists(ruta_imagen):
            continue

        dimensiones = raiz.find('size')
        ancho_img = int(dimensiones.find('width').text)
        alto_img = int(dimensiones.find('height').text)

        lineas_yolo = []
        for objeto in raiz.findall('object'):
            nombre_clase = objeto.find('name').text
            if nombre_clase not in mapa_clases:
                continue
            id_clase = mapa_clases[nombre_clase]

            cuadro = objeto.find('bndbox')
            x_min = int(cuadro.find('xmin').text)
            y_min = int(cuadro.find('ymin').text)
            x_max = int(cuadro.find('xmax').text)
            y_max = int(cuadro.find('ymax').text)

            # Cálculo de coordenadas normalizadas
            centro_x = (x_min + x_max) / (2 * ancho_img)
            centro_y = (y_min + y_max) / (2 * alto_img)
            ancho_cuadro = (x_max - x_min) / ancho_img
            alto_cuadro = (y_max - y_min) / alto_img

            linea = f"{id_clase} {centro_x:.6f} {centro_y:.6f} {ancho_cuadro:.6f} {alto_cuadro:.6f}"
            lineas_yolo.append(linea)

        nombre_txt = archivo_xml.with_suffix('.txt').name
        with open(os.path.join(destino_txt, nombre_txt), 'w') as archivo:
            archivo.write('\n'.join(lineas_yolo))

if __name__ == "__main__":
    transformar_voc_a_yolo(
        origen_xml="datos/anotaciones_voc",
        destino_txt="datos/etiquetas_yolo",
        carpeta_imagenes="datos/imagenes_originales"
    )
    print("Proceso de conversión finalizado.")

Configuración de Entrenamiento para RT-DETR

# configuraciones/rtdetr_personalizado.yml
tarea: deteccion
modo: entrenamiento

modelo:
  archivo_yaml: "rtdetr-l.yaml"
  num_clases: 5
  nombres_clases: ['otro_plastico', 'bolsa_plastico', 'botella_plastico', 'vaso_plastico', 'envoltorio_plastico']

datos:
  ruta_base: ../datos
  subconjunto_entrenamiento: imagenes_originales/entrenamiento
  subconjunto_validacion: imagenes_originales/validacion
  subconjunto_prueba: imagenes_originales/prueba

parametros_entrenamiento:
  epocas: 100
  tamano_lote: 16
  tamano_imagen: 640
  dispositivo: 0  # Cambiar a "cpu" si no hay GPU
  trabajadores: 4
  optimizador: AdamW
  tasa_aprendizaje_inicial: 0.0001
  paciencia: 15
  guardar_modelo: true
  directorio_resultados: ejecuciones/entrenamiento
  nombre_experimento: residuos_rtdetr

Script de Entrenamiento

# scripts/entrenar.py
from ultralytics import RTDETR

def iniciar_entrenamiento():
    modelo_base = RTDETR("rtdetr-l.pt")
    resultados = modelo_base.train(
        data="configuraciones/rtdetr_personalizado.yml",
        epochs=100,
        imgsz=640,
        batch=16,
        device=0,
        project="ejecuciones/entrenamiento",
        name="residuos_rtdetr",
        exist_ok=True
    )
    print(f"Entrenamiento completado. Modelo óptimo en: {resultados.save_dir}/weights/best.pt")

if __name__ == "__main__":
    iniciar_entrenamiento()

Script de Inferencia para Pruebas

# scripts/inferencia.py
from ultralytics import RTDETR
import cv2

def realizar_inferencia(ruta_modelo, ruta_imagen):
    modelo_cargado = RTDETR(ruta_modelo)
    predicciones = modelo_cargado.predict(ruta_imagen, conf=0.3, save=True)
    return predicciones

if __name__ == "__main__":
    realizar_inferencia("ejecuciones/entrenamiento/residuos_rtdetr/weights/best.pt", "prueba.jpg")

Sistema Web con Django

Implementación básica para visualización y registro de detecciones.

Modelo de datos en modelos_datos.py:

# aplicacion_web/modelos_datos.py
from django.db import models

class RegistroDeteccion(models.Model):
    imagen_subida = models.ImageField(upload_to='entradas/')
    imagen_resultado = models.ImageField(upload_to='salidas/', null=True)
    objetos_detectados = models.JSONField()
    marca_temporal = models.DateTimeField(auto_now_add=True)
    ubicacion_monitoreo = models.CharField(max_length=200, default="Río Principal")

Vista principal en vistas.py:

# aplicacion_web/vistas.py
from django.shortcuts import render
from django.http import JsonResponse
from django.core.files.storage import FileSystemStorage
from .modelos_datos import RegistroDeteccion
from ultralytics import RTDETR
import os

modelo_deteccion = RTDETR("ejecuciones/entrenamiento/residuos_rtdetr/weights/best.pt")
traduccion_clases = ['Otro plástico', 'Bolsa de plástico', 'Botella de plástico', 'Vaso de plástico', 'Envoltorio de plástico']

def pagina_principal(request):
    return render(request, 'interfaz_principal.html')

def procesar_imagen(request):
    if request.method == "POST":
        archivo_imagen = request.FILES['imagen']
        gestor = FileSystemStorage()
        nombre_guardado = gestor.save(archivo_imagen.name, archivo_imagen)
        ruta_entrada = gestor.path(nombre_guardado)
        ruta_salida = os.path.join(settings.MEDIA_ROOT, 'salidas', nombre_guardado)

        resultados = modelo_deteccion(ruta_entrada)
        imagen_anotada = resultados[0].plot()
        cv2.imwrite(ruta_salida, imagen_anotada)

        detecciones = []
        for cuadro in resultados[0].boxes:
            id_clase = int(cuadro.cls.item())
            confianza = float(cuadro.conf.item())
            detecciones.append({
                'clase': traduccion_clases[id_clase],
                'confianza': round(confianza, 2)
            })

        RegistroDeteccion.objects.create(
            imagen_subida=archivo_imagen,
            imagen_resultado=f'salidas/{nombre_guardado}',
            objetos_detectados=detecciones
        )

        return JsonResponse({
            'url_resultado': gestor.url(f'salidas/{nombre_guardado}'),
            'lista_detecciones': detecciones
        })
    return JsonResponse({'error': 'Solicitud no válida'})

Etiquetas: RT-DETR YOLO Django Detección de Objetos Drones

Publicado el 6-8 23:33