Midjourney y la composición por espacio negativo: guía práctica

Fundamentos de la composición en la imagen sintética

La composición define la manera en que se organizan los elementos visuales sobre un plano. En Midjourney, incluir términos relacionados con la composición no solo mejora la estética de la imagen, sino que también orienta al modelo hacia referencias visuales de mayor calidad. El sistema ha sido entrenado con imágenes que suelen proceder de fuentes profesionales, por lo que al emplear descriptores compositivos se activan asociaciones con ese tipo de contenido curado.

Desde una perspectiva universal, la composición es una herramienta transversal a cualquier medio visual: dirige la mirada, enfatiza el sujeto y comunica emociones. Por tanto, su aplicación en Midjourney produce mejoras consistentes y predecibles en la salida generada.

Composición por espacio negativo

La composición por espacio negativo se basa en rodear al sujeto principle con amplias zonas vacías o de bajo detalle. Este vacío no es un simple fondo, sino un elemento activo que refuerza la presencia del objeto central y estimula la interpretación personal del observador.

Características principales

  • Enfoque absoluto en el sujeto: la ausencia de elementos secundarios dirige la atención de inmediato hacia el motivo principal.
  • Amplitud interpretativa: el espacio vacío invita a completar la narrativa visual, generando una experiencia más participativa.
  • Limpieza formal: se eliminan distracciones, lo que facilita la lectura de la imagen y refuerza su mensaje.

Ámbitos de aplicación

En retratos, el uso del espacio negativo acentúa la expresión facial y la postura, aislando al individuo de cualquier contexto superfluo. En bodegones y fotografía de producto, permite resaltar texturas, formas y detalles que de otro modo pasarían desapercibidos.

Construcción del prompt

Al redactar las instrucciones para Midjourney, es fundamental identificar primero el elemento central que se desea destacar. La frase clave Negative Space Composition debe integrarse en la descripción para indicar explícitamente la intención compositiva. Acompañar este término con especificaciones sobre iluminación suave, fondos neutros y mínima cantidad de detalles ayuda a consolidar el efecto deseado. La brevedad y precisión en el lenguaje evitan introducir elementos que compitan con el vacío buscado.

Ejemplo comparativo

Se presenta una comparación entre un prompt sin indicación compositiva y otro que incorpora la técnica de espacio negativo.


# Sin composición por espacio negativo
A vibrant pink lotus flower blooming in a pond, surrounded by green lily pads and other flowers, with water ripples and reflections, soft sunlight illuminating the scene, peaceful and natural setting --ar 16:9
 

Este primer caso genera una escena rica en elementos: hojas de nenúfar, otras flores, ondas y reflejos. Aunque el loto es el protagonista, la complejidad del fondo reparte la atención del espectador.


# Con composición por espacio negativo
A vibrant pink lotus flower blooming alone with vast open space around it, minimal background details, soft shadows on a plain white surface, Negative Space Composition --ar 16:9
 

Al añadir la indicación compositiva y simplificar el contexto, la flor se convierte en el único foco de interés. El fondo prácticamente desapareec, creando una atmósfera serena y contemplativa que potencia la carga simbólica de la imagen.

Integración con flujos de trabajo programáticos

Para quienes automatizan procesos creativos, es posible combinar la generación de imágenes con técnicas de transferencia de estilo. A continuación se muestra un ejemplo adaptado de un módulo de transferencia de estilo que utiliza VGG19 y optimización basada en Gram. El código se ha reestructurado para mejorar la legibilidad y renombrar variables, manteniendo la funcionalidad original.

import torch
import torch.nn.functional as F
import torchvision.transforms as T
from torchvision.models import vgg19, VGG19_Weights
from PIL import Image
import matplotlib.pyplot as plt

class EstiloTransferido(torch.nn.Module):
   def __init__(self):
       super().__init__()
       self.red = vgg19(weights=VGG19_Weights.DEFAULT).features
       for p in self.red.parameters():
           p.requires_grad_(False)

   def forward(self, entrada):
       capas = {'0': 'b1c1', '5': 'b2c1', '10': 'b3c1',
                '19': 'b4c1', '21': 'b4c2', '28': 'b5c1'}
       salidas = {}
       for nombre, capa in self.red._modules.items():
           entrada = capa(entrada)
           if nombre in capas:
               salidas[capas[nombre]] = entrada
       return salidas

def cargar_imagen(ruta, tam_max=400, forma=None):
   img = Image.open(ruta).convert('RGB')
   tam = tam_max if max(img.size) > tam_max else max(img.size)
   if forma:
       tam = forma
   transform = T.Compose([
       T.Resize((tam, tam)),
       T.ToTensor(),
       T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
   ])
   return transform(img)[:3].unsqueeze(0)

def tensor_a_imagen(tensor):
   img = tensor.cpu().clone().detach().squeeze(0)
   img = img.permute(1, 2, 0).numpy()
   img = img * (0.229, 0.224, 0.225) + (0.485, 0.456, 0.406)
   return img.clip(0, 1)

def gram(tensor):
   b, c, h, w = tensor.size()
   caracteristicas = tensor.view(c, h * w)
   return torch.mm(caracteristicas, caracteristicas.t())

dispositivo = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
contenido = cargar_imagen('contenido.jpg').to(dispositivo)
estilo = cargar_imagen('estilo.jpg', forma=contenido.shape[-2:]).to(dispositivo)
modelo = EstiloTransferido().to(dispositivo)

mapa_estilo = modelo(estilo)
mapa_contenido = modelo(contenido)
gram_estilo = {capa: gram(mapa_estilo[capa]) for capa in mapa_estilo}

objetivo = contenido.clone().requires_grad_(True).to(dispositivo)
pesos_estilo = {'b1c1': 1.0, 'b2c1': 0.8, 'b3c1': 0.5, 'b4c1': 0.3, 'b5c1': 0.1}
alpha = 1e4
beta = 1e2
optimizador = torch.optim.Adam([objetivo], lr=0.003)

for paso in range(1, 3001):
   mapa_objetivo = modelo(objetivo)
   perdida_contenido = F.mse_loss(mapa_objetivo['b4c2'], mapa_contenido['b4c2'])
   perdida_estilo = 0
   for capa, peso in pesos_estilo.items():
       gram_objetivo = gram(mapa_objetivo[capa])
       perdida_capa = peso * F.mse_loss(gram_objetivo, gram_estilo[capa])
       _, c, h, w = mapa_objetivo[capa].shape
       perdida_estilo += perdida_capa / (c * h * w)
   perdida_total = alpha * perdida_contenido + beta * perdida_estilo
   optimizador.zero_grad()
   perdida_total.backward()
   optimizador.step()
   if paso % 500 == 0:
       print(f'Iteración {paso}, Pérdida total: {perdida_total.item():.4f}')
       plt.imshow(tensor_a_imagen(objetivo))
       plt.axis('off')
       plt.show()
 

Este bloque muestra cómo separar la lógica en funciones más descriptivas y emplear pesos predefinidos de VGG19, facilitando su mantenimiento. La integración con Midjourney podría darse generando imágenes base que luego son estilizadas mediante este flujo de trabajo.

Etiquetas: Midjourney composición visual espacio negativo AI generativa transferencia de estilo

Publicado el 8-31 18:44