Skip to content

Commit 68faac4

Browse files
committed
Rework core_generation_funnel to be generator
Closes thygate#302
1 parent 36a5ed5 commit 68faac4

File tree

5 files changed

+102
-75
lines changed

5 files changed

+102
-75
lines changed

scripts/depthmap.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,30 +43,34 @@ def run(self, p, *inputs):
4343
continue
4444
inputimages.append(processed.images[count])
4545

46-
outputs, mesh_fi, meshsimple_fi = core_generation_funnel(p.outpath_samples, inputimages, None, None, inputs, backbone.gather_ops())
46+
gen_obj = core_generation_funnel(p.outpath_samples, inputimages, None, None, inputs, backbone.gather_ops())
47+
48+
for input_i, type, result in gen_obj:
49+
if type in ['simple_mesh', 'inpainted_mesh']:
50+
continue # We are in script mode: do nothing with the filenames
4751

48-
for input_i, imgs in enumerate(outputs):
4952
# get generation parameters
53+
# TODO: could reuse
5054
if hasattr(processed, 'all_prompts') and shared.opts.enable_pnginfo:
51-
info = create_infotext(processed, processed.all_prompts, processed.all_seeds, processed.all_subseeds,
52-
"", 0, input_i)
55+
info = create_infotext(
56+
processed, processed.all_prompts, processed.all_seeds, processed.all_subseeds, "", 0, input_i)
5357
else:
5458
info = None
55-
for image_type, image in list(imgs.items()):
56-
processed.images.append(image)
57-
if inputs["save_outputs"]:
58-
try:
59-
suffix = "" if image_type == "depth" else f"{image_type}"
60-
backbone.save_image(image, path=p.outpath_samples, basename="", seed=processed.all_seeds[input_i],
61-
prompt=processed.all_prompts[input_i], extension=shared.opts.samples_format,
62-
info=info,
63-
p=processed,
64-
suffix=suffix)
65-
except Exception as e:
66-
if not ('image has wrong mode' in str(e) or 'I;16' in str(e)):
67-
raise e
68-
print('Catched exception: image has wrong mode!')
69-
traceback.print_exc()
59+
60+
processed.images.append(result)
61+
if inputs["save_outputs"]:
62+
try:
63+
suffix = "" if type == "depth" else f"{type}"
64+
backbone.save_image(result, path=p.outpath_samples, basename="", seed=processed.all_seeds[input_i],
65+
prompt=processed.all_prompts[input_i], extension=shared.opts.samples_format,
66+
info=info,
67+
p=processed,
68+
suffix=suffix)
69+
except Exception as e:
70+
if not ('image has wrong mode' in str(e) or 'I;16' in str(e)):
71+
raise e
72+
print('Catched exception: image has wrong mode!')
73+
traceback.print_exc()
7074
return processed
7175

7276

scripts/depthmap_api.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,24 @@ async def process(
5353
depth_input_images: List[str] = Body([], title='Input Images'),
5454
options: Dict[str, object] = Body("options", title='Generation options'),
5555
):
56-
if len(depth_input_images) == 0:
57-
raise HTTPException(status_code=422, detail="No image supplied")
56+
# TODO: restrict mesh options
5857

59-
print(f"Processing {str(len(depth_input_images))} images trough the API.")
58+
if len(depth_input_images) == 0:
59+
raise HTTPException(status_code=422, detail="No images supplied")
60+
print(f"Processing {str(len(depth_input_images))} images trough the API")
6061

61-
PIL_images = []
62+
pil_images = []
6263
for input_image in depth_input_images:
63-
PIL_images.append(to_base64_PIL(input_image))
64-
64+
pil_images.append(to_base64_PIL(input_image))
6565
outpath = backbone.get_outpath()
66-
results, _, _ = core_generation_funnel(outpath, PIL_images, None, None, options)
66+
gen_obj = core_generation_funnel(outpath, pil_images, None, None, options)
6767

