ControlNet для управления композицией изображений
ControlNet добавляет условия управления к Stable Diffusion: поза человека, глубина сцены, контуры объектов, карта нормалей, сегментационная маска. Генерация следует заданной структуре при полной свободе стиля по промпту.
Доступные модели ControlNet
| Тип | Входные данные | Применение |
|---|---|---|
| Canny | Границы Canny | Сохранение структуры/контуров |
| Depth | Карта глубины (MiDaS) | 3D расположение объектов |
| OpenPose | Скелет фигуры (18 точек) | Позы людей |
| SoftEdge | Мягкие контуры (HED) | Мягкая стилизация |
| Scribble | Набросок | Генерация из скетча |
| Segmentation | Семантическая карта | Контроль объектов сцены |
| Normal Map | Карта нормалей | Детализированные поверхности |
| IP-Adapter | Референс-изображение | Перенос стиля/содержания |
Интеграция через diffusers
from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel
from diffusers.utils import load_image
import torch
import cv2
import numpy as np
from PIL import Image
import io
class ControlNetService:
def __init__(self, controlnet_type: str = "canny"):
model_map = {
"canny": "diffusers/controlnet-canny-sdxl-1.0",
"depth": "diffusers/controlnet-depth-sdxl-1.0",
"openpose": "thibaud/controlnet-openpose-sdxl-1.0",
}
controlnet = ControlNetModel.from_pretrained(
model_map[controlnet_type],
torch_dtype=torch.float16
)
self.pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
controlnet=controlnet,
torch_dtype=torch.float16
).to("cuda")
def generate_from_canny(
self,
input_image: bytes,
prompt: str,
negative_prompt: str = "low quality, blurry",
controlnet_strength: float = 0.8,
steps: int = 30
) -> bytes:
img = Image.open(io.BytesIO(input_image)).convert("RGB")
img_np = np.array(img)
# Canny edge detection
gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
edges = cv2.Canny(gray, threshold1=100, threshold2=200)
control_image = Image.fromarray(edges)
result = self.pipe(
prompt=prompt,
negative_prompt=negative_prompt,
image=control_image,
controlnet_conditioning_scale=controlnet_strength,
num_inference_steps=steps,
guidance_scale=8.0
).images[0]
buf = io.BytesIO()
result.save(buf, format="PNG")
return buf.getvalue()
OpenPose — генерация по позе
from controlnet_aux import OpenposeDetector
class PoseControlledGenerator:
def __init__(self):
self.pose_detector = OpenposeDetector.from_pretrained("lllyasviel/Annotators")
self.controlnet_service = ControlNetService("openpose")
def generate_from_pose(
self,
pose_reference: bytes, # Фото человека как референс позы
prompt: str,
style: str = "photorealistic"
) -> bytes:
ref_image = Image.open(io.BytesIO(pose_reference)).convert("RGB")
# Извлекаем скелет из референса
pose_map = self.pose_detector(ref_image, hand_and_face=True)
result = self.controlnet_service.pipe(
prompt=f"{prompt}, {style}",
image=pose_map,
controlnet_conditioning_scale=1.0,
num_inference_steps=30
).images[0]
buf = io.BytesIO()
result.save(buf, format="PNG")
return buf.getvalue()
Multi-ControlNet (несколько условий)
from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel
# Canny + Depth одновременно
controlnets = [
ControlNetModel.from_pretrained("diffusers/controlnet-canny-sdxl-1.0", torch_dtype=torch.float16),
ControlNetModel.from_pretrained("diffusers/controlnet-depth-sdxl-1.0", torch_dtype=torch.float16)
]
pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
controlnet=controlnets,
torch_dtype=torch.float16
).to("cuda")
result = pipe(
prompt="interior design, modern living room, photorealistic",
image=[canny_image, depth_image],
controlnet_conditioning_scale=[0.7, 0.5], # Веса каждого условия
num_inference_steps=30
).images[0]
Практические применения
Архитектурная визуализация: ControlNet Depth + Canny из чертежа → фотореалистичный рендер в указанном стиле.
Fashion: OpenPose модели → генерация одежды на заданной позе без смены телосложения.
Дизайн продукции: SoftEdge скетча → несколько цветовых вариаций продукта.
Переосмысление бренда: Scribble набросок логотипа → полноцветный финальный вариант.
Сроки: ControlNet API с одним типом условия — 2–3 дня. Сервис с несколькими типами и веб-интерфейсом — 1–2 недели.







