Spaces:
Runtime error
Runtime error
| import traceback | |
| from pathlib import Path | |
| import gradio as gr | |
| from PIL import Image | |
| from src import backbone, video_mode | |
| from src.core import core_generation_funnel, unload_models, run_makevideo | |
| from src.depthmap_generation import ModelHolder | |
| from src.gradio_args_transport import GradioComponentBundle | |
| from src.misc import * | |
| from src.common_constants import GenerationOptions as go | |
| # Ugly workaround to fix gradio tempfile issue | |
| def ensure_gradio_temp_directory(): | |
| try: | |
| import tempfile | |
| path = os.path.join(tempfile.gettempdir(), 'gradio') | |
| if not (os.path.exists(path)): | |
| os.mkdir(path) | |
| except Exception as e: | |
| traceback.print_exc() | |
| ensure_gradio_temp_directory() | |
| def main_ui_panel(is_depth_tab): | |
| inp = GradioComponentBundle() | |
| # TODO: Greater visual separation | |
| with gr.Blocks(): | |
| with gr.Row() as cur_option_root: | |
| inp -= 'depthmap_gen_row_0', cur_option_root | |
| inp += go.COMPUTE_DEVICE, gr.Radio(label="Compute on", choices=['GPU', 'CPU'], value='GPU') | |
| # TODO: Should return value instead of index. Maybe Enum should be used? | |
| inp += go.MODEL_TYPE, gr.Dropdown(label="Model", | |
| choices=['res101', 'dpt_beit_large_512 (midas 3.1)', | |
| 'dpt_beit_large_384 (midas 3.1)', 'dpt_large_384 (midas 3.0)', | |
| 'dpt_hybrid_384 (midas 3.0)', | |
| 'midas_v21', 'midas_v21_small', | |
| 'zoedepth_n (indoor)', 'zoedepth_k (outdoor)', 'zoedepth_nk', | |
| 'Marigold v1', 'Depth Anything', 'Depth Anything v2 Small', | |
| 'Depth Anything v2 Base', 'Depth Anything v2 Large'], | |
| value='Depth Anything v2 Base', type="index") | |
| with gr.Box() as cur_option_root: | |
| inp -= 'depthmap_gen_row_1', cur_option_root | |
| with gr.Row(): | |
| inp += go.BOOST, gr.Checkbox(label="BOOST", | |
| info="Generate depth map parts in a mosaic fashion - very slow", | |
| value=False) | |
| inp += go.NET_SIZE_MATCH, gr.Checkbox(label="Match net size to input size", | |
| info="Net size affects quality, performance and VRAM usage") | |
| with gr.Row() as options_depend_on_match_size: | |
| inp += go.NET_WIDTH, gr.Slider(minimum=64, maximum=2048, step=64, label='Net width') | |
| inp += go.NET_HEIGHT, gr.Slider(minimum=64, maximum=2048, step=64, label='Net height') | |
| with gr.Row(): | |
| inp += go.TILING_MODE, gr.Checkbox( | |
| label='Tiling mode', info='Reduces seams that appear if the depthmap is tiled into a grid' | |
| ) | |
| with gr.Box() as cur_option_root: | |
| inp -= 'depthmap_gen_row_2', cur_option_root | |
| with gr.Row(): | |
| with gr.Group(): # 50% of width | |
| inp += "save_outputs", gr.Checkbox(label="Save Outputs", value=True) | |
| with gr.Group(): # 50% of width | |
| inp += go.DO_OUTPUT_DEPTH, gr.Checkbox(label="Output DepthMap") | |
| inp += go.OUTPUT_DEPTH_INVERT, gr.Checkbox(label="Invert (black=near, white=far)") | |
| with gr.Row() as options_depend_on_output_depth_1: | |
| inp += go.OUTPUT_DEPTH_COMBINE, gr.Checkbox( | |
| label="Combine input and depthmap into one image") | |
| inp += go.OUTPUT_DEPTH_COMBINE_AXIS, gr.Radio( | |
| label="Combine axis", choices=['Vertical', 'Horizontal'], type="value", visible=False) | |
| with gr.Box() as cur_option_root: | |
| inp -= 'depthmap_gen_row_3', cur_option_root | |
| with gr.Row(): | |
| inp += go.CLIPDEPTH, gr.Checkbox(label="Clip and renormalize DepthMap") | |
| inp += go.CLIPDEPTH_MODE,\ | |
| gr.Dropdown(label="Mode", choices=['Range', 'Outliers'], type="value", visible=False) | |
| with gr.Row(visible=False) as clip_options_row_1: | |
| inp += go.CLIPDEPTH_FAR, gr.Slider(minimum=0, maximum=1, step=0.001, label='Far clip') | |
| inp += go.CLIPDEPTH_NEAR, gr.Slider(minimum=0, maximum=1, step=0.001, label='Near clip') | |
| with gr.Box(): | |
| with gr.Row(): | |
| inp += go.GEN_STEREO, gr.Checkbox(label="Generate stereoscopic (3D) image(s)") | |
| with gr.Column(visible=False) as stereo_options: | |
| with gr.Row(): | |
| inp += go.STEREO_MODES, gr.CheckboxGroup( | |
| ["left-right", "right-left", "top-bottom", "bottom-top", "red-cyan-anaglyph", | |
| "left-only", "only-right", "cyan-red-reverseanaglyph" | |
| ][0:8 if backbone.get_opt('depthmap_script_extra_stereomodes', False) else 5], label="Output") | |
| with gr.Row(): | |
| inp += go.STEREO_DIVERGENCE, gr.Slider(minimum=0.05, maximum=15.005, step=0.01, | |
| label='Divergence (3D effect)') | |
| inp += go.STEREO_SEPARATION, gr.Slider(minimum=-5.0, maximum=5.0, step=0.01, | |
| label='Separation (moves images apart)') | |
| with gr.Row(): | |
| inp += go.STEREO_FILL_ALGO, gr.Dropdown(label="Gap fill technique", | |
| choices=['none', 'naive', 'naive_interpolating', 'polylines_soft', | |
| 'polylines_sharp'], | |
| type="value") | |
| inp += go.STEREO_OFFSET_EXPONENT, gr.Slider(label="Magic exponent", minimum=1, maximum=2, step=1) | |
| inp += go.STEREO_BALANCE, gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, | |
| label='Balance between eyes') | |
| with gr.Box(): | |
| with gr.Row(): | |
| inp += go.GEN_NORMALMAP, gr.Checkbox(label="Generate NormalMap") | |
| with gr.Column(visible=False) as normalmap_options: | |
| with gr.Row(): | |
| inp += go.NORMALMAP_PRE_BLUR, gr.Checkbox(label="Smooth before calculating normals") | |
| inp += go.NORMALMAP_PRE_BLUR_KERNEL, gr.Slider(minimum=1, maximum=31, step=2, label='Pre-smooth kernel size', visible=False) | |
| inp.add_rule(go.NORMALMAP_PRE_BLUR_KERNEL, 'visible-if', go.NORMALMAP_PRE_BLUR) | |
| with gr.Row(): | |
| inp += go.NORMALMAP_SOBEL, gr.Checkbox(label="Sobel gradient") | |
| inp += go.NORMALMAP_SOBEL_KERNEL, gr.Slider(minimum=1, maximum=31, step=2, label='Sobel kernel size') | |
| inp.add_rule(go.NORMALMAP_SOBEL_KERNEL, 'visible-if', go.NORMALMAP_SOBEL) | |
| with gr.Row(): | |
| inp += go.NORMALMAP_POST_BLUR, gr.Checkbox(label="Smooth after calculating normals") | |
| inp += go.NORMALMAP_POST_BLUR_KERNEL, gr.Slider(minimum=1, maximum=31, step=2, label='Post-smooth kernel size', visible=False) | |
| inp.add_rule(go.NORMALMAP_POST_BLUR_KERNEL, 'visible-if', go.NORMALMAP_POST_BLUR) | |
| with gr.Row(): | |
| inp += go.NORMALMAP_INVERT, gr.Checkbox(label="Invert") | |
| if backbone.get_opt('depthmap_script_gen_heatmap_from_ui', False): | |
| with gr.Box(): | |
| with gr.Row(): | |
| inp += go.GEN_HEATMAP, gr.Checkbox(label="Generate HeatMap") | |
| with gr.Box(): | |
| with gr.Column(): | |
| inp += go.GEN_SIMPLE_MESH, gr.Checkbox(label="Generate simple 3D mesh") | |
| with gr.Column(visible=False) as mesh_options: | |
| with gr.Row(): | |
| gr.HTML(value="Generates fast, accurate only with ZoeDepth models and no boost, no custom maps.") | |
| with gr.Row(): | |
| inp += go.SIMPLE_MESH_OCCLUDE, gr.Checkbox(label="Remove occluded edges") | |
| inp += go.SIMPLE_MESH_SPHERICAL, gr.Checkbox(label="Equirectangular projection") | |
| if is_depth_tab: | |
| with gr.Box(): | |
| with gr.Column(): | |
| inp += go.GEN_INPAINTED_MESH, gr.Checkbox( | |
| label="Generate 3D inpainted mesh") | |
| with gr.Column(visible=False) as inpaint_options_row_0: | |
| gr.HTML("Generation is sloooow. Required for generating videos from mesh.") | |
| inp += go.GEN_INPAINTED_MESH_DEMOS, gr.Checkbox( | |
| label="Generate 4 demo videos with 3D inpainted mesh.") | |
| gr.HTML("More options for generating video can be found in the Generate video tab.") | |
| with gr.Box(): | |
| # TODO: it should be clear from the UI that there is an option of the background removal | |
| # that does not use the model selected above | |
| with gr.Row(): | |
| inp += go.GEN_REMBG, gr.Checkbox(label="Remove background") | |
| with gr.Column(visible=False) as bgrem_options: | |
| with gr.Row(): | |
| inp += go.SAVE_BACKGROUND_REMOVAL_MASKS, gr.Checkbox(label="Save the foreground masks") | |
| inp += go.PRE_DEPTH_BACKGROUND_REMOVAL, gr.Checkbox(label="Pre-depth background removal") | |
| with gr.Row(): | |
| inp += go.REMBG_MODEL, gr.Dropdown( | |
| label="Rembg Model", type="value", | |
| choices=['u2net', 'u2netp', 'u2net_human_seg', 'silueta', "isnet-general-use", "isnet-anime"]) | |
| with gr.Box(): | |
| gr.HTML(f"{SCRIPT_FULL_NAME}<br/>") | |
| gr.HTML("Information, comment and share @ <a " | |
| "href='https://github.com/thygate/stable-diffusion-webui-depthmap-script'>" | |
| "https://github.com/thygate/stable-diffusion-webui-depthmap-script</a>") | |
| def update_default_net_size(model_type): | |
| w, h = ModelHolder.get_default_net_size(model_type) | |
| return inp[go.NET_WIDTH].update(value=w), inp[go.NET_HEIGHT].update(value=h) | |
| inp[go.MODEL_TYPE].change( | |
| fn=update_default_net_size, | |
| inputs=inp[go.MODEL_TYPE], | |
| outputs=[inp[go.NET_WIDTH], inp[go.NET_HEIGHT]] | |
| ) | |
| inp[go.BOOST].change( # Go boost! Wroom!.. | |
| fn=lambda a, b: (inp[go.NET_SIZE_MATCH].update(visible=not a), | |
| options_depend_on_match_size.update(visible=not a and not b)), | |
| inputs=[inp[go.BOOST], inp[go.NET_SIZE_MATCH]], | |
| outputs=[inp[go.NET_SIZE_MATCH], options_depend_on_match_size] | |
| ) | |
| inp.add_rule(options_depend_on_match_size, 'visible-if-not', go.NET_SIZE_MATCH) | |
| inp[go.TILING_MODE].change( # Go boost! Wroom!.. | |
| fn=lambda a: ( | |
| inp[go.BOOST].update(value=False), inp[go.NET_SIZE_MATCH].update(value=True) | |
| ) if a else (inp[go.BOOST].update(), inp[go.NET_SIZE_MATCH].update()), | |
| inputs=[inp[go.TILING_MODE]], | |
| outputs=[inp[go.BOOST], inp[go.NET_SIZE_MATCH]] | |
| ) | |
| inp.add_rule(options_depend_on_output_depth_1, 'visible-if', go.DO_OUTPUT_DEPTH) | |
| inp.add_rule(go.OUTPUT_DEPTH_INVERT, 'visible-if', go.DO_OUTPUT_DEPTH) | |
| inp.add_rule(go.OUTPUT_DEPTH_COMBINE_AXIS, 'visible-if', go.OUTPUT_DEPTH_COMBINE) | |
| inp.add_rule(go.CLIPDEPTH_MODE, 'visible-if', go.CLIPDEPTH) | |
| inp.add_rule(clip_options_row_1, 'visible-if', go.CLIPDEPTH) | |
| inp[go.CLIPDEPTH_FAR].change( | |
| fn=lambda a, b: a if b < a else b, | |
| inputs=[inp[go.CLIPDEPTH_FAR], inp[go.CLIPDEPTH_NEAR]], | |
| outputs=[inp[go.CLIPDEPTH_NEAR]], | |
| show_progress=False | |
| ) | |
| inp[go.CLIPDEPTH_NEAR].change( | |
| fn=lambda a, b: a if b > a else b, | |
| inputs=[inp[go.CLIPDEPTH_NEAR], inp[go.CLIPDEPTH_FAR]], | |
| outputs=[inp[go.CLIPDEPTH_FAR]], | |
| show_progress=False | |
| ) | |
| inp.add_rule(stereo_options, 'visible-if', go.GEN_STEREO) | |
| inp.add_rule(normalmap_options, 'visible-if', go.GEN_NORMALMAP) | |
| inp.add_rule(mesh_options, 'visible-if', go.GEN_SIMPLE_MESH) | |
| if is_depth_tab: | |
| inp.add_rule(inpaint_options_row_0, 'visible-if', go.GEN_INPAINTED_MESH) | |
| inp.add_rule(bgrem_options, 'visible-if', go.GEN_REMBG) | |
| return inp | |
| def open_folder_action(): | |
| # Adapted from stable-diffusion-webui | |
| f = backbone.get_outpath() | |
| if backbone.get_cmd_opt('hide_ui_dir_config', False): | |
| return | |
| if not os.path.exists(f) or not os.path.isdir(f): | |
| raise Exception("Couldn't open output folder") # .isdir is security-related, do not remove! | |
| import platform | |
| import subprocess as sp | |
| path = os.path.normpath(f) | |
| if platform.system() == "Windows": | |
| os.startfile(path) | |
| elif platform.system() == "Darwin": | |
| sp.Popen(["open", path]) | |
| elif "microsoft-standard-WSL2" in platform.uname().release: | |
| sp.Popen(["wsl-open", path]) | |
| else: | |
| sp.Popen(["xdg-open", path]) | |
| def depthmap_mode_video(inp): | |
| gr.HTML(value="Single video mode allows generating videos from videos. Please " | |
| "keep in mind that all the frames of the video need to be processed - therefore it is important to " | |
| "pick settings so that the generation is not too slow. For the best results, " | |
| "use a zoedepth model, since they provide the highest level of coherency between frames.") | |
| inp += gr.File(elem_id='depthmap_vm_input', label="Video or animated file", | |
| file_count="single", interactive=True, type="file") | |
| inp += gr.Checkbox(elem_id="depthmap_vm_custom_checkbox", | |
| label="Use custom/pregenerated DepthMap video", value=False) | |
| inp += gr.Dropdown(elem_id="depthmap_vm_smoothening_mode", label="Smoothening", | |
| type="value", choices=['none', 'experimental'], value='experimental') | |
| inp += gr.File(elem_id='depthmap_vm_custom', file_count="single", | |
| interactive=True, type="file", visible=False) | |
| with gr.Row(): | |
| inp += gr.Checkbox(elem_id='depthmap_vm_compress_checkbox', label="Compress colorvideos?", value=False) | |
| inp += gr.Slider(elem_id='depthmap_vm_compress_bitrate', label="Bitrate (kbit)", visible=False, | |
| minimum=1000, value=15000, maximum=50000, step=250) | |
| inp.add_rule('depthmap_vm_custom', 'visible-if', 'depthmap_vm_custom_checkbox') | |
| inp.add_rule('depthmap_vm_smoothening_mode', 'visible-if-not', 'depthmap_vm_custom_checkbox') | |
| inp.add_rule('depthmap_vm_compress_bitrate', 'visible-if', 'depthmap_vm_compress_checkbox') | |
| return inp | |
| custom_css = """ | |
| #depthmap_vm_input {height: 75px} | |
| #depthmap_vm_custom {height: 75px} | |
| """ | |
| def on_ui_tabs(): | |
| inp = GradioComponentBundle() | |
| with gr.Blocks(analytics_enabled=False, title="DepthMap", css=custom_css) as depthmap_interface: | |
| with gr.Row(equal_height=False): | |
| with gr.Column(variant='panel'): | |
| inp += 'depthmap_mode', gr.HTML(visible=False, value='0') | |
| with gr.Tabs(): | |
| with gr.TabItem('Single Image') as depthmap_mode_0: | |
| with gr.Group(): | |
| with gr.Row(): | |
| inp += gr.Image(label="Source", source="upload", interactive=True, type="pil", | |
| elem_id="depthmap_input_image") | |
| # TODO: depthmap generation settings should disappear when using this | |
| inp += gr.File(label="Custom DepthMap", file_count="single", interactive=True, | |
| type="file", elem_id='custom_depthmap_img', visible=False) | |
| inp += gr.Checkbox(elem_id="custom_depthmap", label="Use custom DepthMap", value=False) | |
| with gr.TabItem('Batch Process') as depthmap_mode_1: | |
| inp += gr.File(elem_id='image_batch', label="Batch Process", file_count="multiple", | |
| interactive=True, type="file") | |
| with gr.TabItem('Batch from Directory') as depthmap_mode_2: | |
| inp += gr.Textbox(elem_id="depthmap_batch_input_dir", label="Input directory", | |
| **backbone.get_hide_dirs(), | |
| placeholder="A directory on the same machine where the server is running.") | |
| inp += gr.Textbox(elem_id="depthmap_batch_output_dir", label="Output directory", | |
| **backbone.get_hide_dirs(), | |
| placeholder="Leave blank to save images to the default path.") | |
| gr.HTML("Files in the output directory may be overwritten.") | |
| inp += gr.Checkbox(elem_id="depthmap_batch_reuse", | |
| label="Skip generation and use (edited/custom) depthmaps " | |
| "in output directory when a file already exists.", | |
| value=True) | |
| with gr.TabItem('Single Video') as depthmap_mode_3: | |
| inp = depthmap_mode_video(inp) | |
| submit = gr.Button('Generate', elem_id="depthmap_generate", variant='primary') | |
| inp |= main_ui_panel(True) # Main panel is inserted here | |
| unloadmodels = gr.Button('Unload models', elem_id="depthmap_unloadmodels") | |
| with gr.Column(variant='panel'): | |
| with gr.Tabs(elem_id="mode_depthmap_output"): | |
| with gr.TabItem('Depth Output'): | |
| with gr.Group(): | |
| result_images = gr.Gallery(label='Output', show_label=False, | |
| elem_id=f"depthmap_gallery", columns=4) | |
| with gr.Column(): | |
| html_info = gr.HTML() | |
| folder_symbol = '\U0001f4c2' # 📂 | |
| gr.Button(folder_symbol, visible=not backbone.get_cmd_opt('hide_ui_dir_config', False)).click( | |
| fn=lambda: open_folder_action(), inputs=[], outputs=[], | |
| ) | |
| with gr.TabItem('3D Mesh'): | |
| with gr.Group(): | |
| result_depthmesh = gr.Model3D(label="3d Mesh", clear_color=[1.0, 1.0, 1.0, 1.0]) | |
| with gr.Row(): | |
| # loadmesh = gr.Button('Load') | |
| clearmesh = gr.Button('Clear') | |
| with gr.TabItem('Generate video'): | |
| # generate video | |
| with gr.Group(): | |
| with gr.Row(): | |
| gr.Markdown("Generate video from inpainted(!) mesh.") | |
| with gr.Row(): | |
| depth_vid = gr.Video(interactive=False) | |
| with gr.Column(): | |
| vid_html_info_x = gr.HTML() | |
| vid_html_info = gr.HTML() | |
| fn_mesh = gr.Textbox(label="Input Mesh (.ply | .obj)", **backbone.get_hide_dirs(), | |
| placeholder="A file on the same machine where " | |
| "the server is running.") | |
| with gr.Row(): | |
| vid_numframes = gr.Textbox(label="Number of frames", value="300") | |
| vid_fps = gr.Textbox(label="Framerate", value="40") | |
| vid_format = gr.Dropdown(label="Format", choices=['mp4', 'webm'], value='mp4', | |
| type="value", elem_id="video_format") | |
| vid_ssaa = gr.Dropdown(label="SSAA", choices=['1', '2', '3', '4'], value='3', | |
| type="value", elem_id="video_ssaa") | |
| with gr.Row(): | |
| vid_traj = gr.Dropdown(label="Trajectory", | |
| choices=['straight-line', 'double-straight-line', 'circle'], | |
| value='double-straight-line', type="index", | |
| elem_id="video_trajectory") | |
| vid_shift = gr.Textbox(label="Translate: x, y, z", value="-0.015, 0.0, -0.05") | |
| vid_border = gr.Textbox(label="Crop: top, left, bottom, right", | |
| value="0.03, 0.03, 0.05, 0.03") | |
| vid_dolly = gr.Checkbox(label="Dolly", value=False, elem_classes="smalltxt") | |
| with gr.Row(): | |
| submit_vid = gr.Button('Generate Video', elem_id="depthmap_generatevideo", | |
| variant='primary') | |
| inp += inp.enkey_tail() | |
| depthmap_mode_0.select(lambda: '0', None, inp['depthmap_mode']) | |
| depthmap_mode_1.select(lambda: '1', None, inp['depthmap_mode']) | |
| depthmap_mode_2.select(lambda: '2', None, inp['depthmap_mode']) | |
| depthmap_mode_3.select(lambda: '3', None, inp['depthmap_mode']) | |
| def custom_depthmap_change_fn(mode, zero_on, three_on): | |
| hide = mode == '0' and zero_on or mode == '3' and three_on | |
| return inp['custom_depthmap_img'].update(visible=hide), \ | |
| inp['depthmap_gen_row_0'].update(visible=not hide), \ | |
| inp['depthmap_gen_row_1'].update(visible=not hide), \ | |
| inp['depthmap_gen_row_3'].update(visible=not hide), not hide | |
| custom_depthmap_change_els = ['depthmap_mode', 'custom_depthmap', 'depthmap_vm_custom_checkbox'] | |
| for el in custom_depthmap_change_els: | |
| inp[el].change( | |
| fn=custom_depthmap_change_fn, | |
| inputs=[inp[el] for el in custom_depthmap_change_els], | |
| outputs=[inp[st] for st in [ | |
| 'custom_depthmap_img', 'depthmap_gen_row_0', 'depthmap_gen_row_1', 'depthmap_gen_row_3', | |
| go.DO_OUTPUT_DEPTH]]) | |
| unloadmodels.click( | |
| fn=unload_models, | |
| inputs=[], | |
| outputs=[] | |
| ) | |
| clearmesh.click( | |
| fn=lambda: None, | |
| inputs=[], | |
| outputs=[result_depthmesh] | |
| ) | |
| submit.click( | |
| fn=backbone.wrap_gradio_gpu_call(run_generate), | |
| inputs=inp.enkey_body(), | |
| outputs=[ | |
| result_images, | |
| fn_mesh, | |
| result_depthmesh, | |
| html_info | |
| ] | |
| ) | |
| submit_vid.click( | |
| fn=backbone.wrap_gradio_gpu_call(run_makevideo), | |
| inputs=[ | |
| fn_mesh, | |
| vid_numframes, | |
| vid_fps, | |
| vid_traj, | |
| vid_shift, | |
| vid_border, | |
| vid_dolly, | |
| vid_format, | |
| vid_ssaa | |
| ], | |
| outputs=[ | |
| depth_vid, | |
| vid_html_info_x, | |
| vid_html_info | |
| ] | |
| ) | |
| return depthmap_interface | |
| def format_exception(e: Exception): | |
| traceback.print_exc() | |
| msg = '<h3>' + 'ERROR: ' + str(e) + '</h3>' + '\n' | |
| if 'out of GPU memory' in msg: | |
| pass | |
| elif "torch.hub.load('facebookresearch/dinov2'," in traceback.format_exc(): | |
| msg += ('<h4>To use Depth Anything integration in WebUI mode, please add "--disable-safe-unpickle" to the command line flags. ' | |
| 'Alternatively, use Standalone mode. This is a known issue.') | |
| elif "Error(s) in loading state_dict " in traceback.format_exc(): | |
| msg += ('<h4>There was issue during loading the model.' | |
| 'Please add "--disable-safe-unpickle" to the command line flags. This is a known issue.') | |
| elif 'out of GPU memory' not in msg: | |
| msg += \ | |
| 'Please report this issue ' \ | |
| f'<a href="https://github.com/thygate/{REPOSITORY_NAME}/issues">here</a>. ' \ | |
| 'Make sure to provide the full stacktrace: \n' | |
| msg += '<code style="white-space: pre;">' + traceback.format_exc() + '</code>' | |
| return msg | |
| def run_generate(*inputs): | |
| inputs = GradioComponentBundle.enkey_to_dict(inputs) | |
| depthmap_mode = inputs['depthmap_mode'] | |
| depthmap_batch_input_dir = inputs['depthmap_batch_input_dir'] | |
| image_batch = inputs['image_batch'] | |
| depthmap_input_image = inputs['depthmap_input_image'] | |
| depthmap_batch_output_dir = inputs['depthmap_batch_output_dir'] | |
| depthmap_batch_reuse = inputs['depthmap_batch_reuse'] | |
| custom_depthmap = inputs['custom_depthmap'] | |
| custom_depthmap_img = inputs['custom_depthmap_img'] | |
| inputimages = [] | |
| inputdepthmaps = [] # Allow supplying custom depthmaps | |
| inputnames = [] # Also keep track of original file names | |
| if depthmap_mode == '3': | |
| try: | |
| custom_depthmap = inputs['depthmap_vm_custom'] \ | |
| if inputs['depthmap_vm_custom_checkbox'] else None | |
| colorvids_bitrate = inputs['depthmap_vm_compress_bitrate'] \ | |
| if inputs['depthmap_vm_compress_checkbox'] else None | |
| ret = video_mode.gen_video( | |
| inputs['depthmap_vm_input'], backbone.get_outpath(), inputs, custom_depthmap, colorvids_bitrate, | |
| inputs['depthmap_vm_smoothening_mode']) | |
| return [], None, None, ret | |
| except Exception as e: | |
| ret = format_exception(e) | |
| return [], None, None, ret | |
| if depthmap_mode == '2' and depthmap_batch_output_dir != '': | |
| outpath = depthmap_batch_output_dir | |
| else: | |
| outpath = backbone.get_outpath() | |
| if depthmap_mode == '0': # Single image | |
| if depthmap_input_image is None: | |
| return [], None, None, "Please select an input image" | |
| inputimages.append(depthmap_input_image) | |
| inputnames.append(None) | |
| if custom_depthmap: | |
| if custom_depthmap_img is None: | |
| return [], None, None, \ | |
| "Custom depthmap is not specified. Please either supply it or disable this option." | |
| inputdepthmaps.append(Image.open(os.path.abspath(custom_depthmap_img.name))) | |
| else: | |
| inputdepthmaps.append(None) | |
| if depthmap_mode == '1': # Batch Process | |
| if image_batch is None: | |
| return [], None, None, "Please select input images", "" | |
| for img in image_batch: | |
| image = Image.open(os.path.abspath(img.name)) | |
| inputimages.append(image) | |
| inputnames.append(os.path.splitext(img.orig_name)[0]) | |
| print(f'{len(inputimages)} images will be processed') | |
| elif depthmap_mode == '2': # Batch from Directory | |
| # TODO: There is a RAM leak when we process batches, I can smell it! Or maybe it is gone. | |
| assert not backbone.get_cmd_opt('hide_ui_dir_config', False), '--hide-ui-dir-config option must be disabled' | |
| if depthmap_batch_input_dir == '': | |
| return [], None, None, "Please select an input directory." | |
| if depthmap_batch_input_dir == depthmap_batch_output_dir: | |
| return [], None, None, "Please pick different directories for batch processing." | |
| image_list = backbone.listfiles(depthmap_batch_input_dir) | |
| for path in image_list: | |
| try: | |
| inputimages.append(Image.open(path)) | |
| inputnames.append(path) | |
| custom_depthmap = None | |
| if depthmap_batch_reuse: | |
| basename = Path(path).stem | |
| # Custom names are not used in samples directory | |
| if outpath != backbone.get_opt('outdir_extras_samples', None): | |
| # Possible filenames that the custom depthmaps may have | |
| name_candidates = [f'{basename}-0000.{backbone.get_opt("samples_format", "png")}', # current format | |
| f'{basename}.png', # human-intuitive format | |
| f'{Path(path).name}'] # human-intuitive format (worse) | |
| for fn_cand in name_candidates: | |
| path_cand = os.path.join(outpath, fn_cand) | |
| if os.path.isfile(path_cand): | |
| custom_depthmap = Image.open(os.path.abspath(path_cand)) | |
| break | |
| inputdepthmaps.append(custom_depthmap) | |
| except Exception as e: | |
| print(f'Failed to load {path}, ignoring. Exception: {str(e)}') | |
| inputdepthmaps_n = len([1 for x in inputdepthmaps if x is not None]) | |
| print(f'{len(inputimages)} images will be processed, {inputdepthmaps_n} existing depthmaps will be reused') | |
| gen_obj = core_generation_funnel(outpath, inputimages, inputdepthmaps, inputnames, inputs, backbone.gather_ops()) | |
| # Saving images | |
| img_results = [] | |
| results_total = 0 | |
| inpainted_mesh_fi = mesh_simple_fi = None | |
| msg = "" # Empty string is never returned | |
| while True: | |
| try: | |
| input_i, type, result = next(gen_obj) | |
| results_total += 1 | |
| except StopIteration: | |
| # TODO: return more info | |
| msg = '<h3>Successfully generated</h3>' if results_total > 0 else \ | |
| '<h3>Successfully generated nothing - please check the settings and try again</h3>' | |
| break | |
| except Exception as e: | |
| msg = format_exception(e) | |
| break | |
| if type == 'simple_mesh': | |
| mesh_simple_fi = result | |
| continue | |
| if type == 'inpainted_mesh': | |
| inpainted_mesh_fi = result | |
| continue | |
| if not isinstance(result, Image.Image): | |
| print(f'This is not supposed to happen! Somehow output type {type} is not supported! Input_i: {input_i}.') | |
| continue | |
| img_results += [(input_i, type, result)] | |
| if inputs["save_outputs"]: | |
| try: | |
| basename = 'depthmap' | |
| if depthmap_mode == '2' and inputnames[input_i] is not None: | |
| if outpath != backbone.get_opt('outdir_extras_samples', None): | |
| basename = Path(inputnames[input_i]).stem | |
| suffix = "" if type == "depth" else f"{type}" | |
| backbone.save_image(result, path=outpath, basename=basename, seed=None, | |
| prompt=None, extension=backbone.get_opt('samples_format', 'png'), short_filename=True, | |
| no_prompt=True, grid=False, pnginfo_section_name="extras", | |
| suffix=suffix) | |
| except Exception as e: | |
| if not ('image has wrong mode' in str(e) or 'I;16' in str(e)): | |
| raise e | |
| print('Catched exception: image has wrong mode!') | |
| traceback.print_exc() | |
| # Deciding what mesh to display (and if) | |
| display_mesh_fi = None | |
| if backbone.get_opt('depthmap_script_show_3d', True): | |
| display_mesh_fi = mesh_simple_fi | |
| if backbone.get_opt('depthmap_script_show_3d_inpaint', True): | |
| if inpainted_mesh_fi is not None and len(inpainted_mesh_fi) > 0: | |
| display_mesh_fi = inpainted_mesh_fi | |
| return map(lambda x: x[2], img_results), inpainted_mesh_fi, display_mesh_fi, msg.replace('\n', '<br>') | |