Spaces:
Running
on
Zero
Running
on
Zero
import gradio as gr | |
import os | |
import imageio | |
import numpy as np | |
from einops import rearrange | |
from demo.img_gen import img_gen | |
from demo.mesh_recon import mesh_reconstruction | |
from demo.relighting_gen import relighting_gen | |
from demo.render_hints import render_hint_images_btn_func | |
from demo.rm_bg import rm_bg | |
with gr.Blocks(title="DiLightNet Demo") as demo: | |
gr.Markdown("""# DiLightNet: Fine-grained Lighting Control for Diffusion-based Image Generation | |
## A demo for generating images under point/environmantal lighting using DiLightNet. For full usage (video generation & arbitary lighting condition), please refer to our [GitHub repository](https://github.com/iamNCJ/DiLightNet)""") | |
with gr.Row(): | |
# 1. Reference Image Input / Generation | |
with gr.Column(variant="panel"): | |
gr.Markdown("## Step 1. Input or Generate Reference Image") | |
input_image = gr.Image(height=512, width=512, label="Input Image", interactive=True) | |
with gr.Accordion("Generate Image", open=False): | |
with gr.Group(): | |
prompt = gr.Textbox(value="", label="Prompt", lines=3, placeholder="Input prompt here") | |
with gr.Row(): | |
seed = gr.Number(value=42, label="Seed", interactive=True) | |
steps = gr.Number(value=20, label="Steps", interactive=True) | |
cfg = gr.Number(value=7.5, label="CFG", interactive=True) | |
down_from_768 = gr.Checkbox(label="Downsample from 768", value=True) | |
with gr.Row(): | |
generate_btn = gr.Button(value="Generate") | |
generate_btn.click(fn=img_gen, inputs=[prompt, seed, steps, cfg, down_from_768], outputs=[input_image]) | |
gr.Examples( | |
examples=[os.path.join("examples/provisional_img", i) for i in os.listdir("examples/provisional_img")], | |
inputs=[input_image], | |
examples_per_page = 20, | |
) | |
# 2. Background Removal | |
with gr.Column(variant="panel"): | |
gr.Markdown("## Step 2. Remove Background") | |
with gr.Tab("Masked Image"): | |
masked_image = gr.Image(height=512, width=512, label="Masked Image", interactive=True) | |
with gr.Tab("Mask"): | |
mask = gr.Image(height=512, width=512, label="Mask", interactive=False) | |
use_sam = gr.Checkbox(label="Use SAM for Refinement", value=False) | |
rm_bg_btn = gr.Button(value="Remove Background") | |
rm_bg_btn.click(fn=rm_bg, inputs=[input_image, use_sam], outputs=[masked_image, mask]) | |
# 3. Depth Estimation & Mesh Reconstruction | |
with gr.Column(variant="panel"): | |
gr.Markdown("## Step 3. Depth Estimation & Mesh Reconstruction") | |
mesh = gr.Model3D(label="Mesh Reconstruction", clear_color=(1.0, 1.0, 1.0, 1.0), interactive=True) | |
with gr.Column(): | |
with gr.Accordion("Options", open=False): | |
with gr.Group(): | |
remove_edges = gr.Checkbox(label="Remove Occlusion Edges", value=False) | |
fov = gr.Number(value=55., label="FOV", interactive=False) | |
mask_threshold = gr.Slider(value=25., label="Mask Threshold", minimum=0., maximum=255., step=1.) | |
depth_estimation_btn = gr.Button(value="Estimate Depth") | |
def mesh_reconstruction_wrapper(image, mask, remove_edges, mask_threshold, | |
progress=gr.Progress(track_tqdm=True)): | |
return mesh_reconstruction(image, mask, remove_edges, None, mask_threshold) | |
depth_estimation_btn.click( | |
fn=mesh_reconstruction_wrapper, | |
inputs=[input_image, mask, remove_edges, mask_threshold], | |
outputs=[mesh, fov], | |
) | |
gr.Markdown("## Step 4. Render Hints") | |
with gr.Row(): | |
with gr.Column(): | |
hint_image = gr.Image(label="Hint Image", height=512, width=512) | |
with gr.Column(): | |
res_folder_path = gr.Textbox("", visible=False) | |
is_env_lighting = gr.Checkbox(label="Use Environmental Lighting", value=True, interactive=False, visible=False) | |
with gr.Tab("Environmental Lighting"): | |
env_map_preview = gr.Image(label="Environment Map Preview", height=256, width=512, interactive=False, show_download_button=False) | |
env_map_path = gr.Text(interactive=False, visible=False, value="examples/env_map/grace.exr") | |
env_rotation = gr.Slider(value=0., label="Environment Rotation", minimum=0., maximum=360., step=0.5) | |
env_examples = gr.Examples( | |
examples=[[os.path.join("examples/env_map_preview", i), os.path.join("examples/env_map", i).replace("png", "exr")] for i in os.listdir("examples/env_map_preview")], | |
inputs=[env_map_preview, env_map_path], | |
examples_per_page = 20, | |
) | |
render_btn_env = gr.Button(value="Render Hints") | |
def render_wrapper_env(mesh, fov, env_map_path, env_rotation, progress=gr.Progress(track_tqdm=True)): | |
env_map_path = os.path.abspath(env_map_path) | |
res_path = render_hint_images_btn_func(mesh, float(fov), [(0, 0, 0)], env_map=env_map_path, env_start_azi=env_rotation / 360.) | |
hint_files = [res_path + '/hint00' + mat for mat in ["_diffuse.png", "_ggx0.05.png", "_ggx0.13.png", "_ggx0.34.png"]] | |
hints = [] | |
for hint_file in hint_files: | |
hint = imageio.v3.imread(hint_file) | |
hints.append(hint) | |
hints = rearrange(np.stack(hints), '(n1 n2) h w c -> (n1 h) (n2 w) c', n1=2, n2=2) | |
return hints, res_path, True | |
render_btn_env.click( | |
fn=render_wrapper_env, | |
inputs=[mesh, fov, env_map_path, env_rotation], | |
outputs=[hint_image, res_folder_path, is_env_lighting] | |
) | |
with gr.Tab("Point Lighting"): | |
pl_pos_x = gr.Slider(value=3., label="Point Light X", minimum=-5., maximum=5., step=0.01) | |
pl_pos_y = gr.Slider(value=1., label="Point Light Y", minimum=-5., maximum=5., step=0.01) | |
pl_pos_z = gr.Slider(value=3., label="Point Light Z", minimum=-5., maximum=5., step=0.01) | |
power = gr.Slider(value=1000., label="Point Light Power", minimum=0., maximum=2000., step=1.) | |
render_btn_pl = gr.Button(value="Render Hints") | |
def render_wrapper_pl(mesh, fov, pl_pos_x, pl_pos_y, pl_pos_z, power, | |
progress=gr.Progress(track_tqdm=True)): | |
res_path = render_hint_images_btn_func(mesh, float(fov), [(pl_pos_x, pl_pos_y, pl_pos_z)], power) | |
hint_files = [res_path + '/hint00' + mat for mat in ["_diffuse.png", "_ggx0.05.png", "_ggx0.13.png", "_ggx0.34.png"]] | |
hints = [] | |
for hint_file in hint_files: | |
hint = imageio.v3.imread(hint_file) | |
hints.append(hint) | |
hints = rearrange(np.stack(hints), '(n1 n2) h w c -> (n1 h) (n2 w) c', n1=2, n2=2) | |
return hints, res_path, False | |
render_btn_pl.click( | |
fn=render_wrapper_pl, | |
inputs=[mesh, fov, pl_pos_x, pl_pos_y, pl_pos_z, power], | |
outputs=[hint_image, res_folder_path, is_env_lighting] | |
) | |
gr.Markdown("## Step 5. Control Lighting!") | |
with gr.Row(): | |
res_image = gr.Image(label="Result Image") | |
with gr.Column(): | |
with gr.Group(): | |
with gr.Row(): | |
relighting_prompt = gr.Textbox(value="", label="Appearance Text Prompt", lines=3, | |
placeholder="Input prompt here", | |
interactive=True) | |
with gr.Row(): | |
# several example prompts | |
metallic_prompt_btn = gr.Button(value="Metallic", size="sm") | |
specular_prompt_btn = gr.Button(value="Specular", size="sm") | |
very_specular_prompt_btn = gr.Button(value="Very Specular", size="sm") | |
clear_prompt_btn = gr.Button(value="Clear", size="sm") | |
metallic_prompt_btn.click(fn=lambda x: x + " metallic", inputs=[relighting_prompt], outputs=[relighting_prompt]) | |
specular_prompt_btn.click(fn=lambda x: x + " specular", inputs=[relighting_prompt], outputs=[relighting_prompt]) | |
very_specular_prompt_btn.click(fn=lambda x: x + " very specular", inputs=[relighting_prompt], outputs=[relighting_prompt]) | |
clear_prompt_btn.click(fn=lambda x: "", inputs=[relighting_prompt], outputs=[relighting_prompt]) | |
with gr.Row(): | |
reuse_btn = gr.Button(value="Reuse Provisional Image Generation Prompt") | |
reuse_btn.click(fn=lambda x: x, inputs=[prompt], outputs=[relighting_prompt]) | |
with gr.Accordion("Options", open=False): | |
with gr.Row(): | |
relighting_seed = gr.Number(value=3407, label="Seed", interactive=True) | |
relighting_steps = gr.Number(value=20, label="Steps", interactive=True) | |
relighting_cfg = gr.Number(value=3.0, label="CFG", interactive=True) | |
with gr.Row(): | |
relighting_generate_btn = gr.Button(value="Generate") | |
def gen_relighting_image(masked_image, mask, res_folder_path, relighting_prompt, relighting_seed, | |
relighting_steps, relighting_cfg, do_env_inpainting, | |
progress=gr.Progress(track_tqdm=True)): | |
relighting_gen( | |
masked_ref_img=masked_image, | |
mask=mask, | |
cond_path=res_folder_path, | |
frames=1, | |
prompt=relighting_prompt, | |
steps=int(relighting_steps), | |
seed=int(relighting_seed), | |
cfg=relighting_cfg | |
) | |
relit_img = imageio.v3.imread(res_folder_path + '/relighting00.png') | |
if do_env_inpainting: | |
bg = imageio.v3.imread(res_folder_path + f'/bg00.png') / 255. | |
relit_img = relit_img / 255. | |
mask_for_bg = imageio.v3.imread(res_folder_path + '/hint00_diffuse.png')[..., -1:] / 255. | |
relit_img = relit_img * mask_for_bg + bg * (1. - mask_for_bg) | |
relit_img = (relit_img * 255).clip(0, 255).astype(np.uint8) | |
return relit_img | |
relighting_generate_btn.click(fn=gen_relighting_image, | |
inputs=[masked_image, mask, res_folder_path, relighting_prompt, relighting_seed, | |
relighting_steps, relighting_cfg, is_env_lighting], | |
outputs=[res_image]) | |
if __name__ == '__main__': | |
demo.queue().launch(server_name="0.0.0.0", share=True) | |