Spaces:
Runtime error
Runtime error
Return depth as 16-bit PNG via gr.File (preserve full precision)
Browse files
app.py
CHANGED
|
@@ -56,6 +56,8 @@ except Exception as _e:
|
|
| 56 |
print(f"[warn] gradio_client patch failed: {_e}")
|
| 57 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 58 |
|
|
|
|
|
|
|
| 59 |
import numpy as np
|
| 60 |
import spaces
|
| 61 |
import torch
|
|
@@ -75,22 +77,40 @@ def _get_pipe(task: str):
|
|
| 75 |
return _pipes[task]
|
| 76 |
|
| 77 |
|
| 78 |
-
def
|
| 79 |
-
"""
|
| 80 |
-
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
"""
|
| 83 |
arr = np.array(img)
|
|
|
|
|
|
|
| 84 |
if arr.dtype == np.uint16:
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
|
| 90 |
@spaces.GPU
|
| 91 |
def infer_depth(image_path):
|
| 92 |
pipe = _get_pipe("depth")
|
| 93 |
-
|
|
|
|
| 94 |
|
| 95 |
|
| 96 |
@spaces.GPU
|
|
@@ -101,11 +121,12 @@ def infer_normal(image_path):
|
|
| 101 |
|
| 102 |
with gr.Blocks(title="Lotus 1 - Depth + Normal") as demo:
|
| 103 |
gr.Markdown("# Lotus 1 - Depth & Normal")
|
| 104 |
-
gr.Markdown("API: `/depth` returns
|
|
|
|
| 105 |
|
| 106 |
with gr.Tab("Depth"):
|
| 107 |
d_in = gr.Image(label="Input", type="filepath")
|
| 108 |
-
d_out = gr.
|
| 109 |
d_btn = gr.Button("Run depth")
|
| 110 |
d_btn.click(infer_depth, inputs=d_in, outputs=d_out, api_name="depth")
|
| 111 |
|
|
|
|
| 56 |
print(f"[warn] gradio_client patch failed: {_e}")
|
| 57 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 58 |
|
| 59 |
+
import tempfile
|
| 60 |
+
|
| 61 |
import numpy as np
|
| 62 |
import spaces
|
| 63 |
import torch
|
|
|
|
| 77 |
return _pipes[task]
|
| 78 |
|
| 79 |
|
| 80 |
+
def _save_16bit_png(img: Image.Image) -> str:
|
| 81 |
+
"""Save the depth map as a true 16-bit PNG and return the path.
|
| 82 |
+
|
| 83 |
+
colorize_depth_map (modified previously) already returns a uint16 PIL
|
| 84 |
+
Image. The default gr.Image output would re-encode it as 8-bit webp,
|
| 85 |
+
which destroys the upper byte and yields visible stepping in the
|
| 86 |
+
fabricated relief (~20 Β΅m per step over a 5 mm relief). Returning
|
| 87 |
+
a file path via gr.File bypasses Gradio's image processing entirely.
|
| 88 |
"""
|
| 89 |
arr = np.array(img)
|
| 90 |
+
fd, tmp_path = tempfile.mkstemp(suffix='_depth16.png')
|
| 91 |
+
os.close(fd)
|
| 92 |
if arr.dtype == np.uint16:
|
| 93 |
+
# Native 16-bit path β preserve all 65,536 levels
|
| 94 |
+
Image.fromarray(arr, mode="I;16").save(tmp_path, format="PNG")
|
| 95 |
+
elif arr.dtype == np.uint8:
|
| 96 |
+
# Up-promote to 16-bit (no extra precision, but consistent output)
|
| 97 |
+
arr16 = arr.astype(np.uint16) * 257 # 0->0, 255->65535
|
| 98 |
+
Image.fromarray(arr16, mode="I;16").save(tmp_path, format="PNG")
|
| 99 |
+
else:
|
| 100 |
+
# Float / other β normalise to 16-bit
|
| 101 |
+
a = arr.astype(np.float32)
|
| 102 |
+
rng = max(a.max() - a.min(), 1e-9)
|
| 103 |
+
a = (a - a.min()) / rng
|
| 104 |
+
Image.fromarray((a * 65535).astype(np.uint16),
|
| 105 |
+
mode="I;16").save(tmp_path, format="PNG")
|
| 106 |
+
return tmp_path
|
| 107 |
|
| 108 |
|
| 109 |
@spaces.GPU
|
| 110 |
def infer_depth(image_path):
|
| 111 |
pipe = _get_pipe("depth")
|
| 112 |
+
img = infer_pipe(pipe, image_path, "depth", SEED, device)
|
| 113 |
+
return _save_16bit_png(img)
|
| 114 |
|
| 115 |
|
| 116 |
@spaces.GPU
|
|
|
|
| 121 |
|
| 122 |
with gr.Blocks(title="Lotus 1 - Depth + Normal") as demo:
|
| 123 |
gr.Markdown("# Lotus 1 - Depth & Normal")
|
| 124 |
+
gr.Markdown("API: `/depth` returns a **16-bit grayscale PNG** depth map, "
|
| 125 |
+
"`/normal` returns an RGB normal map.")
|
| 126 |
|
| 127 |
with gr.Tab("Depth"):
|
| 128 |
d_in = gr.Image(label="Input", type="filepath")
|
| 129 |
+
d_out = gr.File(label="Depth (16-bit PNG)")
|
| 130 |
d_btn = gr.Button("Run depth")
|
| 131 |
d_btn.click(infer_depth, inputs=d_in, outputs=d_out, api_name="depth")
|
| 132 |
|