Búsqueda de sitios web

Transformaciones funcionales para visión por computadora usando PyTorch


Las tareas de visión por computadora a menudo requieren preprocesamiento y aumento de datos de imágenes para mejorar el rendimiento y la generalización del modelo. PyTorch, un popular marco de aprendizaje profundo, proporciona una poderosa biblioteca para transformaciones de imágenes llamada torchvision.transforms. Esta biblioteca ofrece una amplia gama de transformaciones predefinidas para el preprocesamiento y el aumento de datos. Sin embargo, en algunos casos, las transformaciones predefinidas pueden no ser suficientes y debemos aplicar transformaciones personalizadas a los datos de nuestra imagen. En esta publicación de blog, exploraremos el concepto de transformaciones funcionales en PyTorch y demostraremos cómo crear y aplicar transformaciones personalizadas para tareas de visión por computadora.

Comprender las transformaciones en PyTorch

Las transformaciones en PyTorch son operaciones que se pueden aplicar a datos de entrada, como imágenes, para modificar su apariencia o propiedades. Estas transformaciones se pueden clasificar en dos tipos: transformaciones de clase y transformaciones funcionales. Las transformaciones de clase se implementan como clases que definen tanto la operación de transformación como los parámetros asociados a ella. Por otro lado, las transformaciones funcionales se implementan como funciones que realizan la operación de transformación en los datos de entrada.

Las transformaciones funcionales ofrecen más flexibilidad en comparación con las transformaciones de clase, ya que nos permiten definir operaciones personalizadas aprovechando el poder de los tensores y funciones de PyTorch. Esto hace que las transformaciones funcionales sean particularmente útiles cuando necesitamos aplicar transformaciones complejas o parametrizadas a nuestros datos de imagen.

Crear transformaciones funcionales personalizadas

Para crear una transformación funcional personalizada, necesitamos definir una función que acepte un tensor de entrada y realice la operación de transformación deseada. Digamos que queremos crear una transformación personalizada llamada escala de grises, que convierte una imagen RGB a escala de grises. A continuación se muestra un ejemplo de implementación 

import torch

def grayscale(img):
   """Converts an RGB image to grayscale.
    
   Args:
       img (Tensor): Input RGB image tensor of shape (C, H, W).
        
   Returns:
       Tensor: Grayscale image tensor of shape (1, H, W).
   """
   if img.size(0) != 3:
       raise ValueError("Input image must have 3 channels (RGB).")
        
   # Apply grayscale transformation
   grayscale_img = torch.mean(img, dim=0, keepdim=True)
    
   return grayscale_img

En este ejemplo, definimos la función de escala de grises que toma una imagen tensor de imagen RGB de entrada de forma (C, H, W), donde C representa el número de canales (3 para imágenes RGB) y H y W representan la altura y el ancho. de la imagen, respectivamente. La función primero verifica si la imagen de entrada tiene el número correcto de canales (3 en este caso) y luego aplica la transformación en escala de grises calculando el valor medio en la dimensión del canal. El tensor de imagen en escala de grises resultante se devuelve con la forma (1, H, W), donde la imagen en escala de grises tiene un solo canal.

Aplicar transformaciones funcionales

Una vez que hayamos definido nuestra transformación funcional personalizada, podemos aplicarla a nuestros datos de imagen usando el módulo torchvision.transforms.function. Este módulo proporciona funciones de utilidad para trabajar con transformaciones funcionales. Para aplicar una transformación funcional, simplemente llamamos a la función de transformación y pasamos los datos de entrada. A continuación se muestra un ejemplo de cómo aplicar la transformación en escala de grises a una imagen 

from torchvision.transforms import functional as F
from PIL import Image

# Load the image using PIL
image = Image.open("image.jpg")

# Convert PIL image to PyTorch tensor
tensor_image = F.to_tensor(image)

# Apply the custom grayscale transform
grayscale_image = grayscale(tensor_image)

# Convert the grayscale tensor back to PIL image
grayscale_pil_image = F.to_pil_image(grayscale_image)

# Save the grayscale image
grayscale_pil_image.save("grayscale_image.jpg")

En este ejemplo, primero cargamos una imagen usando la biblioteca PIL y la convertimos a un tensor de PyTorch usando la función F.to_tensor. Luego aplicamos nuestra transformación en escala de grises a la imagen del tensor, que devuelve un tensor de imagen en escala de grises. Finalmente, volvemos a convertir el tensor de escala de grises a una imagen PIL usando la función F.to_pil_image y lo guardamos como un archivo JPEG.

