Buckets:
| # Outpainting | |
| Outpainting은 이미지의 원래 경계를 넘어 확장하여, 원본 이미지를 보존하면서 시각적 요소를 추가, 교체 또는 수정할 수 있게 합니다. [inpainting](../using-diffusers/inpaint)과 마찬가지로, 원본 이미지(검은색 픽셀의 마스크로 표현됨)를 유지하면서 흰색 영역(이 경우 원본 이미지 외부 영역)을 새로운 시각적 요소로 채우는 것이 목표입니다. [ControlNet](https://hf.co/blog/OzzyGT/outpainting-controlnet) 또는 [Differential Diffusion](https://hf.co/blog/OzzyGT/outpainting-differential-diffusion)를 사용하여 outpainting을 수행하는 방법 등이 있습니다. | |
| 이 가이드에서는 inpainting 모델, ControlNet, ZoeDepth 추정기를 사용하여 outpainting을 수행하는 방법을 보여줍니다. | |
| 시작하기 전에 ZoeDepth 추정기를 사용할 수 있도록 [controlnet_aux](https://github.com/huggingface/controlnet_aux) 라이브러리가 설치되어 있는지 확인하세요. | |
| ```py | |
| !pip install -q controlnet_aux | |
| ``` | |
| ## 이미지 준비 | |
| outpainting할 이미지를 선택하고 [BRIA-RMBG-1.4](https://hf.co/spaces/briaai/BRIA-RMBG-1.4)와 같은 Space를 사용해 배경을 제거하는 것으로 시작합니다. | |
| <iframe src="https://briaai-bria-rmbg-1-4.hf.space" frameborder="0" width="850" height="450" | |
| > | |
| 예를 들어, 이 신발 사진에서 배경을 제거합니다. | |
| 원본 이미지 | |
| 배경 제거 | |
| [Stable Diffusion XL (SDXL)](../api/pipelines/stable_diffusion/stable_diffusion_xl) 모델은 1024x1024 이미지에 최적화되어 있지만, 하드웨어에 충분한 메모리가 있다면 이미지를 원하는 크기로 리사이즈할 수 있습니다. 이미지의 투명 배경은 흰색 배경으로 교체해야 합니다. 아래와 같은 함수를 만들어 이미지를 스케일링하고 흰색 배경에 붙여넣으세요. | |
| ```py | |
| import random | |
| import requests | |
| import torch | |
| from controlnet_aux import ZoeDetector | |
| from PIL import Image, ImageOps | |
| from diffusers import ( | |
| AutoencoderKL, | |
| ControlNetModel, | |
| StableDiffusionXLControlNetPipeline, | |
| StableDiffusionXLInpaintPipeline, | |
| ) | |
| def scale_and_paste(original_image): | |
| aspect_ratio = original_image.width / original_image.height | |
| if original_image.width > original_image.height: | |
| new_width = 1024 | |
| new_height = round(new_width / aspect_ratio) | |
| else: | |
| new_height = 1024 | |
| new_width = round(new_height * aspect_ratio) | |
| resized_original = original_image.resize((new_width, new_height), Image.LANCZOS) | |
| white_background = Image.new("RGBA", (1024, 1024), "white") | |
| x = (1024 - new_width) // 2 | |
| y = (1024 - new_height) // 2 | |
| white_background.paste(resized_original, (x, y), resized_original) | |
| return resized_original, white_background | |
| original_image = Image.open( | |
| requests.get( | |
| "https://huggingface.co/datasets/stevhliu/testing-images/resolve/main/no-background-jordan.png", | |
| stream=True, | |
| ).raw | |
| ).convert("RGBA") | |
| resized_img, white_bg_image = scale_and_paste(original_image) | |
| ``` | |
| 원치 않는 추가 세부 사항이 포함되는 것을 방지하려면, ZoeDepth 추정기를 사용하여 생성 과정에서 추가적인 지침을 제공하고 신발이 원본 이미지와 일관되도록 유지하세요. | |
| ```py | |
| zoe = ZoeDetector.from_pretrained("lllyasviel/Annotators") | |
| image_zoe = zoe(white_bg_image, detect_resolution=512, image_resolution=1024) | |
| image_zoe | |
| ``` | |
| ## Outpaint | |
| 이미지가 준비되면, 인페인팅을 위해 학습된 SDXL ControlNet인 [controlnet-inpaint-dreamer-sdxl](https://hf.co/destitech/controlnet-inpaint-dreamer-sdxl)을 사용하여 신발 주변의 흰색 영역에 콘텐츠를 생성할 수 있습니다. | |
| 인페인팅용 ControlNet, ZoeDepth 모델, VAE를 로드하고 [StableDiffusionXLControlNetPipeline](/docs/diffusers/main/ko/api/pipelines/controlnet_sdxl#diffusers.StableDiffusionXLControlNetPipeline)에 전달합니다. 그런 다음 편의를 위해 초기 이미지를 아웃페인팅하는 선택적 `generate_image` 함수를 만들 수 있습니다. | |
| ```py | |
| controlnets = [ | |
| ControlNetModel.from_pretrained( | |
| "destitech/controlnet-inpaint-dreamer-sdxl", dtype=torch.float16, variant="fp16" | |
| ), | |
| ControlNetModel.from_pretrained( | |
| "diffusers/controlnet-zoe-depth-sdxl-1.0", dtype=torch.float16 | |
| ), | |
| ] | |
| vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", dtype=torch.float16).to("cuda") # or "mps", "xpu", "cpu" | |
| pipeline = StableDiffusionXLControlNetPipeline.from_pretrained( | |
| "SG161222/RealVisXL_V4.0", dtype=torch.float16, variant="fp16", controlnet=controlnets, vae=vae | |
| ).to("cuda") | |
| def generate_image(prompt, negative_prompt, inpaint_image, zoe_image, seed: int = None): | |
| if seed is None: | |
| seed = random.randint(0, 2**32 - 1) | |
| generator = torch.Generator(device="cpu").manual_seed(seed) | |
| image = pipeline( | |
| prompt, | |
| negative_prompt=negative_prompt, | |
| image=[inpaint_image, zoe_image], | |
| guidance_scale=6.5, | |
| num_inference_steps=25, | |
| generator=generator, | |
| controlnet_conditioning_scale=[0.5, 0.8], | |
| control_guidance_end=[0.9, 0.6], | |
| ).images[0] | |
| return image | |
| prompt = "nike air jordans on a basketball court" | |
| negative_prompt = "" | |
| temp_image = generate_image(prompt, negative_prompt, white_bg_image, image_zoe, 908097) | |
| ``` | |
| … | |
| ```py | |
| x = (1024 - resized_img.width) // 2 | |
| y = (1024 - resized_img.height) // 2 | |
| temp_image.paste(resized_img, (x, y), resized_img) | |
| temp_image | |
| ``` | |
| > [!TIP] | |
| > 메모리가 부족하다면 지금이 메모리를 해제할 좋은 타이밍입니다! | |
| > | |
| > ```py | |
| > pipeline=None | |
| > torch.cuda.empty_cache() | |
| > ``` | |
| 초기 outpainted 이미지를 확보했으므로, [StableDiffusionXLInpaintPipeline](/docs/diffusers/main/ko/api/pipelines/stable_diffusion/stable_diffusion_xl#diffusers.StableDiffusionXLInpaintPipeline)을 [RealVisXL](https://hf.co/SG161222/RealVisXL_V4.0) 모델과 함께 로드하여 더 높은 품질의 최종 outpainted 이미지를 생성하세요. | |
| ```py | |
| pipeline = StableDiffusionXLInpaintPipeline.from_pretrained( | |
| "OzzyGT/RealVisXL_V4.0_inpainting", | |
| dtype=torch.float16, | |
| variant="fp16", | |
| vae=vae, | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| ``` | |
| 최종 아웃페인팅된 이미지에 사용할 마스크를 준비합니다. 원본 이미지와 아웃페인팅된 배경 사이의 더 자연스러운 전환을 위해 마스크를 흐리게 처리하여 더 잘 어우러지도록 합니다. | |
| ```py | |
| mask = Image.new("L", temp_image.size) | |
| mask.paste(resized_img.split()[3], (x, y)) | |
| mask = ImageOps.invert(mask) | |
| final_mask = mask.point(lambda p: p > 128 and 255) | |
| mask_blurred = pipeline.mask_processor.blur(final_mask, blur_factor=20) | |
| mask_blurred | |
| ``` | |
| 더 나은 프롬프트를 작성하여 `generate_outpaint` 함수에 전달하고 최종 아웃페인팅 이미지를 생성합니다. 다시 한 번, 원본 이미지를 최종 아웃페인팅 배경 위에 겹쳐 배치합니다. | |
| ```py | |
| def generate_outpaint(prompt, negative_prompt, image, mask, seed: int = None): | |
| if seed is None: | |
| seed = random.randint(0, 2**32 - 1) | |
| generator = torch.Generator(device="cpu").manual_seed(seed) | |
| image = pipeline( | |
| prompt, | |
| negative_prompt=negative_prompt, | |
| image=image, | |
| mask_image=mask, | |
| guidance_scale=10.0, | |
| strength=0.8, | |
| num_inference_steps=30, | |
| generator=generator, | |
| ).images[0] | |
| return image | |
| prompt = "high quality photo of nike air jordans on a basketball court, highly detailed" | |
| negative_prompt = "" | |
| final_image = generate_outpaint(prompt, negative_prompt, temp_image, mask_blurred, 7688778) | |
| x = (1024 - resized_img.width) // 2 | |
| y = (1024 - resized_img.height) // 2 | |
| final_image.paste(resized_img, (x, y), resized_img) | |
| final_image | |
| ``` | |
Xet Storage Details
- Size:
- 7.92 kB
- Xet hash:
- b07c89b44a6890c60c8d4727af4dfe08b88ced78e14dc6f4de3418a1acb9e29b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.