68-
# TODO: Fix: this just keeps depth image throws everything else away
69-
results = [img['depth'] for img in results]
70-
results64 = list(map(encode_to_base64, results))
68+
results_based = []
69+
for count, type, result in gen_obj:
70+
if type not in ['simple_mesh', 'inpainted_mesh']:
71+
results_based += [encode_to_base64(result)]
72+
return {"images": results_based, "info": "Success"}
7173

72-
return {"images": results64, "info": "Success"}
7374

7475
try:
7576
import modules.script_callbacks as script_callbacks

src/backbone.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
# must be resided in this file (or in the scripts folder).
44
import pathlib
55
from datetime import datetime
6+
import enum
7+
8+
9+
class BackboneType(enum.Enum):
10+
WEBUI = 1
11+
STANDALONE = 2
12+
613

714
try:
815
# stable-diffusion-webui backbone
@@ -61,6 +68,8 @@ def reload_sd_model():
6168
def get_hide_dirs():
6269
import modules.shared
6370
return modules.shared.hide_dirs
71+
72+
USED_BACKBONE = BackboneType.WEBUI
6473
except:
6574
# Standalone backbone
6675
print( # " DepthMap did not detect stable-diffusion-webui; launching with the standalone backbone.\n"
@@ -116,3 +125,6 @@ def unload_sd_model(): pass # Not needed
116125
def reload_sd_model(): pass # Not needed
117126

118127
def get_hide_dirs(): return {} # Directories will not be hidden from traversal (except when starts with the dot)
128+
129+
130+
USED_BACKBONE = BackboneType.STANDALONE

src/common_ui.py

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -470,36 +470,42 @@ def run_generate(*inputs):
470470
inputdepthmaps_n = len([1 for x in inputdepthmaps if x is not None])
471471
print(f'{len(inputimages)} images will be processed, {inputdepthmaps_n} existing depthmaps will be reused')
472472

473-
outputs, fn_mesh, display_mesh = core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inputs, backbone.gather_ops())
473+
gen_obj = core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inputs, backbone.gather_ops())
474474

475-
# Saving images
476475
show_images = []
477-
for input_i, imgs in enumerate(outputs):
476+
inpainted_mesh_fi = mesh_simple_fi = None
477+
for input_i, type, result in gen_obj:
478+
if type == 'simple_mesh':
479+
mesh_simple_fi = result
480+
continue
481+
if type == 'inpainted_mesh':
482+
inpainted_mesh_fi = result
483+
continue
484+
478485
basename = 'depthmap'
479486
if depthmap_mode == '2' and inputnames[input_i] is not None and outpath != backbone.get_opt('outdir_extras_samples', None):
480487
basename = Path(inputnames[input_i]).stem
481488

