Spaces:
Paused
Paused
P01yH3dr0n
commited on
Commit
•
05346f6
1
Parent(s):
201a961
director tools and send jump
Browse files- app.py +57 -43
- director_tools.py +98 -0
- images_history.py +9 -5
- utils.py +43 -8
app.py
CHANGED
@@ -8,20 +8,14 @@ from huggingface_hub import HfApi, snapshot_download
|
|
8 |
|
9 |
from pnginfo import read_info_from_image, send_paras
|
10 |
from images_history import img_history_ui
|
|
|
11 |
from utils import set_token, generate_novelai_image, image_from_bytes, get_remain_anlas, calculate_cost
|
12 |
|
13 |
client_config = toml.load("config.toml")['client']
|
14 |
today_count = 0
|
15 |
-
anlas = -1
|
16 |
today = datetime.date.today().strftime('%Y-%m-%d')
|
17 |
api = HfApi()
|
18 |
|
19 |
-
def refresh_anlas():
|
20 |
-
global anlas
|
21 |
-
set_token(os.environ.get('token'))
|
22 |
-
anlas = get_remain_anlas()
|
23 |
-
return anlas
|
24 |
-
|
25 |
def get_count():
|
26 |
global today_count, today
|
27 |
now = datetime.date.today().strftime('%Y-%m-%d')
|
@@ -61,7 +55,7 @@ def control_ui():
|
|
61 |
height = gr.Slider(label="高度", value=1024, minimum=64, maximum=2048, step=64)
|
62 |
with gr.Row():
|
63 |
with gr.Column():
|
64 |
-
with gr.Accordion('风格迁移', open=False):
|
65 |
ref_images = gr.Gallery(label="上传单(多)张图片", format="png", value=None, interactive=True, type="pil", show_share_button=False)
|
66 |
info_extracts = gr.State([])
|
67 |
ref_strs = gr.State([])
|
@@ -85,13 +79,13 @@ def control_ui():
|
|
85 |
s.change(fn=dynparas, inputs=strs, outputs=ref_strs)
|
86 |
ref_images.change(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
|
87 |
ref_images.upload(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
|
88 |
-
with gr.Accordion('附加输入', open=False):
|
89 |
-
with gr.Tab('图生图') as i2i:
|
90 |
i2i_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
|
91 |
i2i_str = gr.Slider(label='去噪强度', value=0.7, minimum=0, maximum=0.99, step=0.01)
|
92 |
i2i_noise = gr.Slider(label='噪声', value=0, minimum=0, maximum=1, step=0.1)
|
93 |
reuse_img_i2i = gr.Button(value='使用上一次生成的图片')
|
94 |
-
with gr.Tab('局部重绘') as inp:
|
95 |
overlay = gr.Checkbox(label='覆盖原图', value=True)
|
96 |
inp_img = gr.ImageMask(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", eraser=False, transforms=None, brush=gr.Brush(colors=['#FFFFFF'], color_mode='fixed'), layers=False, show_share_button=False)
|
97 |
reuse_img_inp = gr.Button(value='使用上一次生成的图片')
|
@@ -120,7 +114,7 @@ def control_ui():
|
|
120 |
rand_seed.click(fn=lambda: -1, inputs=None, outputs=seed)
|
121 |
i2i.select(lambda: 'i2i', inputs=None, outputs=selection)
|
122 |
inp.select(lambda: 'inp', inputs=None, outputs=selection)
|
123 |
-
return gen_btn, stop_btn, [prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection], [save, rand_seed, reuse_seed, reuse_img_i2i, reuse_img_inp]
|
124 |
|
125 |
def generate(prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection):
|
126 |
global today_count
|
@@ -140,8 +134,10 @@ def generate(prompt, quality_tags, neg_prompt, seed, scale, width, height, steps
|
|
140 |
def preview_ui():
|
141 |
with gr.Blocks(css='#preview_image { height: 100%;}'):
|
142 |
image = gr.Image(format='png', elem_id='preview_image', interactive=False, type='filepath', show_share_button=False)
|
|
|
|
|
143 |
info = gr.JSON(value={}, label="生成信息")
|
144 |
-
return image, info
|
145 |
|
146 |
def rename_save_img(path, payload, save):
|
147 |
if path is None:
|
@@ -168,38 +164,39 @@ def update_btn_cost(w, h, s, sm, dyn, i2i_img, i2i_str, inp_img, selection):
|
|
168 |
cost = calculate_cost(w, h, s, False, False)
|
169 |
else:
|
170 |
cost = calculate_cost(w, h, s, sm, dyn)
|
171 |
-
return gr.Button(value=f"生成(
|
172 |
|
173 |
def main_ui():
|
174 |
-
with gr.Blocks()
|
175 |
with gr.Row(variant="panel"):
|
176 |
with gr.Column():
|
177 |
gen_btn, stop_btn, paras, others = control_ui()
|
178 |
with gr.Column():
|
179 |
-
image, info = preview_ui()
|
180 |
cost_list = paras[5:8] + paras[10:12] + paras[17:19] + paras[21:23]
|
181 |
for component in cost_list:
|
182 |
component.change(update_btn_cost, inputs=cost_list, outputs=gen_btn)
|
183 |
gen_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[gen_btn, stop_btn])
|
184 |
-
gen = gen_btn.click(generate, paras, [image, info], concurrency_limit=1)
|
185 |
others[2].click(lambda o, s: o if len(s) == 0 else s['parameters']['seed'], inputs=[paras[3], info], outputs=paras[3])
|
186 |
others[3].click(lambda i: i, inputs=image, outputs=paras[17])
|
187 |
others[4].click(lambda i: gr.ImageEditor(value=i), inputs=image, outputs=paras[21])
|
188 |
ren = image.change(rename_save_img, inputs=[image, info, others[0]], outputs=image, trigger_mode="once")
|
189 |
image.change(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn])
|
190 |
stop_btn.click(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn], cancels=[gen, ren])
|
191 |
-
return
|
192 |
|
193 |
def util_ui():
|
194 |
-
with gr.Blocks(
|
195 |
with gr.Row(equal_height=False):
|
196 |
with gr.Column(variant='panel'):
|
197 |
image = gr.Image(label="上传图片", sources=["upload"], interactive=True, type="pil")
|
198 |
with gr.Column(variant='panel'):
|
199 |
-
info = gr.HTML()
|
200 |
items = gr.JSON(value=None, visible=False)
|
201 |
-
png2main = gr.Button('参数发送到文生图')
|
202 |
-
|
|
|
203 |
|
204 |
def load_javascript():
|
205 |
head = ''
|
@@ -215,22 +212,40 @@ def load_javascript():
|
|
215 |
return res
|
216 |
|
217 |
gr.routes.templates.TemplateResponse = template_response
|
218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
def ui():
|
220 |
load_javascript()
|
221 |
-
|
222 |
-
with gr.Blocks(title="NAI Client", theme=gr.themes.Base(), js="() => {document.body.classList.toggle('dark');}") as website:
|
223 |
with gr.Row():
|
224 |
-
remain_anlas = gr.
|
225 |
refresh = gr.Button("🔄")
|
226 |
-
refresh.click(
|
227 |
with gr.Tabs():
|
228 |
with gr.TabItem("图片生成", elem_id="client_ui_main"):
|
229 |
-
|
|
|
|
|
230 |
with gr.TabItem("图片信息读取"):
|
231 |
-
|
232 |
with gr.TabItem("云端图片浏览") as tab:
|
233 |
-
gal2main, gal_items = img_history_ui(tab)
|
234 |
with gr.TabItem("设置"):
|
235 |
switchLightDark = gr.Button(value="切换浅色/深色模式")
|
236 |
switchLightDark.click(fn=None, js="() => {document.body.classList.toggle('dark');}")
|
@@ -238,19 +253,18 @@ def ui():
|
|
238 |
loadTagComplete.click(fn=None, js="() => {run();}")
|
239 |
clearTagCache = gr.Button(value="清除tag补全缓存")
|
240 |
clearTagCache.click(fn=None, js="() => {localStorage.clear();}")
|
241 |
-
png2main
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
image.change(read_info_from_image, inputs=image, outputs=[info, png_items])
|
254 |
return website
|
255 |
|
256 |
|
|
|
8 |
|
9 |
from pnginfo import read_info_from_image, send_paras
|
10 |
from images_history import img_history_ui
|
11 |
+
from director_tools import director_ui, send_outputs
|
12 |
from utils import set_token, generate_novelai_image, image_from_bytes, get_remain_anlas, calculate_cost
|
13 |
|
14 |
client_config = toml.load("config.toml")['client']
|
15 |
today_count = 0
|
|
|
16 |
today = datetime.date.today().strftime('%Y-%m-%d')
|
17 |
api = HfApi()
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
def get_count():
|
20 |
global today_count, today
|
21 |
now = datetime.date.today().strftime('%Y-%m-%d')
|
|
|
55 |
height = gr.Slider(label="高度", value=1024, minimum=64, maximum=2048, step=64)
|
56 |
with gr.Row():
|
57 |
with gr.Column():
|
58 |
+
with gr.Accordion('风格迁移', open=False) as vibe_tab:
|
59 |
ref_images = gr.Gallery(label="上传单(多)张图片", format="png", value=None, interactive=True, type="pil", show_share_button=False)
|
60 |
info_extracts = gr.State([])
|
61 |
ref_strs = gr.State([])
|
|
|
79 |
s.change(fn=dynparas, inputs=strs, outputs=ref_strs)
|
80 |
ref_images.change(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
|
81 |
ref_images.upload(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
|
82 |
+
with gr.Accordion('附加输入', open=False, elem_id="i2i_tab") as i2i_tab:
|
83 |
+
with gr.Tab('图生图', elem_id="i2i_block") as i2i:
|
84 |
i2i_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
|
85 |
i2i_str = gr.Slider(label='去噪强度', value=0.7, minimum=0, maximum=0.99, step=0.01)
|
86 |
i2i_noise = gr.Slider(label='噪声', value=0, minimum=0, maximum=1, step=0.1)
|
87 |
reuse_img_i2i = gr.Button(value='使用上一次生成的图片')
|
88 |
+
with gr.Tab('局部重绘', elem_id="inp_block") as inp:
|
89 |
overlay = gr.Checkbox(label='覆盖原图', value=True)
|
90 |
inp_img = gr.ImageMask(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", eraser=False, transforms=None, brush=gr.Brush(colors=['#FFFFFF'], color_mode='fixed'), layers=False, show_share_button=False)
|
91 |
reuse_img_inp = gr.Button(value='使用上一次生成的图片')
|
|
|
114 |
rand_seed.click(fn=lambda: -1, inputs=None, outputs=seed)
|
115 |
i2i.select(lambda: 'i2i', inputs=None, outputs=selection)
|
116 |
inp.select(lambda: 'inp', inputs=None, outputs=selection)
|
117 |
+
return gen_btn, stop_btn, [prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection], [save, rand_seed, reuse_seed, reuse_img_i2i, reuse_img_inp, vibe_tab, i2i_tab]
|
118 |
|
119 |
def generate(prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection):
|
120 |
global today_count
|
|
|
134 |
def preview_ui():
|
135 |
with gr.Blocks(css='#preview_image { height: 100%;}'):
|
136 |
image = gr.Image(format='png', elem_id='preview_image', interactive=False, type='filepath', show_share_button=False)
|
137 |
+
send_dtool = gr.Button(value="发送到引导工具", visible=False)
|
138 |
+
image.change(lambda i: gr.Button(visible=False) if i is None else gr.Button(visible=True), inputs=image, outputs=send_dtool)
|
139 |
info = gr.JSON(value={}, label="生成信息")
|
140 |
+
return image, info, send_dtool
|
141 |
|
142 |
def rename_save_img(path, payload, save):
|
143 |
if path is None:
|
|
|
164 |
cost = calculate_cost(w, h, s, False, False)
|
165 |
else:
|
166 |
cost = calculate_cost(w, h, s, sm, dyn)
|
167 |
+
return gr.Button(value=f"生成(预计消耗{cost}点数)")
|
168 |
|
169 |
def main_ui():
|
170 |
+
with gr.Blocks():
|
171 |
with gr.Row(variant="panel"):
|
172 |
with gr.Column():
|
173 |
gen_btn, stop_btn, paras, others = control_ui()
|
174 |
with gr.Column():
|
175 |
+
image, info, send_dtool = preview_ui()
|
176 |
cost_list = paras[5:8] + paras[10:12] + paras[17:19] + paras[21:23]
|
177 |
for component in cost_list:
|
178 |
component.change(update_btn_cost, inputs=cost_list, outputs=gen_btn)
|
179 |
gen_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[gen_btn, stop_btn])
|
180 |
+
gen = gen_btn.click(generate, paras, [image, info], concurrency_limit=1, concurrency_id="generate")
|
181 |
others[2].click(lambda o, s: o if len(s) == 0 else s['parameters']['seed'], inputs=[paras[3], info], outputs=paras[3])
|
182 |
others[3].click(lambda i: i, inputs=image, outputs=paras[17])
|
183 |
others[4].click(lambda i: gr.ImageEditor(value=i), inputs=image, outputs=paras[21])
|
184 |
ren = image.change(rename_save_img, inputs=[image, info, others[0]], outputs=image, trigger_mode="once")
|
185 |
image.change(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn])
|
186 |
stop_btn.click(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn], cancels=[gen, ren])
|
187 |
+
return image, paras, others, send_dtool
|
188 |
|
189 |
def util_ui():
|
190 |
+
with gr.Blocks():
|
191 |
with gr.Row(equal_height=False):
|
192 |
with gr.Column(variant='panel'):
|
193 |
image = gr.Image(label="上传图片", sources=["upload"], interactive=True, type="pil")
|
194 |
with gr.Column(variant='panel'):
|
195 |
+
info = gr.HTML('')
|
196 |
items = gr.JSON(value=None, visible=False)
|
197 |
+
png2main = gr.Button('参数发送到文生图', visible=False)
|
198 |
+
items.change(lambda i: gr.Button(visible=False) if i is None else gr.Button(visible=True), inputs=items, outputs=png2main)
|
199 |
+
return png2main, items, info, image
|
200 |
|
201 |
def load_javascript():
|
202 |
head = ''
|
|
|
212 |
return res
|
213 |
|
214 |
gr.routes.templates.TemplateResponse = template_response
|
215 |
+
|
216 |
+
def send_and_jump(component, fn, inputs, outputs, tab, trigger):
|
217 |
+
component.click(fn, inputs=inputs, outputs=outputs)
|
218 |
+
component.click(fn=None,
|
219 |
+
js="(x) => { if (x !== null && x != 0) document.getElementById('" + tab + "-button').click(); return null; }",
|
220 |
+
inputs=trigger)
|
221 |
+
|
222 |
+
def send_jump_select(component, fn, inputs, outputs, tab, accordin, trigger, secondary=None):
|
223 |
+
component.click(fn, inputs=inputs, outputs=outputs)
|
224 |
+
extra_js = ''
|
225 |
+
if secondary is not None:
|
226 |
+
extra_js = "document.getElementById('" + secondary + "-button').click();"
|
227 |
+
component.click(fn=None,
|
228 |
+
js="(x) => { if (x !== null && x != 0) document.getElementById('" + tab + "-button').click();" + extra_js + " return null; }",
|
229 |
+
inputs=trigger)
|
230 |
+
component.click(lambda x: gr.Accordion(open=True) if x else gr.Accordion(), inputs=trigger, outputs=accordin)
|
231 |
+
|
232 |
def ui():
|
233 |
load_javascript()
|
234 |
+
set_token(os.environ.get('token'))
|
235 |
+
with gr.Blocks(title="NAI Client", theme=gr.themes.Base(), js="() => {document.body.classList.toggle('dark', true);}") as website:
|
236 |
with gr.Row():
|
237 |
+
remain_anlas = gr.Textbox(label="剩余点数", value=get_remain_anlas, scale=3)
|
238 |
refresh = gr.Button("🔄")
|
239 |
+
refresh.click(get_remain_anlas, inputs=None, outputs=remain_anlas)
|
240 |
with gr.Tabs():
|
241 |
with gr.TabItem("图片生成", elem_id="client_ui_main"):
|
242 |
+
image, paras, others, send_dtool = main_ui()
|
243 |
+
with gr.TabItem("引导工具", elem_id="client_ui_dtool"):
|
244 |
+
from_t2i, send_i2i, send_inp, send_vib, in_image, out_image, d_index = director_ui()
|
245 |
with gr.TabItem("图片信息读取"):
|
246 |
+
png2main, png_items, info, read_image = util_ui()
|
247 |
with gr.TabItem("云端图片浏览") as tab:
|
248 |
+
gallery, h_index, gal2main, gal_items, history2ref, history2i2i, history2inp, history2dtl = img_history_ui(tab)
|
249 |
with gr.TabItem("设置"):
|
250 |
switchLightDark = gr.Button(value="切换浅色/深色模式")
|
251 |
switchLightDark.click(fn=None, js="() => {document.body.classList.toggle('dark');}")
|
|
|
253 |
loadTagComplete.click(fn=None, js="() => {run();}")
|
254 |
clearTagCache = gr.Button(value="清除tag补全缓存")
|
255 |
clearTagCache.click(fn=None, js="() => {localStorage.clear();}")
|
256 |
+
send_and_jump(png2main, send_paras, [png_items] + paras[:14], paras[:14], "client_ui_main", read_image)
|
257 |
+
send_and_jump(gal2main, send_paras, [gal_items] + paras[:14], paras[:14], "client_ui_main", gal_items)
|
258 |
+
from_t2i.click(lambda x: x, inputs=image, outputs=in_image)
|
259 |
+
send_jump_select(send_i2i, send_outputs, [out_image, d_index], paras[17], "client_ui_main", others[6], out_image, "i2i_block")
|
260 |
+
send_jump_select(send_inp, send_outputs, [out_image, d_index], paras[21], "client_ui_main", others[6], out_image, "inp_block")
|
261 |
+
send_jump_select(send_vib, (lambda l, i: l if i == -1 else [l[i]]), [out_image, d_index], paras[14], "client_ui_main", others[5], out_image)
|
262 |
+
send_and_jump(send_dtool, (lambda x: x), image, in_image, "client_ui_dtool", image)
|
263 |
+
send_jump_select(history2i2i, send_outputs, [gallery, h_index], paras[17], "client_ui_main", others[6], gal_items, "i2i_block")
|
264 |
+
send_jump_select(history2inp, send_outputs, [gallery, h_index], paras[21], "client_ui_main", others[6], gal_items, "inp_block")
|
265 |
+
send_jump_select(history2ref, (lambda l, i: None if i == -1 else [l[i]]), [gallery, h_index], paras[14], "client_ui_main", others[5], gal_items)
|
266 |
+
send_and_jump(history2dtl, send_outputs, [gallery, h_index], in_image, "client_ui_dtool", gal_items)
|
267 |
+
read_image.change(read_info_from_image, inputs=read_image, outputs=[info, png_items])
|
|
|
268 |
return website
|
269 |
|
270 |
|
director_tools.py
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from utils import calculate_cost, augment_image
|
3 |
+
|
4 |
+
def update_btn_cost(w, h, req_type, selection, l=''):
|
5 |
+
if selection == 'scale':
|
6 |
+
after = l.split()[-1]
|
7 |
+
w, h = map(int, after.split('x'))
|
8 |
+
cost = calculate_cost(w, h, rmbg=(req_type == "移除背景"))
|
9 |
+
return gr.Button(value=f"生成(预计消耗{cost}点数)")
|
10 |
+
|
11 |
+
def getWH(img, w, h, f):
|
12 |
+
if img is None:
|
13 |
+
return w, h, ''
|
14 |
+
w, h = img.width, img.height
|
15 |
+
l = f"{w}x{h} -> {int(w * f)}x{int(h * f)}"
|
16 |
+
return w, h, l
|
17 |
+
|
18 |
+
def refresh_hint(l, f):
|
19 |
+
if len(l) == 0:
|
20 |
+
return ''
|
21 |
+
before = l.split()[0]
|
22 |
+
w, h = map(int, before.split('x'))
|
23 |
+
l = f"{w}x{h} -> {int(w * f)}x{int(h * f)}"
|
24 |
+
return l
|
25 |
+
|
26 |
+
def set_index(evt: gr.SelectData):
|
27 |
+
return evt.index
|
28 |
+
|
29 |
+
def send_outputs(imgs, index):
|
30 |
+
if imgs is None or len(imgs) == 0:
|
31 |
+
return None
|
32 |
+
elif len(imgs) == 1:
|
33 |
+
return imgs[0][0]
|
34 |
+
elif index >= 0:
|
35 |
+
return imgs[index][0]
|
36 |
+
else:
|
37 |
+
return None
|
38 |
+
|
39 |
+
def director_ui():
|
40 |
+
with gr.Row():
|
41 |
+
with gr.Column():
|
42 |
+
input_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
|
43 |
+
with gr.Row():
|
44 |
+
from_t2i = gr.Button("使用文生图上一次生成的图片")
|
45 |
+
from_out = gr.Button("使用右侧生成的图片")
|
46 |
+
with gr.Column():
|
47 |
+
output_image = gr.Gallery(format='png', interactive=False, preview=True, show_share_button=False)
|
48 |
+
selected_index = gr.Number(value=-1, visible=False)
|
49 |
+
with gr.Row():
|
50 |
+
send_i2i = gr.Button("发送到图生图")
|
51 |
+
send_inp = gr.Button("发送到局部重绘")
|
52 |
+
send_vib = gr.Button("发送到风格迁移")
|
53 |
+
req_type = gr.Radio(["移除背景", "素描", "线稿", "上色", "更改表情", "去聊天框"], value="线稿", label="功能选择")
|
54 |
+
with gr.Tab("自由调整") as resize:
|
55 |
+
width = gr.Slider(label="调整宽度", value=1024, minimum=1, maximum=2048, step=1)
|
56 |
+
height = gr.Slider(label="调整高度", value=1024, minimum=1, maximum=2048, step=1)
|
57 |
+
with gr.Tab("等比例缩放") as scale:
|
58 |
+
hint = gr.HTML('', show_label=False)
|
59 |
+
factor = gr.Slider(label="缩放比例", minimum=0.1, maximum=2, step=0.1)
|
60 |
+
defry = gr.State(0)
|
61 |
+
prompt = gr.State('')
|
62 |
+
selection = gr.Radio(["resize", "scale"], visible=False)
|
63 |
+
resize.select(lambda: 'resize', inputs=None, outputs=selection)
|
64 |
+
scale.select(lambda: 'scale', inputs=None, outputs=selection)
|
65 |
+
@gr.render(inputs=req_type)
|
66 |
+
def extra_paras(r):
|
67 |
+
if r == "上色":
|
68 |
+
with gr.Row():
|
69 |
+
strength = gr.Radio(choices=range(6), value=0, label="强度")
|
70 |
+
text = gr.Textbox(label="提示词(可选)", value='')
|
71 |
+
strength.change(lambda x: x, inputs=strength, outputs=defry)
|
72 |
+
text.change(lambda x: x, inputs=text, outputs=prompt)
|
73 |
+
elif r == "更改表情":
|
74 |
+
with gr.Row():
|
75 |
+
emotion = gr.Dropdown(choices=["neutral", "happy", "sad", "angry", "scared", "surprised", "tired", "excited", "nervous", "thinking", "confused", "shy", "disgusted", "smug", "bored", "laughing", "irritated", "aroused", "embarrassed", "worried", "love", "determined", "hurt", "playful"], value="neutral", label="表情")
|
76 |
+
strength = gr.Dropdown(choices=["正常", "偏弱", "弱", "更弱", "很弱", "最弱"], value="正常", label="强度")
|
77 |
+
text = gr.Textbox(label="提示词(可选)", value='')
|
78 |
+
emotion.change(lambda e, t: f"{e};;{t}", inputs=[emotion, text], outputs=prompt)
|
79 |
+
text.change(lambda e, t: f"{e};;{t}", inputs=[emotion, text], outputs=prompt)
|
80 |
+
strength.change(lambda s: {"正常": 0, "偏弱": 1, "弱": 2, "更弱": 3, "很弱": 4, "最弱": 5}[s], inputs=strength, outputs=defry)
|
81 |
+
else:
|
82 |
+
return
|
83 |
+
output_image.select(set_index, inputs=None, outputs=selected_index)
|
84 |
+
from_out.click(send_outputs, inputs=[output_image, selected_index], outputs=input_image)
|
85 |
+
req_type.change(lambda r: "neutral;;" if r == "更改表情" else '', inputs=req_type, outputs=prompt)
|
86 |
+
input_image.change(getWH, inputs=[input_image, width, height, factor], outputs=[width, height, hint])
|
87 |
+
factor.change(refresh_hint, inputs=[hint, factor], outputs=[hint])
|
88 |
+
tool_btn = gr.Button(value="生成", variant="primary")
|
89 |
+
dtool_stop = gr.Button(value="取消", variant="stop", visible=False)
|
90 |
+
tool_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[tool_btn, dtool_stop])
|
91 |
+
dtool_gen = tool_btn.click(augment_image, inputs=[input_image, width, height, req_type, selection, factor, defry, prompt], outputs=output_image, concurrency_id="generate")
|
92 |
+
dtool_stop.click(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[tool_btn, dtool_stop], cancels=[dtool_gen])
|
93 |
+
width.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
|
94 |
+
height.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
|
95 |
+
req_type.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
|
96 |
+
factor.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
|
97 |
+
selection.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
|
98 |
+
return from_t2i, send_i2i, send_inp, send_vib, input_image, output_image, selected_index
|
images_history.py
CHANGED
@@ -61,14 +61,18 @@ def img_history_ui(tab):
|
|
61 |
page_index = gr.Number(value=1, label="页码", precision=0)
|
62 |
next_page = gr.Button('下一页')
|
63 |
end_page = gr.Button('末尾页')
|
64 |
-
history_gallery = gr.Gallery(show_label=False, columns=6, height=1024, show_share_button=False)
|
65 |
with gr.Column(scale=1):
|
66 |
info = gr.HTML()
|
67 |
items = gr.JSON(value=None, visible=False)
|
68 |
selected_index = gr.Number(value=-1, visible=False, precision=0)
|
69 |
with gr.Row():
|
70 |
-
send_btn = gr.Button('参数发送到文生图')
|
71 |
-
|
|
|
|
|
|
|
|
|
72 |
|
73 |
img_dir_path.change(lambda path: get_img_list(path, 1) + ('', None), inputs=img_dir_path, outputs=[history_gallery, page_index, info, items])
|
74 |
img_dir_path.blur(update_img_dir, inputs=None, outputs=img_dir_path)
|
@@ -80,5 +84,5 @@ def img_history_ui(tab):
|
|
80 |
history_gallery.select(get_img_info, inputs=None, outputs=[selected_index, info, items])
|
81 |
history_gallery.change(lambda: -1, outputs=selected_index)
|
82 |
del_btn.click(del_img, inputs=[selected_index, img_dir_path, page_index], outputs=history_gallery)
|
83 |
-
|
84 |
-
return send_btn, items
|
|
|
61 |
page_index = gr.Number(value=1, label="页码", precision=0)
|
62 |
next_page = gr.Button('下一页')
|
63 |
end_page = gr.Button('末尾页')
|
64 |
+
history_gallery = gr.Gallery(show_label=False, format='png', columns=6, height=1024, interactive=False, show_share_button=False)
|
65 |
with gr.Column(scale=1):
|
66 |
info = gr.HTML()
|
67 |
items = gr.JSON(value=None, visible=False)
|
68 |
selected_index = gr.Number(value=-1, visible=False, precision=0)
|
69 |
with gr.Row():
|
70 |
+
send_btn = gr.Button('参数发送到文生图', visible=False)
|
71 |
+
history2ref = gr.Button("图片发送到风格迁移", visible=False)
|
72 |
+
history2i2i = gr.Button("图片发送到图生图", visible=False)
|
73 |
+
history2inp = gr.Button("图片发送到局部重绘", visible=False)
|
74 |
+
history2dtl = gr.Button("图片发送到引导工具", visible=False)
|
75 |
+
del_btn = gr.Button('删除', visible=False)
|
76 |
|
77 |
img_dir_path.change(lambda path: get_img_list(path, 1) + ('', None), inputs=img_dir_path, outputs=[history_gallery, page_index, info, items])
|
78 |
img_dir_path.blur(update_img_dir, inputs=None, outputs=img_dir_path)
|
|
|
84 |
history_gallery.select(get_img_info, inputs=None, outputs=[selected_index, info, items])
|
85 |
history_gallery.change(lambda: -1, outputs=selected_index)
|
86 |
del_btn.click(del_img, inputs=[selected_index, img_dir_path, page_index], outputs=history_gallery)
|
87 |
+
items.change(lambda s: [gr.Button(visible=False) for _ in range(6)] if s is None else [gr.Button(visible=True) for _ in range(6)], inputs=items, outputs=[send_btn, history2ref, history2i2i, history2inp, history2dtl, del_btn])
|
88 |
+
return history_gallery, selected_index, send_btn, items, history2ref, history2i2i, history2inp, history2dtl
|
utils.py
CHANGED
@@ -5,15 +5,14 @@ import requests
|
|
5 |
import json
|
6 |
import base64
|
7 |
import math
|
|
|
8 |
|
9 |
from PIL import Image
|
10 |
|
11 |
-
|
12 |
jwt_token = ''
|
13 |
url = "https://image.novelai.net/ai/generate-image"
|
14 |
headers = {}
|
15 |
|
16 |
-
|
17 |
def set_token(token):
|
18 |
global jwt_token, headers
|
19 |
if jwt_token == token:
|
@@ -34,9 +33,9 @@ def get_remain_anlas():
|
|
34 |
except:
|
35 |
return '获取失败,err:' + str(data)
|
36 |
|
37 |
-
def calculate_cost(width, height, steps, sm, dyn, strength=1, rmbg=False):
|
38 |
pixels = width * height
|
39 |
-
if pixels <= 1048576 and steps <= 28:
|
40 |
return 0
|
41 |
dyn = sm and dyn
|
42 |
L = math.ceil(2951823174884865e-21 * pixels + 5.753298233447344e-7 * pixels * steps)
|
@@ -122,7 +121,7 @@ def generate_novelai_image(
|
|
122 |
try:
|
123 |
response = requests.post(url, json=payload, headers=headers, timeout=180)
|
124 |
except:
|
125 |
-
|
126 |
|
127 |
# Process the response
|
128 |
if response.headers.get('Content-Type') == 'binary/octet-stream':
|
@@ -133,9 +132,11 @@ def generate_novelai_image(
|
|
133 |
with zip_ref.open(file_names[0]) as file:
|
134 |
return file.read(), payload
|
135 |
else:
|
136 |
-
|
|
|
137 |
else:
|
138 |
-
|
|
|
139 |
|
140 |
def image_from_bytes(data):
|
141 |
img_file = io.BytesIO(data)
|
@@ -147,4 +148,38 @@ def image2base64(img):
|
|
147 |
img.save(output_buffer, format='PNG' if img.mode=='RGBA' else 'JPEG')
|
148 |
byte_data = output_buffer.getvalue()
|
149 |
base64_str = base64.b64encode(byte_data).decode()
|
150 |
-
return base64_str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
import json
|
6 |
import base64
|
7 |
import math
|
8 |
+
import gradio as gr
|
9 |
|
10 |
from PIL import Image
|
11 |
|
|
|
12 |
jwt_token = ''
|
13 |
url = "https://image.novelai.net/ai/generate-image"
|
14 |
headers = {}
|
15 |
|
|
|
16 |
def set_token(token):
|
17 |
global jwt_token, headers
|
18 |
if jwt_token == token:
|
|
|
33 |
except:
|
34 |
return '获取失败,err:' + str(data)
|
35 |
|
36 |
+
def calculate_cost(width, height, steps=28, sm=False, dyn=False, strength=1, rmbg=False):
|
37 |
pixels = width * height
|
38 |
+
if pixels <= 1048576 and steps <= 28 and not rmbg:
|
39 |
return 0
|
40 |
dyn = sm and dyn
|
41 |
L = math.ceil(2951823174884865e-21 * pixels + 5.753298233447344e-7 * pixels * steps)
|
|
|
121 |
try:
|
122 |
response = requests.post(url, json=payload, headers=headers, timeout=180)
|
123 |
except:
|
124 |
+
raise gr.Error('NAI response timeout')
|
125 |
|
126 |
# Process the response
|
127 |
if response.headers.get('Content-Type') == 'binary/octet-stream':
|
|
|
132 |
with zip_ref.open(file_names[0]) as file:
|
133 |
return file.read(), payload
|
134 |
else:
|
135 |
+
messages = json.loads(response.content)
|
136 |
+
raise gr.Error(messages["statusCode"] + ": " + messages["message"])
|
137 |
else:
|
138 |
+
messages = json.loads(response.content)
|
139 |
+
raise gr.Error(messages["statusCode"] + ": " + messages["message"])
|
140 |
|
141 |
def image_from_bytes(data):
|
142 |
img_file = io.BytesIO(data)
|
|
|
148 |
img.save(output_buffer, format='PNG' if img.mode=='RGBA' else 'JPEG')
|
149 |
byte_data = output_buffer.getvalue()
|
150 |
base64_str = base64.b64encode(byte_data).decode()
|
151 |
+
return base64_str
|
152 |
+
|
153 |
+
def augment_image(image, width, height, req_type, selection, factor=1, defry=0, prompt=''):
|
154 |
+
if selection == "scale":
|
155 |
+
width = int(width * factor)
|
156 |
+
height = int(height * factor)
|
157 |
+
image = image.resize((width, height))
|
158 |
+
req_type = {"移除背景": "bg-removal", "素描": "sketch", "线稿": "lineart", "上色": "colorize", "更改表情": "emotion", "去聊天框": "declutter"}[req_type]
|
159 |
+
base64img = image2base64(image)
|
160 |
+
payload = {"image": base64img, "width": width, "height": height, "req_type": req_type}
|
161 |
+
if req_type == "colorize" or req_type == "emotion":
|
162 |
+
payload["defry"] = defry
|
163 |
+
payload["prompt"] = prompt
|
164 |
+
|
165 |
+
try:
|
166 |
+
response = requests.post("https://image.novelai.net/ai/augment-image", json=payload, headers=headers, timeout=60)
|
167 |
+
except:
|
168 |
+
raise gr.Error('NAI response timeout')
|
169 |
+
|
170 |
+
# Process the response
|
171 |
+
if response.headers.get('Content-Type') == 'binary/octet-stream':
|
172 |
+
zipfile_in_memory = io.BytesIO(response.content)
|
173 |
+
with zipfile.ZipFile(zipfile_in_memory, 'r') as zip_ref:
|
174 |
+
if len(zip_ref.namelist()):
|
175 |
+
files = []
|
176 |
+
for file_name in zip_ref.namelist():
|
177 |
+
with zip_ref.open(file_name) as file:
|
178 |
+
files.append(file.read())
|
179 |
+
return files
|
180 |
+
else:
|
181 |
+
messages = json.loads(response.content)
|
182 |
+
raise gr.Error(messages["statusCode"] + ": " + messages["message"])
|
183 |
+
else:
|
184 |
+
messages = json.loads(response.content)
|
185 |
+
raise gr.Error(messages["statusCode"] + ": " + messages["message"])
|