P01yH3dr0n commited on
Commit
9a80c58
·
1 Parent(s): d708a62

add character reference

Browse files
Files changed (2) hide show
  1. app.py +12 -5
  2. utils.py +8 -1
app.py CHANGED
@@ -185,6 +185,10 @@ def control_ui():
185
  coords_y[i].input(fn=change_one, inputs=[char_coords_y, coords_y[i]], outputs=char_coords_y)
186
  num_chars.change(lambda: gr.Accordion(open=True), inputs=None, outputs=chars)
187
  auto_pos.change(lambda: gr.Accordion(open=True), inputs=None, outputs=chars)
 
 
 
 
188
  with gr.Accordion('高级选项', open=False):
189
  scheduler = gr.Dropdown(
190
  choices=[
@@ -212,10 +216,10 @@ def control_ui():
212
  return gen_btn, stop_btn, \
213
  [model, prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, variety, \
214
  ref_images, info_extracts, ref_strs, vibe_files, str_norm, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection, \
215
- num_chars, auto_pos, char_prompts, char_ucs, char_coords_x, char_coords_y, legacy], \
216
  [save, rand_seed, reuse_seed, reuse_img_i2i, reuse_img_inp, vibe_tab, i2i_tab, rerender]
217
 
218
- def generate(model, prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, variety, ref_images, info_extracts, ref_strs, vibe_files, str_norm, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection, num_chars, auto_pos, char_prompts, char_ucs, char_coords_x, char_coords_y, legacy):
219
  global today_count
220
  set_token(os.environ.get('token'))
221
  img_data, payload = generate_novelai_image(
@@ -223,7 +227,8 @@ def generate(model, prompt, quality_tags, neg_prompt, seed, scale, width, height
223
  width, height, steps, sampler, scheduler,
224
  smea, dyn, dyn_threshold, cfg_rescale, variety, ref_images, info_extracts, ref_strs, vibe_files, str_norm,
225
  i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection,
226
- auto_pos, char_prompts[:num_chars], char_ucs[:num_chars], char_coords_x[:num_chars], char_coords_y[:num_chars], legacy
 
227
  )
228
  if not isinstance(img_data, bytes):
229
  return gr.Image(value=None), payload
@@ -281,7 +286,7 @@ def display_vibe_thumbs(vibe_files):
281
  thumbs.append(base642image(data))
282
  return gr.Gallery(value=thumbs, visible=True)
283
 
284
- def update_btn_cost(model, w, h, s, sm, dyn, ref_imgs, i2i_img, i2i_str, inp_img, selection):
285
  if selection == 'i2i' and i2i_img != None:
286
  cost = calculate_cost(w, h, s, False, False, i2i_str)
287
  elif selection == 'inp' and inp_img['background'] != None:
@@ -290,6 +295,8 @@ def update_btn_cost(model, w, h, s, sm, dyn, ref_imgs, i2i_img, i2i_str, inp_img
290
  cost = calculate_cost(w, h, s, sm, dyn)
291
  if len(ref_imgs) and model.startswith('nai-diffusion-4'):
292
  cost += len(ref_imgs) * 2
 
 
293
  return gr.Button(value=f"生成(预计消耗{cost}点数)")
294
 
295
  def main_ui():
@@ -299,7 +306,7 @@ def main_ui():
299
  gen_btn, stop_btn, paras, others = control_ui()
300
  with gr.Column():
301
  image, info, send_dtool = preview_ui()
302
- cost_list = [paras[0]] + paras[6:9] + paras[11:13] + [paras[17]] + paras[21:23] + paras[25:27]
303
  for component in cost_list:
304
  component.change(update_btn_cost, inputs=cost_list, outputs=gen_btn)
305
  gen = gen_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[gen_btn, stop_btn]).then(
 
185
  coords_y[i].input(fn=change_one, inputs=[char_coords_y, coords_y[i]], outputs=char_coords_y)
186
  num_chars.change(lambda: gr.Accordion(open=True), inputs=None, outputs=chars)
187
  auto_pos.change(lambda: gr.Accordion(open=True), inputs=None, outputs=chars)
188
+ with gr.Accordion('角色参考(仅nai4.5有效)', open=False, elem_id="v4.5char_tab") as v45char_tab:
189
+ chr_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
190
+ fidelity = gr.Slider(label='参考度', value=1, minimum=0, maximum=1, step=0.05)
191
+ style_aware = gr.Checkbox(label='参考风格', value=True)
192
  with gr.Accordion('高级选项', open=False):
193
  scheduler = gr.Dropdown(
194
  choices=[
 
216
  return gen_btn, stop_btn, \
217
  [model, prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, variety, \
218
  ref_images, info_extracts, ref_strs, vibe_files, str_norm, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection, \
219
+ num_chars, auto_pos, char_prompts, char_ucs, char_coords_x, char_coords_y, legacy, chr_image, fidelity, style_aware], \
220
  [save, rand_seed, reuse_seed, reuse_img_i2i, reuse_img_inp, vibe_tab, i2i_tab, rerender]
221
 
222
+ def generate(model, prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, variety, ref_images, info_extracts, ref_strs, vibe_files, str_norm, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection, num_chars, auto_pos, char_prompts, char_ucs, char_coords_x, char_coords_y, legacy, chr_image, fidelity, style_aware):
223
  global today_count
224
  set_token(os.environ.get('token'))
225
  img_data, payload = generate_novelai_image(
 
227
  width, height, steps, sampler, scheduler,
228
  smea, dyn, dyn_threshold, cfg_rescale, variety, ref_images, info_extracts, ref_strs, vibe_files, str_norm,
229
  i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection,
230
+ auto_pos, char_prompts[:num_chars], char_ucs[:num_chars], char_coords_x[:num_chars], char_coords_y[:num_chars], legacy,
231
+ chr_image, fidelity, style_aware
232
  )
233
  if not isinstance(img_data, bytes):
234
  return gr.Image(value=None), payload
 
286
  thumbs.append(base642image(data))
287
  return gr.Gallery(value=thumbs, visible=True)
288
 
289
+ def update_btn_cost(model, w, h, s, sm, dyn, ref_imgs, i2i_img, i2i_str, inp_img, selection, chr_img):
290
  if selection == 'i2i' and i2i_img != None:
291
  cost = calculate_cost(w, h, s, False, False, i2i_str)
292
  elif selection == 'inp' and inp_img['background'] != None:
 
295
  cost = calculate_cost(w, h, s, sm, dyn)
296
  if len(ref_imgs) and model.startswith('nai-diffusion-4'):
297
  cost += len(ref_imgs) * 2
298
+ if chr_img != None and model.startswith('nai-diffusion-4-5'):
299
+ cost += 5
300
  return gr.Button(value=f"生成(预计消耗{cost}点数)")
301
 
302
  def main_ui():
 
306
  gen_btn, stop_btn, paras, others = control_ui()
307
  with gr.Column():
308
  image, info, send_dtool = preview_ui()
309
+ cost_list = [paras[0]] + paras[6:9] + paras[11:13] + [paras[17]] + paras[21:23] + paras[25:27] + [paras[34]]
310
  for component in cost_list:
311
  component.change(update_btn_cost, inputs=cost_list, outputs=gen_btn)
312
  gen = gen_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[gen_btn, stop_btn]).then(
utils.py CHANGED
@@ -77,7 +77,10 @@ def generate_novelai_image(
77
  char_ucs=[],
78
  char_coords_x=[],
79
  char_coords_y=[],
80
- legacy=False
 
 
 
81
  ):
82
  # Assign a random seed if seed is -1
83
  if seed == -1:
@@ -151,6 +154,10 @@ def generate_novelai_image(
151
  payload['parameters']['strength'] = i2i_str
152
  payload['parameters']['extra_noise_seed'] = seed
153
  payload["parameters"]['noise'] = i2i_noise
 
 
 
 
154
  # Send the POST request
155
  try:
156
  response = requests.post(url, json=payload, headers=headers, timeout=180)
 
77
  char_ucs=[],
78
  char_coords_x=[],
79
  char_coords_y=[],
80
+ legacy=False,
81
+ chr_image=None,
82
+ fidelity=1,
83
+ style_aware=True
84
  ):
85
  # Assign a random seed if seed is -1
86
  if seed == -1:
 
154
  payload['parameters']['strength'] = i2i_str
155
  payload['parameters']['extra_noise_seed'] = seed
156
  payload["parameters"]['noise'] = i2i_noise
157
+ if chr_image != None:
158
+ payload['parameters']['director_reference_images'] = [image2base64(chr_image)]
159
+ payload['parameters']['director_reference_descriptions'] = [{'caption': {'base_caption': 'character&style' if style_aware else 'character', 'char_captions': []}, 'legacy_uc': False}]
160
+ payload['parameters']['director_reference_secondary_strength_values'] = [1 - fidelity]
161
  # Send the POST request
162
  try:
163
  response = requests.post(url, json=payload, headers=headers, timeout=180)