Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use StableDiffusionControl(XL)NetImg2ImgPipeline im Cond2ImPipe #77

Merged
merged 2 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions examples/cim2im.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
first run promp2im.py

this script expects https://huggingface.co/lllyasviel/control_v11p_sd15_softedge
to be placed in ./models-cn/control_v11p_sd15_softedge


modified versions of the input image will be placed in ./_projects/biolab/controlnet/
"""

from multigen.prompting import Cfgen
from multigen.sessions import GenSession
from multigen.pipes import Im2ImPipe, CIm2ImPipe, ModelType


model_dir = "./models-sd/"
model_id = "icbinp"

prompt = ["bioinformatics lab with flasks and exotic flowers",
"happy vibrant", "green colors", "artwork", "high tech"]

nprompt = "jpeg artifacts, blur, distortion, watermark, extra fingers, fewer fingers, lowres, bad hands, duplicate heads, bad anatomy"


pipe = CIm2ImPipe(model_dir + model_id, model_type=ModelType.SD, ctypes=['soft'])
pipe.setup("./_projects/biolab/00000.png", strength=0.6, steps=25)
gs = GenSession("./_projects/biolab/controlnet/", pipe, Cfgen(prompt, nprompt))
gs.gen_sess(add_count=10)
71 changes: 56 additions & 15 deletions multigen/pipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, UniPCMultistepScheduler, StableDiffusionXLControlNetPipeline
from diffusers import StableDiffusionControlNetInpaintPipeline, StableDiffusionXLControlNetInpaintPipeline, DDIMScheduler
from diffusers.schedulers import KarrasDiffusionSchedulers
from diffusers import StableDiffusionXLControlNetImg2ImgPipeline, StableDiffusionControlNetImg2ImgPipeline

from .pipelines.masked_stable_diffusion_img2img import MaskedStableDiffusionImg2ImgPipeline
from .pipelines.masked_stable_diffusion_xl_img2img import MaskedStableDiffusionXLImg2ImgPipeline
Expand Down Expand Up @@ -581,8 +582,8 @@ def gen(self, inputs):


class Cond2ImPipe(BasePipe):
_class = StableDiffusionControlNetPipeline
_classxl = StableDiffusionXLControlNetPipeline
_class = StableDiffusionControlNetImg2ImgPipeline
_classxl = StableDiffusionXLControlNetImg2ImgPipeline
_autopipeline = DiffusionPipeline

# TODO: set path
Expand Down Expand Up @@ -708,7 +709,7 @@ def get_cpath(self):
return cpath

def setup(self, fimage, width=None, height=None,
image=None, cscales=None, guess_mode=False, **args):
image=None, cscales=None, guess_mode=False, strength=1, **args):
"""
Set up the pipeline with the given parameters.

Expand All @@ -723,23 +724,27 @@ def setup(self, fimage, width=None, height=None,
The input image. Defaults to None. fimage should be None if this argument is provided.
cscales (list, optional):
The list of conditioning scales. Defaults to None.
guess_mode (bool, optional):
guess_mode (bool, *optional*):
Whether to use guess mode. Defaults to False.
it enables image generation without text prompt.
strength (float, *optional*):
Strength image modification. Defaults to 1. A lower strength values keep result close to the input image. value of 1 means input image more or less ignored.
**args: Additional arguments for the pipeline setup.
"""
super().setup(**args)
# TODO: allow multiple input images for multiple control nets
self.fname = fimage
image = Image.open(fimage) if image is None else image
self._condition_image = [image]
self._input_image = [image]
if cscales is None:
cscales = [self.get_default_cond_scales()[c] for c in self.ctypes]
self.pipe_params.update({
"width": image.size[0] if width is None else width,
"height": image.size[1] if height is None else height,
"controlnet_conditioning_scale": cscales,
"guess_mode": guess_mode,
"strength": strength,
})

def get_default_cond_scales(self):
Expand Down Expand Up @@ -772,7 +777,8 @@ def gen(self, inputs):
"""
inputs = self.prepare_inputs(inputs)
inputs.update(self.pipe_params)
inputs.update({"image": self._condition_image})
inputs.update({"image": self._input_image,
"control_image": self._condition_image})
image = self.pipe(**inputs).images[0]
return image

Expand Down Expand Up @@ -801,24 +807,59 @@ def __init__(self, model_id, pipe: Optional[StableDiffusionControlNetPipeline] =
Additional arguments passed to the Cond2ImPipe constructor.
"""
super().__init__(model_id=model_id, pipe=pipe, ctypes=ctypes, model_type=model_type, **args)
self.processor = None
self.body_estimation = None
self.draw_bodypose = None
self.dprocessor = None
self.dmodel = None
for c in self.ctypes:
self.load_processor(c)

if "soft" in ctypes:
def load_processor(self, ctype):
if "soft" == ctype:
from controlnet_aux import PidiNetDetector, HEDdetector
self.processor = HEDdetector.from_pretrained('lllyasviel/Annotators')
if self.processor is None:
self.processor = HEDdetector.from_pretrained('lllyasviel/Annotators')
#processor = PidiNetDetector.from_pretrained('lllyasviel/Annotators')
if "pose" in ctypes:
if "pose" == ctype:
from pytorch_openpose.src.body import Body
from pytorch_openpose.src import util
self.body_estimation = Body('pytorch_openpose/model/body_pose_model.pth')
self.draw_bodypose = util.draw_bodypose
if self.body_estimation is None:
self.body_estimation = Body('pytorch_openpose/model/body_pose_model.pth')
self.draw_bodypose = util.draw_bodypose
#hand_estimation = Hand('model/hand_pose_model.pth')
if "depth" in ctypes:
if "depth" == ctype:
from transformers import DPTImageProcessor, DPTForDepthEstimation
self.dprocessor = DPTImageProcessor.from_pretrained("./models-other/dpt-large")
self.dmodel = DPTForDepthEstimation.from_pretrained("./models-other/dpt-large")
if self.dprocessor is None:
self.dprocessor = DPTImageProcessor.from_pretrained("./models-other/dpt-large")
self.dmodel = DPTForDepthEstimation.from_pretrained("./models-other/dpt-large")

def setup(self, fimage, width=None, height=None, image=None,
cscales=None, guess_mode=False, strength=0.75, **args):
"""
Set up the pipeline with the given parameters.

def setup(self, fimage, width=None, height=None, image=None, cscales=None, guess_mode=False, **args):
super().setup(fimage, width, height, image, cscales, guess_mode, **args)
Args:
fimage (str):
The path to the input image file.
width (int, *optional*):
The width of the generated image. Defaults to the width of the input image.
height (int, *optional*):
The height of the generated image. Defaults to the height of the input image.
image (PIL.Image.Image, *optional*):
The input image. Defaults to None. fimage should be None if this argument is provided.
cscales (list, optional):
The list of conditioning scales. Defaults to None.
guess_mode (bool, *optional*):
Whether to use guess mode. Defaults to False.
it enables image generation without text prompt.
strength (float, *optional*):
Strength image modification. Defaults to 0.75. A lower strength values keep result close to the input image. value of 1 means input image more or less ignored.
**args: Additional arguments for the pipeline setup.
"""
super().setup(fimage, width, height, image, cscales, guess_mode, strength=strength, **args)
if 'ctypes' in args:
raise RuntimeError("ctypes can be used only in constructor")
# Additionally process the input image
# REM: CIm2ImPipe expects only one image, which can be the base for multiple control images
self._condition_image = self._proc_cimg(np.asarray(self._condition_image[0]))
Expand Down
Loading