482-
for image_type, image in list(imgs.items()):
483-
show_images += [image]
484-
if inputs["save_outputs"]:
485-
try:
486-
suffix = "" if image_type == "depth" else f"{image_type}"
487-
backbone.save_image(image, path=outpath, basename=basename, seed=None,
488-
prompt=None, extension=backbone.get_opt('samples_format', 'png'), short_filename=True,
489-
no_prompt=True, grid=False, pnginfo_section_name="extras",
490-
suffix=suffix)
491-
except Exception as e:
492-
if not ('image has wrong mode' in str(e) or 'I;16' in str(e)):
493-
raise e
494-
print('Catched exception: image has wrong mode!')
495-
traceback.print_exc()
496-
497-
display_mesh = None
498-
# use inpainted 3d mesh to show in 3d model output when enabled in settings
499-
if backbone.get_opt('depthmap_script_show_3d_inpaint', True) and fn_mesh is not None and len(fn_mesh) > 0:
500-
display_mesh = fn_mesh
501-
# however, don't show 3dmodel when disabled in settings
489+
show_images += [result]
490+
if inputs["save_outputs"]:
491+
try:
492+
suffix = "" if type == "depth" else f"{type}"
493+
backbone.save_image(result, path=outpath, basename=basename, seed=None,
494+
prompt=None, extension=backbone.get_opt('samples_format', 'png'), short_filename=True,
495+
no_prompt=True, grid=False, pnginfo_section_name="extras",
496+
suffix=suffix)
497+
except Exception as e:
498+
if not ('image has wrong mode' in str(e) or 'I;16' in str(e)):
499+
raise e
500+
print('Catched exception: image has wrong mode!')
501+
traceback.print_exc()
502+
503+
# Deciding what mesh to display (and if)
504+
display_mesh_fi = None
502505
if not backbone.get_opt('depthmap_script_show_3d', True):
503-
display_mesh = None
506+
display_mesh_fi = mesh_simple_fi
507+
if backbone.get_opt('depthmap_script_show_3d_inpaint', True):
508+
if inpainted_mesh_fi is not None and len(inpainted_mesh_fi) > 0:
509+
display_mesh_fi = inpainted_mesh_fi
504510
# TODO: return more info
505-
return show_images, fn_mesh, display_mesh, 'Generated!'
511+
return show_images, inpainted_mesh_fi, display_mesh_fi, 'Generated!'

src/core.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def __getattr__(self, item):
6666

6767
def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp, ops=None):
6868
if len(inputimages) == 0 or inputimages[0] is None:
69-
return [], '', ''
69+
return
7070
if inputdepthmaps is None or len(inputdepthmaps) == 0:
7171
inputdepthmaps: list[Image] = [None for _ in range(len(inputimages))]
7272
inputdepthmaps_complete = all([x is not None for x in inputdepthmaps])
@@ -103,12 +103,7 @@ def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp
103103
device = torch.device("cpu")
104104
print("device: %s" % device)
105105

106-
generated_images = [{} for _ in range(len(inputimages))]
107-
"""Images that will be returned.
108-
Every array element corresponds to particular input image.
109-
Dictionary keys are types of images that were derived from the input image."""
110-
# TODO: ???
111-
meshsimple_fi = None
106+
# TODO: This should not be here
112107
inpaint_imgs = []
113108
inpaint_depths = []
114109

@@ -192,14 +187,14 @@ def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp
192187
background_removed_array[:, :, 2] == 0) & (background_removed_array[:, :, 3] <= 0.2)
193188
img_output[bg_mask] = 0 # far value
194189

195-
generated_images[count]['background_removed'] = background_removed_image
190+
yield count, 'background_removed', background_removed_image
196191

197192
if inp[go.SAVE_BACKGROUND_REMOVAL_MASKS]:
198193
bg_array = (1 - bg_mask.astype('int8')) * 255
199194
mask_array = np.stack((bg_array, bg_array, bg_array, bg_array), axis=2)
200195
mask_image = Image.fromarray(mask_array.astype(np.uint8))
201196

202-
generated_images[count]['foreground_mask'] = mask_image
197+
yield count, 'foreground_mask', mask_image
203198

204199
# A weird quirk: if user tries to save depthmap, whereas input depthmap is used,
205200
# depthmap will be outputed, even if output_depth_combine is used.
@@ -211,9 +206,9 @@ def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp
211206
img_concat = Image.fromarray(np.concatenate(
212207
(inputimages[count], convert_i16_to_rgb(img_depth, inputimages[count])),
213208
axis=axis))
214-
generated_images[count]['concat_depth'] = img_concat
209+
yield count, 'concat_depth', img_concat
215210
else:
216-
generated_images[count]['depth'] = Image.fromarray(img_depth)
211+
yield count, 'depth', Image.fromarray(img_depth)
217212

