Skip to content

Commit eb82cd4

Browse files
committed
Rework custom depthmaps option
Large refactor part, may be broken Also restore "wrong mode" bug workaround
1 parent c57e8c5 commit eb82cd4

File tree

1 file changed

+90
-67
lines changed

1 file changed

+90
-67
lines changed

scripts/depthmap.py

Lines changed: 90 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ def get_commit_hash():
118118
return commit_hash
119119

120120

121+
def convert_i16_to_rgb(image, like):
122+
# three channel, 8 bits per channel image
123+
output = np.zeros_like(like)
124+
output[:, :, 0] = image / 256.0
125+
output[:, :, 1] = image / 256.0
126+
output[:, :, 2] = image / 256.0
127+
return output
128+
129+
121130
def main_ui_panel(is_depth_tab):
122131
inp = GradioComponentBundle()
123132
# TODO: Greater visual separation
@@ -344,7 +353,7 @@ def run(self, p, *inputs):
344353
continue
345354
inputimages.append(processed.images[count])
346355

347-
generated_images, mesh_fi, meshsimple_fi = run_depthmap(processed, p.outpath_samples, inputimages, None, inputs)
356+
generated_images, mesh_fi, meshsimple_fi = run_depthmap(p.outpath_samples, inputimages, None, None, inputs)
348357