Integración de transformaciones funcionales personalizadas en el canal de datos

Para utilizar eficazmente transformaciones funcionales personalizadas en tareas de visión por computadora, es fundamental integrarlas sin problemas en la canalización de datos. PyTorch proporciona la clase torchvision.transforms.Compose, que nos permite encadenar múltiples transformaciones y aplicarlas secuencialmente a nuestros datos de imagen. Podemos integrar fácilmente nuestras transformaciones funcionales personalizadas en la canalización de datos combinándolas con otras transformaciones predefinidas. A continuación se muestra un ejemplo 

from torchvision.transforms import Compose, RandomCrop, ToTensor

# Create a custom transform pipeline
custom_transforms = Compose([
   RandomCrop(224),     # Predefined transform
   grayscale,           # Custom transform
   ToTensor()            # Predefined transform
])

# Apply the transform pipeline to the image data
transformed_image = custom_transforms(image)

En este ejemplo, creamos una canalización de transformación usando Compose e incluimos transformaciones predefinidas y personalizadas. La transformación RandomCrop recorta aleatoriamente la imagen a un tamaño de 224x224, la transformación en escala de grises convierte la imagen a escala de grises usando nuestra transformación personalizada y ToTensor convierte la imagen transformada en un tensor de PyTorch. Al integrar nuestra transformación funcional personalizada en la canalización de datos, podemos aplicarla fácilmente junto con otras transformaciones y garantizar un flujo de trabajo de preprocesamiento consistente y eficiente.

Transformaciones aleatorias

Las transformaciones aleatorias son útiles para introducir variaciones y aleatoriedad en el proceso de aumento de datos. PyTorch proporciona varias transformaciones aleatorias en el módulo torchvision.transforms.function, como random_crop, random_rotation y random_horizontal_flip. Estas transformaciones se pueden combinar con transformaciones funcionales personalizadas para crear diversos datos de entrenamiento. Por ejemplo, podemos crear una transformación personalizada llamada random_resize_crop que cambia el tamaño y recorta aleatoriamente una imagen 

import random
from torchvision.transforms import functional as F

def random_resize_crop(img):
   """Randomly resizes and crops the image.
    
   Args:
       img (Tensor): Input image tensor.
        
   Returns:
       Tensor: Randomly resized and cropped image tensor.
   """
   # Randomly resize the image
   size = random.randint(256, 512)
   img = F.resize(img, size)
    
   # Randomly crop the image
   i, j, h, w = F.random_crop(img, (224, 224))
   img = F.crop(img, i, j, h, w)
    
   return img

Al combinar transformaciones aleatorias con transformaciones funcionales personalizadas, podemos introducir variaciones en el tamaño, la rotación y el volteo de la imagen, lo que hace que nuestros modelos sean más robustos y capaces de manejar diversas entradas.

Transformaciones parametrizadas personalizadas

En ciertos escenarios, es posible que deseemos crear transformaciones parametrizadas que se puedan ajustar según requisitos específicos. Por ejemplo, es posible que necesitemos una transformación personalizada llamada contraste_adjustment que nos permita controlar el contraste de una imagen:

def contrast_adjustment(img, factor):
   """Adjusts the contrast of the image.
    
   Args:
       img (Tensor): Input image tensor.
       factor (float): Contrast adjustment factor.
        
   Returns:
       Tensor: Image tensor with adjusted contrast.
   """
   return F.adjust_contrast(img, factor)

Aquí, la transformación contrast_adjustment acepta un parámetro adicional, factor, que determina el grado de ajuste de contraste aplicado a la imagen. Este enfoque parametrizado permite un control detallado sobre el proceso de transformación.

Conclusión

En este artículo, aprendimos cómo crear transformaciones personalizadas y aplicarlas a datos de imágenes. Las transformaciones funcionales ofrecen más flexibilidad en comparación con las transformaciones de clases, lo que nos permite definir operaciones personalizadas utilizando tensores y funciones de PyTorch. Con las transformaciones funcionales, tenemos la libertad de diseñar y aplicar transformaciones personalizadas a nuestras tareas de visión por computadora, lo que nos permite lograr un mejor rendimiento y generalización del modelo.