218213
if inp[go.GEN_STEREO]:
219214
print("Generating stereoscopic images..")
@@ -222,21 +217,22 @@ def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp
222217
inp[go.STEREO_DIVERGENCE], inp[go.STEREO_SEPARATION],
223218
inp[go.STEREO_MODES], inp[go.STEREO_BALANCE], inp[go.STEREO_FILL_ALGO])
224219
for c in range(0, len(stereoimages)):
225-
generated_images[count][inp[go.STEREO_MODES][c]] = stereoimages[c]
220+
yield count, inp[go.STEREO_MODES][c], stereoimages[c]
226221

227222
if inp[go.GEN_NORMALMAP]:
228-
generated_images[count]['normalmap'] = create_normalmap(
223+
normalmap = create_normalmap(
229224
img_output,
230225
inp[go.NORMALMAP_PRE_BLUR_KERNEL] if inp[go.NORMALMAP_PRE_BLUR] else None,
231226
inp[go.NORMALMAP_SOBEL_KERNEL] if inp[go.NORMALMAP_SOBEL] else None,
232227
inp[go.NORMALMAP_POST_BLUR_KERNEL] if inp[go.NORMALMAP_POST_BLUR] else None,
233228
inp[go.NORMALMAP_INVERT]
234229
)
230+
yield count, 'normalmap', normalmap
235231

236232
if inp[go.GEN_HEATMAP]:
237233
from dzoedepth.utils.misc import colorize
238234
heatmap = Image.fromarray(colorize(img_output, cmap='inferno'))
239-
generated_images[count]['heatmap'] = heatmap
235+
yield count, 'heatmap', heatmap
240236

241237
# gen mesh
242238
if inp[go.GEN_SIMPLE_MESH]:
@@ -268,17 +264,25 @@ def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp
268264
mesh = create_mesh(inputimages[count], depthi, keep_edges=not inp[go.SIMPLE_MESH_OCCLUDE],
269265
spherical=(inp[go.SIMPLE_MESH_SPHERICAL]))
270266
mesh.export(meshsimple_fi)
267+
yield count, 'simple_mesh', meshsimple_fi
271268

272269
print("Computing output(s) done.")
273270
except RuntimeError as e:
274271
# TODO: display in UI
275272
if 'out of memory' in str(e):
276-
suggestion = "ERROR: out of memory, could not generate depthmap!\nPlease try a different model"
277-
if device != torch.device("cpu"):
278-
suggestion += ", or try using the CPU"
273+
suggestion = "ERROR: out of GPU memory, could not generate depthmap! " \
274+
"Here are some suggestions to work around this issue:\n"
279275
if inp[go.BOOST]:
280-
suggestion += ", or disable BOOST"
281-
print(f"{suggestion}.")
276+
suggestion += " * Disable BOOST (generation will be faster, but the depthmap will be less detailed)\n"
277+
if backbone.USED_BACKBONE == backbone.BackboneType.WEBUI:
278+
suggestion += " * Run DepthMap in the standalone mode - without launching the SD WebUI\n"
279+
if device != torch.device("cpu"):
280+
suggestion += " * Select CPU as the processing device (this will be slower)\n"
281+
if inp[go.MODEL_TYPE] != 6:
282+
suggestion += " * Use a different model (this could reduce quality)\n"
283+
if not inp[go.BOOST]:
284+
suggestion += " * Reduce net size (this could reduce quality)\n"
285+
print(f"{suggestion}")
282286
else:
283287
raise e
284288
finally:
@@ -301,12 +305,12 @@ def core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inp
301305
mesh_fi = run_3dphoto(device, inpaint_imgs, inpaint_depths, inputnames, outpath,
302306
inp[go.GEN_INPAINTED_MESH_DEMOS],
303307
1, "mp4")
308+
yield 0, 'inpainted_mesh', mesh_fi
304309
except Exception as e:
305310
print(f'{str(e)}, some issue with generating inpainted mesh')
306311

307312
backbone.reload_sd_model()
308313
print("All done.\n")
309-
return generated_images, mesh_fi, meshsimple_fi
310314

311315

312316
def get_uniquefn(outpath, basename, ext):

0 commit comments

Comments
 (0)