349358
for input_i, imgs in enumerate(generated_images):
350359
# get generation parameters
@@ -355,10 +364,15 @@ def run(self, p, *inputs):
355364
for image_type, image in list(imgs.items()):
356365
processed.images.append(image)
357366
if inputs["save_outputs"]:
358-
images.save_image(image, path=p.outpath_samples, basename="", seed=processed.all_seeds[input_i],
367+
try:
368+
images.save_image(image, path=p.outpath_samples, basename="", seed=processed.all_seeds[input_i],
359369
prompt=processed.all_prompts[input_i], extension=opts.samples_format, info=info,
360370
p=processed,
361371
suffix=f"_{image_type}")
372+
except Exception as e:
373+
if not ('image has wrong mode' in str(e) or 'I;16' in str(e)): raise e
374+
print('Catched exception: image has wrong mode!')
375+
traceback.print_exc()
362376
return processed
363377

364378

@@ -374,9 +388,12 @@ def reload_sd_model():
374388
shared.sd_model.first_stage_model.to(devices.device)
375389

376390

377-
def run_depthmap(processed, outpath, inputimages, inputnames, inp):
391+
def run_depthmap(outpath, inputimages, inputdepthmaps, inputnames, inp):
378392
if len(inputimages) == 0 or inputimages[0] is None:
379-
return [], []
393+
return [], '', ''
394+
if len(inputdepthmaps) == 0:
395+
inputdepthmaps = [None for _ in range(len(inputimages))]
396+
inputdepthmaps_complete = all([x is not None for x in inputdepthmaps])
380397

381398
background_removal = inp["background_removal"]
382399
background_removal_model = inp["background_removal_model"]
@@ -409,10 +426,6 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
409426
stereo_modes = inp["stereo_modes"]
410427
stereo_separation = inp["stereo_separation"]
411428

412-
custom_depthmap = inp["custom_depthmap"] if "custom_depthmap" in inp else False
413-
custom_depthmap_img = inp["custom_depthmap_img"] if "custom_depthmap_img" in inp else None
414-
depthmap_batch_reuse = inp["depthmap_batch_reuse"] if "depthmap_batch_reuse" in inp else True
415-
416429
# TODO: run_depthmap should not generate or save meshes, since these do not use generated depthmaps.
417430
# Rationale: allowing webui-independent (stand-alone) wrappers.
418431
print(f"\n{scriptname} {scriptversion} ({get_commit_hash()})")
@@ -429,9 +442,6 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
429442
else:
430443
background_removed_images = batched_background_removal(inputimages, background_removal_model)
431444

432-
meshsimple_fi = None
433-
mesh_fi = None
434-
435445
resize_mode = "minimal"
436446
normalization = NormalizeImage(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
437447

@@ -455,7 +465,7 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
455465
os.makedirs('./models/pix2pix', exist_ok=True)
456466

457467
global depthmap_model_depth, depthmap_model_pix2pix, depthmap_model_type, depthmap_device_idx
458-
loadmodels = True
468+
loadmodels = True # TODO: loadmodels is not intuitive
459469
if hasattr(opts, 'depthmap_script_keepmodels') and opts.depthmap_script_keepmodels:
460470
loadmodels = False
461471
if depthmap_model_type != model_type or depthmap_model_depth == None or depthmap_device_idx != depthmap_compute_device:
@@ -464,7 +474,7 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
464474
loadmodels = True
465475

466476
try:
467-
if loadmodels and not (custom_depthmap and custom_depthmap_img != None):
477+
if loadmodels and not inputdepthmaps_complete:
468478
# TODO: loading model should be separated into a function that would return the model
469479
# and the parameters (or maybe even functions) needed.
470480
# The rest of the run_depthmap should not depend on what specific model
@@ -645,10 +655,12 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
645655
# Every array element corresponds to particular input image.
646656
# Dictionary keys are types of images that were derived from the input image.
647657
generated_images = [{} for _ in range(numimages)]
658+
648659
# TODO: ???
660+
meshsimple_fi = None
649661
inpaint_imgs = []
650-
# TODO: ???
651662
inpaint_depths = []
663+
652664
# iterate over input (generated) images
653665
for count in trange(0, numimages):
654666

@@ -657,25 +669,8 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
657669
# filename
658670
basename = 'depthmap'
659671

660-
# TODO: this should not use heuristics to figure out the mode, mode should ideally be abstracted away.
661-
# By the way, this is probably broken
662-
# figuring out the name of custom DepthMap
663-
custom_depthmap_fn = None # None means that DepthMap should be computed
664-
# find filename if in the single image mode
665-
if custom_depthmap and custom_depthmap_img is not None:
666-
custom_depthmap_fn = custom_depthmap_img.name
667-
# find filename if in batch mode
668-
if inputnames is not None and depthmap_batch_reuse:
669-
if inputnames[count] is not None:
670-
p = Path(inputnames[count])
671-
basename = p.stem
672-
if outpath != opts.outdir_extras_samples:
673-
custom_depthmap_fn = os.path.join(outpath, basename + '-0000.' + opts.samples_format)
674-
if not os.path.isfile(custom_depthmap_fn):
675-
custom_depthmap_fn = None
676-
677672
# override net size
678-
if (match_size):
673+
if match_size:
679674
net_width, net_height = inputimages[count].width, inputimages[count].height
680675

681676
# Convert single channel input (PIL) images to rgb
@@ -687,10 +682,9 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
687682
img = cv2.cvtColor(np.asarray(inputimages[count]), cv2.COLOR_BGR2RGB) / 255.0
688683

689684
skipInvertAndSave = False
690-
# TODO: custom depthmaps should be supplied in the same way as "custom depthmap" in single image mode
691-
if custom_depthmap_fn is not None:
685+
if inputdepthmaps is not None and inputdepthmaps[count] is not None:
692686
# use custom depthmap
693-
dimg = Image.open(os.path.abspath(custom_depthmap_fn))
687+
dimg = inputdepthmaps[count]
694688
# resize if not same size as input
695689
if dimg.width != inputimages[count].width or dimg.height != inputimages[count].height:
696690
dimg = dimg.resize((inputimages[count].width, inputimages[count].height), Image.Resampling.LANCZOS)
@@ -736,12 +730,6 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
736730
img_output = clipdepthmap(img_output, clipthreshold_far, clipthreshold_near)
737731
# img_output = cv2.blur(img_output, (3, 3))
738732

739-
# three channel, 8 bits per channel image
740-
img_output2 = np.zeros_like(inputimages[count])
741-
img_output2[:, :, 0] = img_output / 256.0
742-
img_output2[:, :, 1] = img_output / 256.0
743-
img_output2[:, :, 2] = img_output / 256.0
744-
745733
# if 3dinpainting, store maps for processing in second pass
746734
if inpaint:
747735
inpaint_imgs.append(inputimages[count])
@@ -773,7 +761,8 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
773761
if not skipInvertAndSave: # TODO: skipInvertAndSave is not intuitive
774762
if output_depth:
775763
if combine_output:
776-
img_concat = Image.fromarray(np.concatenate((rgb_image, img_output2), axis=combine_output_axis))
764+
img_concat = Image.fromarray(np.concatenate(
765+
(rgb_image, convert_i16_to_rgb(img_output, rgb_image)), axis=combine_output_axis))
777766
generated_images[count]['concat_depth'] = img_concat
778767
else:
779768
generated_images[count]['depth'] = Image.fromarray(img_output)
@@ -819,9 +808,9 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
819808

820809
depthi = prediction
821810
# try to map output to sensible values for non zoedepth models, boost, or custom maps
822-
if model_type < 7 or boost or (custom_depthmap and custom_depthmap_img != None):
811+
if model_type < 7 or boost or inputdepthmaps_complete:
823812
# invert if midas
824-
if model_type > 0 or ((custom_depthmap and custom_depthmap_img != None) and not invert_depth):
813+
if model_type > 0 or (inputdepthmaps_complete and not invert_depth):
825814
depthi = depth_max - depthi + depth_min
826815
depth_max = depthi.max()
827816
depth_min = depthi.min()
@@ -860,13 +849,15 @@ def run_depthmap(processed, outpath, inputimages, inputnames, inp):
860849
gc.collect()
861850
devices.torch_gc()
862851
reload_sd_model()
863-
try:
864-
if inpaint:
852+
853+
mesh_fi = None
854+
if inpaint:
855+
try:
865856
unload_sd_model()
866857
mesh_fi = run_3dphoto(device, inpaint_imgs, inpaint_depths, inputnames, outpath, inpaint_vids, 1, "mp4")
867-
finally:
868-
reload_sd_model()
869-
print("All done.")
858+
finally:
859+
reload_sd_model() # Do not reload twice
860+
print("All done.")
870861

871862
return generated_images, mesh_fi, meshsimple_fi
872863

@@ -1196,15 +1187,27 @@ def run_generate(*inputs):
11961187
depthmap_input_image = inputs['depthmap_input_image']
11971188
depthmap_batch_output_dir = inputs['depthmap_batch_output_dir']
11981189
depthmap_batch_reuse = inputs['depthmap_batch_reuse']
1190+
custom_depthmap = inputs['custom_depthmap']
1191+
custom_depthmap_img = inputs['custom_depthmap_img']
11991192

12001193
inputimages = []
1194+
# Allow supplying custom depthmaps
1195+
inputdepthmaps = []
12011196
# Also keep track of original file names
12021197
inputnames = []
1203-
show_images = []
1198+
1199+
if depthmap_mode == '2' and depthmap_batch_output_dir != '':
1200+
outpath = depthmap_batch_output_dir
1201+
else:
1202+
outpath = opts.outdir_samples or opts.outdir_extras_samples
12041203

12051204
if depthmap_mode == '0': # Single image
12061205
inputimages.append(depthmap_input_image)
12071206
inputnames.append(None)
1207+
if custom_depthmap:
1208+
inputdepthmaps.append(custom_depthmap_img)
1209+
else:
1210+
inputdepthmaps.append(None)
12081211
if depthmap_mode == '1': # Batch Process
12091212
# convert files to pillow images
12101213
for img in image_batch:
@@ -1214,39 +1217,58 @@ def run_generate(*inputs):
12141217
elif depthmap_mode == '2': # Batch from Directory
12151218
assert not shared.cmd_opts.hide_ui_dir_config, '--hide-ui-dir-config option must be disabled'
12161219
if depthmap_batch_input_dir == '':
1217-
return show_images, "Please select an input directory.", ''
1220+
return [], "Please select an input directory.", ""
1221+
if depthmap_batch_input_dir == depthmap_batch_output_dir:
1222+
return [], "Please pick different directories for batch processing.", ""
12181223
image_list = shared.listfiles(depthmap_batch_input_dir)
1219-
for img in image_list:
1224+
for path in image_list:
12201225
try:
1221-
image = Image.open(img)
1222-
inputimages.append(image)
1223-
inputnames.append(img)
1224-
except Exception:
1225-
print(f'Failed to load {img}, ignoring.')
1226+
inputimages.append(Image.open(path))
1227+
inputnames.append(path)
12261228

1227-
if depthmap_mode == '2' and depthmap_batch_output_dir != '':
1228-
outpath = depthmap_batch_output_dir
1229-
else:
1230-
outpath = opts.outdir_samples or opts.outdir_extras_samples
1229+
custom_depthmap = None
1230+
if depthmap_batch_reuse:
1231+
basename = Path(path).stem
1232+
# Custom names are not used in samples directory
1233+
if outpath != opts.outdir_extras_samples:
1234+
# Possible filenames that the custom depthmaps may have
1235+
name_candidates = [f'{basename}-0000_depth.{opts.samples_format}', # current format
1236+
f'{basename}-0000.{opts.samples_format}', # old format
1237+
f'{basename}.png', # human-intuitive format
1238+
f'{Path(path).name}'] # human-intuitive format (worse)
1239+
for fn_cand in name_candidates:
1240+
path_cand = os.path.join(outpath, fn_cand)
1241+
if os.path.isfile(path_cand):
1242+
custom_depthmap = Image.open(os.path.abspath(path_cand))
1243+
break
1244+
inputdepthmaps.append(custom_depthmap)
1245+
except Exception:
1246+
print(f'Failed to load {path}, ignoring.')
1247+
inputdepthmaps_n = len([1 for x in inputdepthmaps if x is not None])
1248+
print(f'{len(inputimages)} images will be processed, {inputdepthmaps_n} existing depthmaps will be reused')
12311249

1232-
save_images, mesh_fi, meshsimple_fi = run_depthmap(None, outpath, inputimages, inputnames, inputs)
1250+
save_images, mesh_fi, meshsimple_fi = run_depthmap(outpath, inputimages, inputdepthmaps, inputnames, inputs)
12331251
show_images = []
12341252

12351253
# Saving images
12361254
for input_i, imgs in enumerate(save_images):
12371255
basename = 'depthmap'
1238-
if depthmap_batch_reuse and depthmap_mode == '2':
1239-
if inputnames[input_i] is not None:
1240-
basename = Path(inputnames[input_i]).stem
1256+
if depthmap_mode == '2' and inputnames[input_i] is not None and outpath != opts.outdir_extras_samples:
1257+
basename = Path(inputnames[input_i]).stem
12411258
info = None
12421259

12431260
for image_type, image in list(imgs.items()):
12441261
show_images += [image]
12451262
if inputs["save_outputs"]:
1246-
images.save_image(image, path=outpath, basename=basename, seed=None,
1263+
try:
1264+
images.save_image(image, path=outpath, basename=basename, seed=None,
12471265
prompt=None, extension=opts.samples_format, info=info, short_filename=True,
12481266
no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=None,
12491267
forced_filename=None, suffix=f"_{image_type}")
1268+
except Exception as e:
1269+
if not ('image has wrong mode' in str(e) or 'I;16' in str(e)): raise e
1270+
print('Catched exception: image has wrong mode!')
1271+
traceback.print_exc()
12501272

12511273
# use inpainted 3d mesh to show in 3d model output when enabled in settings
12521274
if hasattr(opts, 'depthmap_script_show_3d_inpaint') and opts.depthmap_script_show_3d_inpaint and mesh_fi != None and len(mesh_fi) > 0:
@@ -1320,8 +1342,9 @@ def on_ui_tabs():
13201342
inp += gr.Textbox(elem_id="depthmap_batch_output_dir", label="Output directory",
13211343
**shared.hide_dirs,
13221344
placeholder="Leave blank to save images to the default path.")
1345+
gr.HTML("Files in the output directory may be overwritten")
13231346
inp += gr.Checkbox(elem_id="depthmap_batch_reuse",
1324-
label="Skip generation and use (edited/custom) depthmaps in output directory when a file exists.",
1347+
label="Skip generation and use (edited/custom) depthmaps in output directory when a file already exists.",
13251348
value=True)
13261349
submit = gr.Button('Generate', elem_id="depthmap_generate", variant='primary')
13271350
inp += main_ui_panel(True) # Main panel is inserted here

0 commit comments

Comments
 (0)