aptol commited on
Commit
de1e7d9
·
verified ·
1 Parent(s): 2227290

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -43
app.py CHANGED
@@ -222,6 +222,26 @@ SPACES: Dict[str, Dict[str, Any]] = {
222
  # ---------------------------------
223
  # Utility
224
  # ---------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  def _save_png(img: Image.Image, path: Union[str,Path]) -> str:
226
  p = Path(path); p.parent.mkdir(parents=True, exist_ok=True); img.save(p); return str(p)
227
 
@@ -635,50 +655,47 @@ def step1_gpu_refine(
635
 
636
  # ---- T-포즈 (ControlNet/OpenPose)
637
  if enforce_tpose:
638
- try:
639
- from diffusers import ControlNetModel, StableDiffusionControlNetImg2ImgPipeline, EulerAncestralDiscreteScheduler
640
-
641
- controlnet = ControlNetModel.from_pretrained(
642
- "lllyasviel/control_v11p_sd15_openpose", torch_dtype=dtype
643
- )
644
- pipe_pose = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
645
- "runwayml/stable-diffusion-v1-5",
646
- controlnet=controlnet,
647
- torch_dtype=dtype
648
- )
649
- # 안정 스케줄러
650
- try:
651
- pipe_pose.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe_pose.scheduler.config)
652
- except Exception:
653
- pass
654
- if dev == "cuda":
655
- pipe_pose.to("cuda")
656
-
657
- img_rgb = _resize_to_multiple(img.convert("RGB"), multiple=8, max_side=512)
658
- pose_canvas = _make_tpose_canvas_like(img_rgb).resize(img_rgb.size)
659
- pose_canvas.save(OUT/"step1"/"dbg_02_pose_canvas.png")
660
-
661
- POS = "T-pose, full body, same outfit, same colors, clean anime lines, consistent scale, white background"
662
- NEG = "extra limbs, deformed hands, melted face, disfigured, distorted body, artifacts, blurry, noisy, watermark, text"
663
-
664
- out = pipe_pose(
665
- prompt=POS,
666
- negative_prompt=NEG,
667
- image=img_rgb,
668
- control_image=pose_canvas,
669
- strength=float(tpose_strength),
670
- guidance_scale=float(tpose_guidance),
671
- num_inference_steps=int(tpose_steps),
672
- controlnet_conditioning_scale=0.45,
673
- control_guidance_start=[0.0],
674
- control_guidance_end=[0.6],
675
- ).images[0]
676
-
677
- img = out.convert("RGBA")
678
  img.save(OUT/"step1"/"dbg_03_after_tpose.png")
679
- logs.append("ControlNet(OpenPose) T-포즈 적용(안정화 설정)")
680
- except Exception as e:
681
- logs.append(f"T-포즈 ControlNet 실패: {e}")
682
 
683
  # ---- (옵션) 리드로우(img2img)
684
  if do_redraw_flag:
 
222
  # ---------------------------------
223
  # Utility
224
  # ---------------------------------
225
+ def _openpose_canvas_from_image(img_rgb: Image.Image) -> Image.Image:
226
+ try:
227
+ if PKG.get("OpenposeDetector") is None:
228
+ return Image.new("RGB", img_rgb.size, "black")
229
+ det = PKG["OpenposeDetector"]()
230
+ pose = det(img_rgb)
231
+ return pose.convert("RGB").resize(img_rgb.size)
232
+ except Exception:
233
+ return Image.new("RGB", img_rgb.size, "black")
234
+
235
+ def _blend_pose_canvases(orig_pose: Image.Image, tpose: Image.Image, alpha: float = 0.4) -> Image.Image:
236
+ alpha = max(0.0, min(1.0, float(alpha)))
237
+ if orig_pose.size != tpose.size:
238
+ tpose = tpose.resize(orig_pose.size)
239
+ return Image.blend(orig_pose, tpose, alpha).convert("RGB")
240
+
241
+ def _mean_brightness(img: Image.Image) -> float:
242
+ import numpy as np
243
+ return float(np.asarray(img.convert("L"), dtype=np.uint8).mean())
244
+
245
  def _save_png(img: Image.Image, path: Union[str,Path]) -> str:
246
  p = Path(path); p.parent.mkdir(parents=True, exist_ok=True); img.save(p); return str(p)
247
 
 
655
 
656
  # ---- T-포즈 (ControlNet/OpenPose)
657
  if enforce_tpose:
658
+ from diffusers import ControlNetModel, StableDiffusionControlNetImg2ImgPipeline, EulerAncestralDiscreteScheduler
659
+ import torch
660
+ dev = "cuda" if torch.cuda.is_available() else "cpu"
661
+ dtype = torch.float16 if dev == "cuda" else torch.float32
662
+
663
+ controlnet = ControlNetModel.from_pretrained("lllyasviel/control_v11p_sd15_openpose", torch_dtype=dtype)
664
+ pipe_pose = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
665
+ "runwayml/stable-diffusion-v1-5", controlnet=controlnet, torch_dtype=dtype
666
+ )
667
+ try: pipe_pose.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe_pose.scheduler.config)
668
+ except: pass
669
+ if dev == "cuda": pipe_pose.to("cuda")
670
+
671
+ img_rgb = _resize_to_multiple(img.convert("RGB"), multiple=8, max_side=512)
672
+ pose_orig = _openpose_canvas_from_image(img_rgb)
673
+ pose_tpose = _draw_tpose_openpose_canvas(size=min(img_rgb.size)) # 기존 T-포즈 가이드
674
+ pose_canvas= _blend_pose_canvases(pose_orig, pose_tpose, alpha=0.4)
675
+
676
+ out = pipe_pose(
677
+ prompt="T-pose tendency, full body, same outfit and colors, clean anime lines, plain light background",
678
+ negative_prompt="extra limbs, deformed, melted face, distorted body, watermark, text, noisy",
679
+ image=img_rgb,
680
+ control_image=pose_canvas,
681
+ strength=float(tpose_strength), # (클램프됨)
682
+ guidance_scale=float(tpose_guidance),
683
+ num_inference_steps=int(tpose_steps),
684
+ controlnet_conditioning_scale=0.30, # ★ 낮춤
685
+ control_guidance_start=[0.0],
686
+ control_guidance_end=[0.50], # ★ 중반까지만
687
+ guess_mode=True # ★ 배경/미세영역 과제어 방지
688
+ ).images[0]
689
+
690
+ img = out.convert("RGBA")
691
+ if _mean_brightness(img) < 12:
692
+ logs.append("T-포즈 결과가 너무 어두움 → 원본으로 롤백")
693
+ img = Image.open(s1_path).convert("RGBA")
694
+ else:
695
+ (OUT/"step1"/"dbg_pose_orig.png").write_bytes(pose_orig.tobytes()) if False else None
 
 
696
  img.save(OUT/"step1"/"dbg_03_after_tpose.png")
697
+ logs.append("ControlNet(OpenPose) T-포즈(블렌드) 적용")
698
+
 
699
 
700
  # ---- (옵션) 리드로우(img2img)
701
  if do_redraw_flag: