Skip to content

Commit ae9dba9

Browse files
committed
Changes to be committed:
modified: ppdiffusers/examples/controlnet/README.md new file: ppdiffusers/examples/controlnet/annotator/shuffle/__init__.py modified: ppdiffusers/examples/controlnet/annotator/util.py renamed: ppdiffusers/examples/controlnet/gradio_mlsd2image.py -> ppdiffusers/examples/controlnet/gradio_shuffle2image.py
1 parent dbb3784 commit ae9dba9

File tree

4 files changed

+128
-23
lines changed

4 files changed

+128
-23
lines changed

ppdiffusers/examples/controlnet/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ python gradio_ip2p2image.py
7575
```
7676
![image](https://github.com/Submerge-Gu/Images/raw/main/4.png)
7777

78-
## MLSD to Image
79-
(ControlNet V1.1) 在原基础上进行升级,采用HoughLine检测图片作为控制条件
78+
## Shuffle to Image
79+
(ControlNet V1.1) Shuffle打乱图像进行重构。
8080
```
81-
python gradio_mlsd2image.py
81+
python gradio_shuffle2image.py
8282
```
83-
![image](https://github.com/Submerge-Gu/Images/raw/main/8.png)
83+
![image](https://github.com/Submerge-Gu/Images/raw/main/control.png)
8484

8585
# ControlNet模型训练
8686

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import random
16+
17+
import cv2
18+
import numpy as np
19+
from annotator.util import img2mask, make_noise_disk
20+
21+
22+
class ContentShuffleDetector:
23+
def __call__(self, img, h=None, w=None, f=None):
24+
H, W, C = img.shape
25+
if h is None:
26+
h = H
27+
if w is None:
28+
w = W
29+
if f is None:
30+
f = 256
31+
x = make_noise_disk(h, w, 1, f) * float(W - 1)
32+
y = make_noise_disk(h, w, 1, f) * float(H - 1)
33+
flow = np.concatenate([x, y], axis=2).astype(np.float32)
34+
return cv2.remap(img, flow, None, cv2.INTER_LINEAR)
35+
36+
37+
class ColorShuffleDetector:
38+
def __call__(self, img):
39+
H, W, C = img.shape
40+
F = random.randint(64, 384)
41+
A = make_noise_disk(H, W, 3, F)
42+
B = make_noise_disk(H, W, 3, F)
43+
C = (A + B) / 2.0
44+
A = (C + (A - C) * 3.0).clip(0, 1)
45+
B = (C + (B - C) * 3.0).clip(0, 1)
46+
L = img.astype(np.float32) / 255.0
47+
Y = A * L + B * (1 - L)
48+
Y -= np.min(Y, axis=(0, 1), keepdims=True)
49+
Y /= np.maximum(np.max(Y, axis=(0, 1), keepdims=True), 1e-5)
50+
Y *= 255.0
51+
return Y.clip(0, 255).astype(np.uint8)
52+
53+
54+
class GrayDetector:
55+
def __call__(self, img):
56+
eps = 1e-5
57+
X = img.astype(np.float32)
58+
r, g, b = X[:, :, 0], X[:, :, 1], X[:, :, 2]
59+
kr, kg, kb = [random.random() + eps for _ in range(3)]
60+
ks = kr + kg + kb
61+
kr /= ks
62+
kg /= ks
63+
kb /= ks
64+
Y = r * kr + g * kg + b * kb
65+
Y = np.stack([Y] * 3, axis=2)
66+
return Y.clip(0, 255).astype(np.uint8)
67+
68+
69+
class DownSampleDetector:
70+
def __call__(self, img, level=3, k=16.0):
71+
h = img.astype(np.float32)
72+
for _ in range(level):
73+
h += np.random.normal(loc=0.0, scale=k, size=h.shape)
74+
h = cv2.pyrDown(h)
75+
for _ in range(level):
76+
h = cv2.pyrUp(h)
77+
h += np.random.normal(loc=0.0, scale=k, size=h.shape)
78+
return h.clip(0, 255).astype(np.uint8)
79+
80+
81+
class Image2MaskShuffleDetector:
82+
def __init__(self, resolution=(640, 512)):
83+
self.H, self.W = resolution
84+
85+
def __call__(self, img):
86+
m = img2mask(img, self.H, self.W)
87+
m *= 255.0
88+
return m.clip(0, 255).astype(np.uint8)

ppdiffusers/examples/controlnet/annotator/util.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# limitations under the License.
1515

1616
import os
17+
import random
1718

1819
import cv2
1920
import numpy as np
@@ -51,3 +52,31 @@ def resize_image(input_image, resolution):
5152
W = int(np.round(W / 64.0)) * 64
5253
img = cv2.resize(input_image, (W, H), interpolation=cv2.INTER_LANCZOS4 if k > 1 else cv2.INTER_AREA)
5354
return img
55+
56+
57+
def make_noise_disk(H, W, C, F):
58+
noise = np.random.uniform(low=0, high=1, size=((H // F) + 2, (W // F) + 2, C))
59+
noise = cv2.resize(noise, (W + 2 * F, H + 2 * F), interpolation=cv2.INTER_CUBIC)
60+
noise = noise[F : F + H, F : F + W]
61+
noise -= np.min(noise)
62+
noise /= np.max(noise)
63+
if C == 1:
64+
noise = noise[:, :, None]
65+
return noise
66+
67+
68+
def img2mask(img, H, W, low=10, high=90):
69+
assert img.ndim == 3 or img.ndim == 2
70+
assert img.dtype == np.uint8
71+
72+
if img.ndim == 3:
73+
y = img[:, :, random.randrange(0, img.shape[2])]
74+
else:
75+
y = img
76+
77+
y = cv2.resize(y, (W, H), interpolation=cv2.INTER_CUBIC)
78+
79+
if random.uniform(0, 1) < 0.5:
80+
y = 255 - y
81+
82+
return y < np.percentile(y, random.randrange(low, high))

ppdiffusers/examples/controlnet/gradio_mlsd2image.py renamed to ppdiffusers/examples/controlnet/gradio_shuffle2image.py

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717

1818
import gradio as gr
1919
import paddle
20-
from annotator.mlsd import MLSDdetector
20+
from annotator.shuffle import ContentShuffleDetector
2121
from annotator.util import HWC3, resize_image
2222

2323
from paddlenlp.trainer import set_seed as seed_everything
2424
from ppdiffusers import ControlNetModel, StableDiffusionControlNetPipeline
2525

26-
apply_mlsd = MLSDdetector()
26+
apply_shuffle = ContentShuffleDetector()
2727

28-
controlnet = ControlNetModel.from_pretrained("lllyasviel/control_v11p_sd15_mlsd")
28+
controlnet = ControlNetModel.from_pretrained("lllyasviel/control_v11e_sd15_shuffle")
2929
pipe = StableDiffusionControlNetPipeline.from_pretrained(
3030
"runwayml/stable-diffusion-v1-5", controlnet=controlnet, safety_checker=None
3131
)
@@ -44,21 +44,16 @@ def process(
4444
scale,
4545
seed,
4646
eta,
47-
value_threshold,
48-
distance_threshold,
4947
):
5048
with paddle.no_grad():
5149
img = resize_image(HWC3(input_image), image_resolution)
5250
H, W, C = img.shape
53-
detected_map = apply_mlsd(img, value_threshold, distance_threshold)
54-
detected_map = HWC3(detected_map)
51+
detected_map = apply_shuffle(img, w=W, h=H, f=256)
5552

5653
control = paddle.to_tensor(detected_map.copy(), dtype=paddle.float32) / 255.0
5754
control = control.unsqueeze(0).transpose([0, 3, 1, 2])
5855

59-
control_scales = (
60-
[strength * (0.825 ** float(12 - i)) for i in range(13)] if guess_mode else ([strength] * 13)
61-
) # Magic number. IDK why. Perhaps because 0.825**12<0.01 but 0.826**12>0.01
56+
control_scales = [strength] * 13
6257
if seed == -1:
6358
seed = random.randint(0, 65535)
6459
seed_everything(seed)
@@ -83,7 +78,7 @@ def process(
8378
block = gr.Blocks().queue()
8479
with block:
8580
with gr.Row():
86-
gr.Markdown("## Control Stable Diffusion with MLSD Lines")
81+
gr.Markdown("## Control Stable Diffusion with Content Shuffle")
8782
with gr.Row():
8883
with gr.Column():
8984
input_image = gr.Image(source="upload", type="numpy")
@@ -94,12 +89,6 @@ def process(
9489
image_resolution = gr.Slider(label="Image Resolution", minimum=256, maximum=768, value=512, step=64)
9590
strength = gr.Slider(label="Control Strength", minimum=0.0, maximum=2.0, value=1.0, step=0.01)
9691
guess_mode = gr.Checkbox(label="Guess Mode", value=False)
97-
value_threshold = gr.Slider(
98-
label="Hough value threshold (MLSD)", minimum=0.01, maximum=2.0, value=0.1, step=0.01
99-
)
100-
distance_threshold = gr.Slider(
101-
label="Hough ditance threshold (MLSD)", minimum=0.01, maximum=20.0, value=0.1, step=0.01
102-
)
10392
ddim_steps = gr.Slider(label="Steps", minimum=1, maximum=100, value=20, step=1)
10493
scale = gr.Slider(label="Guidance Scale", minimum=0.1, maximum=30.0, value=9.0, step=0.1)
10594
seed = gr.Slider(label="Seed", minimum=-1, maximum=2147483647, step=1, randomize=True)
@@ -126,9 +115,8 @@ def process(
126115
scale,
127116
seed,
128117
eta,
129-
value_threshold,
130-
distance_threshold,
131118
]
132119
run_button.click(fn=process, inputs=ips, outputs=[result_gallery])
133120

121+
134122
block.launch(server_name="0.0.0.0", server_port=8513)

0 commit comments

Comments
 (0)