Source code for agentlego.tools.image_pose.pose_to_image
from typing import Tuple
from PIL import Image
from agentlego.types import Annotated, ImageIO, Info
from agentlego.utils import require
from ..base import BaseTool
from ..utils.diffusers import load_sd, load_sdxl
[docs]class PoseToImage(BaseTool):
"""A tool to generate image according to a human pose image.
Args:
model (str): The pose controlnet model to use. You can choose
from "sd" and "sdxl". Defaults to "sd".
device (str): The device to load the model. Defaults to 'cuda'.
toolmeta (None | dict | ToolMeta): The additional info of the tool.
Defaults to None.
"""
default_desc = ('This tool can generate an image from a human pose '
'image and a text.')
@require('diffusers')
def __init__(self, model: str = 'sd', device: str = 'cuda', toolmeta=None):
super().__init__(toolmeta=toolmeta)
assert model in ['sd', 'sdxl']
self.model = model
self.device = device
def setup(self):
if self.model == 'sdxl':
self.pipe = load_sdxl(
controlnet='thibaud/controlnet-openpose-sdxl-1.0',
device=self.device,
)
self.canvas_size = 1024
elif self.model == 'sd':
self.pipe = load_sd(
controlnet='lllyasviel/sd-controlnet-openpose',
device=self.device,
)
self.canvas_size = 512
self.a_prompt = 'best quality, extremely detailed'
self.n_prompt = 'longbody, lowres, bad anatomy, bad hands, '\
' missing fingers, extra digit, fewer digits, '\
'cropped, worst quality, low quality'
def apply(
self,
image: ImageIO,
keywords: Annotated[str,
Info('A series of English keywords separated by comma.')],
) -> ImageIO:
text = f'{keywords}, {self.a_prompt}'
width, height = self.get_image_size(image.to_pil(), canvas_size=self.canvas_size)
image = self.pipe(
text,
image=image.to_pil(),
negative_prompt=self.n_prompt,
width=width,
height=height,
).images[0]
return ImageIO(image)
@staticmethod
def get_image_size(image: Image.Image, canvas_size=512) -> Tuple[int, int]:
# The sd canvas size must can be divided by 8.
aspect_ratio = image.width / image.height
width = int((canvas_size * canvas_size * aspect_ratio)**0.5)
height = int(width / aspect_ratio)
width = width - (width % 8)
height = height - (height % 8)
return width, height