Spaces:
Runtime error
Runtime error
[Admin maintenance] Support new ZeroGPU hardware
#2
by multimodalart HF Staff - opened
- README.md +1 -1
- app.py +151 -44
- lvdm/modules/encoders/condition.py +11 -3
- requirements.txt +15 -19
- utils/pvd_utils.py +15 -2
README.md
CHANGED
|
@@ -4,7 +4,7 @@ emoji: 🐨
|
|
| 4 |
colorFrom: yellow
|
| 5 |
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: other
|
|
|
|
| 4 |
colorFrom: yellow
|
| 5 |
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.49.1
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: other
|
app.py
CHANGED
|
@@ -1,13 +1,142 @@
|
|
| 1 |
import os
|
| 2 |
-
import torch
|
| 3 |
import sys
|
| 4 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
import random
|
| 7 |
import gradio as gr
|
| 8 |
-
import random
|
| 9 |
from configs.infer_config import get_parser
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
traj_examples = [
|
| 13 |
['0 -35; 0 0; 0 -0.1'],
|
|
@@ -27,6 +156,7 @@ img_examples = [
|
|
| 27 |
|
| 28 |
max_seed = 2 ** 31
|
| 29 |
|
|
|
|
| 30 |
def download_model():
|
| 31 |
REPO_ID = 'Drexubery/ViewCrafter_25'
|
| 32 |
filename_list = ['model.ckpt']
|
|
@@ -34,29 +164,16 @@ def download_model():
|
|
| 34 |
local_file = os.path.join('./checkpoints/', filename)
|
| 35 |
if not os.path.exists(local_file):
|
| 36 |
hf_hub_download(repo_id=REPO_ID, filename=filename, local_dir='./checkpoints/', force_download=True)
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
|
|
|
| 41 |
tmp = str(random.randint(10**(5-1), 10**5 - 1))
|
| 42 |
opts.save_dir = f'./{tmp}'
|
| 43 |
-
os.makedirs(opts.save_dir,exist_ok=True)
|
| 44 |
-
|
| 45 |
-
opts.
|
| 46 |
-
opts.config = './configs/inference_pvd_1024_gradio.yaml' #fixme
|
| 47 |
-
# opts.config = './configs/inference_pvd_1024_local.yaml' #fixme
|
| 48 |
-
|
| 49 |
-
# install pytorch3d # fixme
|
| 50 |
-
pyt_version_str=torch.__version__.split("+")[0].replace(".", "")
|
| 51 |
-
version_str="".join([
|
| 52 |
-
f"py3{sys.version_info.minor}_cu",
|
| 53 |
-
torch.version.cuda.replace(".",""),
|
| 54 |
-
f"_pyt{pyt_version_str}"
|
| 55 |
-
])
|
| 56 |
-
print(version_str)
|
| 57 |
-
os.system(f"{sys.executable} -m pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html")
|
| 58 |
-
os.system("mkdir -p checkpoints/ && wget https://download.europe.naverlabs.com/ComputerVision/DUSt3R/DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth -P checkpoints/")
|
| 59 |
-
print(f'>>> System info: {version_str}')
|
| 60 |
|
| 61 |
|
| 62 |
from viewcrafter import ViewCrafter
|
|
@@ -86,7 +203,7 @@ def show_traj(mode):
|
|
| 86 |
def viewcrafter_demo(opts):
|
| 87 |
css = """#input_img {max-width: 1024px !important} #output_vid {max-width: 1024px; max-height:576px} #random_button {max-width: 100px !important}"""
|
| 88 |
image2video = ViewCrafter(opts, gradio = True)
|
| 89 |
-
image2video.run_both = spaces.GPU(image2video.run_both, duration=290)
|
| 90 |
with gr.Blocks(analytics_enabled=False, css=css) as viewcrafter_iface:
|
| 91 |
gr.Markdown("<div align='center'> <h1> ViewCrafter: Taming Video Diffusion Models for High-fidelity Novel View Synthesis </span> </h1> \
|
| 92 |
<h2 style='font-weight: 450; font-size: 1rem; margin: 0rem'>\
|
|
@@ -106,10 +223,6 @@ def viewcrafter_demo(opts):
|
|
| 106 |
|
| 107 |
with gr.Row():
|
| 108 |
with gr.Column():
|
| 109 |
-
# # step 1: input an image
|
| 110 |
-
# gr.Markdown("---\n## Step 1: Input an Image, selet an elevation angle and a center_scale factor", show_label=False, visible=True)
|
| 111 |
-
# gr.Markdown("<div align='left' style='font-size:18px;color: #000000'>1. Estimate an elevation angle that represents the angle at which the image was taken; a value bigger than 0 indicates a top-down view, and it doesn't need to be precise. <br>2. The origin of the world coordinate system is by default defined at the point cloud corresponding to the center pixel of the input image. You can adjust the position of the origin by modifying center_scale; a value smaller than 1 brings the origin closer to you.</div>")
|
| 112 |
-
|
| 113 |
with gr.Column():
|
| 114 |
i2v_input_image = gr.Image(label="Input Image",elem_id="input_img")
|
| 115 |
with gr.Row():
|
|
@@ -120,11 +233,11 @@ def viewcrafter_demo(opts):
|
|
| 120 |
left = gr.Button(value = "Left")
|
| 121 |
right = gr.Button(value = "Right")
|
| 122 |
up = gr.Button(value = "Up")
|
| 123 |
-
with gr.Row():
|
| 124 |
-
down = gr.Button(value = "Down")
|
| 125 |
zin = gr.Button(value = "Zoom in")
|
| 126 |
zout = gr.Button(value = "Zoom out")
|
| 127 |
-
with gr.Row():
|
| 128 |
custom = gr.Button(value = "Customize")
|
| 129 |
reset = gr.Button(value = "Reset")
|
| 130 |
|
|
@@ -136,25 +249,21 @@ def viewcrafter_demo(opts):
|
|
| 136 |
gr.Markdown("<div align='left' style='font-size:18px;color: #000000'>Please refer to the <a href='https://github.com/Drexubery/ViewCrafter/blob/main/docs/gradio_tutorial.md' target='_blank'>tutorial</a> for customizing camera trajectory.</div>")
|
| 137 |
gr.Examples(examples=traj_examples,
|
| 138 |
inputs=[i2v_pose],
|
| 139 |
-
)
|
| 140 |
|
| 141 |
|
| 142 |
-
# step 3 - Generate video
|
| 143 |
with gr.Column():
|
| 144 |
-
# gr.Markdown("---\n## Step 3: Generate video", show_label=False, visible=True)
|
| 145 |
-
# gr.Markdown("<div align='left' style='font-size:18px;color: #000000'> You can reduce the sampling steps for faster inference; try different random seed if the result is not satisfying. </div>")
|
| 146 |
i2v_output_video = gr.Video(label="Generated Video",elem_id="output_vid",autoplay=True,show_share_button=True)
|
| 147 |
with gr.Row():
|
| 148 |
i2v_steps = gr.Slider(minimum=1, maximum=50, step=1, elem_id="i2v_steps", label="Sampling steps", value=50)
|
| 149 |
i2v_seed = gr.Slider(label='Random seed', minimum=0, maximum=max_seed, step=1, value=0)
|
| 150 |
-
i2v_end_btn = gr.Button("Generate video")
|
| 151 |
i2v_traj_video = gr.Video(label="Camera Trajectory",elem_id="traj_vid",autoplay=True,show_share_button=True)
|
| 152 |
|
| 153 |
-
|
| 154 |
gr.Examples(examples=img_examples,
|
| 155 |
inputs=[i2v_input_image,i2v_elevation, i2v_center_scale,],
|
| 156 |
-
|
| 157 |
-
)
|
| 158 |
|
| 159 |
|
| 160 |
|
|
@@ -201,6 +310,4 @@ def viewcrafter_demo(opts):
|
|
| 201 |
|
| 202 |
viewcrafter_iface = viewcrafter_demo(opts)
|
| 203 |
viewcrafter_iface.queue(max_size=10)
|
| 204 |
-
viewcrafter_iface.launch()
|
| 205 |
-
# viewcrafter_iface.launch(server_name='11.220.92.96', server_port=80, max_threads=10,debug=True)
|
| 206 |
-
|
|
|
|
| 1 |
import os
|
|
|
|
| 2 |
import sys
|
| 3 |
+
import subprocess
|
| 4 |
+
|
| 5 |
+
# ---------------------------------------------------------------------------
|
| 6 |
+
# Blackwell ZeroGPU shim — env + heavy CUDA-extension build
|
| 7 |
+
# ---------------------------------------------------------------------------
|
| 8 |
+
# pytorch3d publishes prebuilt wheels only for torch <= 2.4. On the new
|
| 9 |
+
# Blackwell ZeroGPU stack (torch 2.10/2.11, CUDA 13) the old offline-install
|
| 10 |
+
# block in this file simply fails. Build pytorch3d from source the first time
|
| 11 |
+
# we get a GPU, the same way the Blackwell playbook recommends for
|
| 12 |
+
# nvdiffrast / diff_gaussian_rasterization.
|
| 13 |
+
|
| 14 |
+
import spaces # MUST come before torch / CUDA-touching imports
|
| 15 |
+
import torch
|
| 16 |
+
|
| 17 |
+
# torch.load weights_only flipped in 2.6 — old ckpts (DUSt3R/dynamicrafter) use
|
| 18 |
+
# argparse Namespaces / numpy scalars that the new default refuses to unpickle.
|
| 19 |
+
_orig_torch_load = torch.load
|
| 20 |
+
def _patched_torch_load(*args, **kwargs):
|
| 21 |
+
kwargs.setdefault("weights_only", False)
|
| 22 |
+
return _orig_torch_load(*args, **kwargs)
|
| 23 |
+
torch.load = _patched_torch_load
|
| 24 |
+
|
| 25 |
+
# xformers on the Blackwell ZeroGPU wheel ships without CUDA-built ops for
|
| 26 |
+
# sm_120: FA3 needs cap <= 9.0, Cutlass needs cap <= 9.0 too. Every op raises
|
| 27 |
+
# `NotImplementedError`. Replace `xformers.ops.memory_efficient_attention` with
|
| 28 |
+
# a torch-native SDPA equivalent so existing call-sites keep working.
|
| 29 |
+
def _mea_sdpa(q, k, v, attn_bias=None, p=0.0, scale=None, op=None):
|
| 30 |
+
# xformers convention: q/k/v shaped (B, M, H, K) or (B*H, M, K).
|
| 31 |
+
# The lvdm code path passes 3D (B*H, M, K). Convert to (B*H, 1, M, K)
|
| 32 |
+
# for F.scaled_dot_product_attention.
|
| 33 |
+
import torch.nn.functional as F
|
| 34 |
+
is_3d = (q.ndim == 3)
|
| 35 |
+
if is_3d:
|
| 36 |
+
q = q.unsqueeze(1); k = k.unsqueeze(1); v = v.unsqueeze(1)
|
| 37 |
+
elif q.ndim == 4:
|
| 38 |
+
# (B, M, H, K) -> (B, H, M, K)
|
| 39 |
+
q = q.transpose(1, 2); k = k.transpose(1, 2); v = v.transpose(1, 2)
|
| 40 |
+
mask = None
|
| 41 |
+
if attn_bias is not None and hasattr(attn_bias, "to_tensor"):
|
| 42 |
+
mask = attn_bias.to_tensor()
|
| 43 |
+
elif attn_bias is not None and torch.is_tensor(attn_bias):
|
| 44 |
+
mask = attn_bias
|
| 45 |
+
out = F.scaled_dot_product_attention(q, k, v, attn_mask=mask, dropout_p=p, scale=scale)
|
| 46 |
+
if is_3d:
|
| 47 |
+
out = out.squeeze(1)
|
| 48 |
+
else:
|
| 49 |
+
out = out.transpose(1, 2)
|
| 50 |
+
return out
|
| 51 |
+
|
| 52 |
+
try:
|
| 53 |
+
import xformers.ops as _xops # noqa: E402
|
| 54 |
+
_xops.memory_efficient_attention = _mea_sdpa
|
| 55 |
+
except Exception as _e:
|
| 56 |
+
print(f"[xformers shim] could not patch xformers.ops: {_e}")
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
CUDA_HOME = "/cuda-image/usr/local/cuda-13.0"
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
@spaces.GPU(duration=600)
|
| 63 |
+
def _first_gpu_setup():
|
| 64 |
+
"""Build pytorch3d from source against the live torch on first GPU acquire."""
|
| 65 |
+
try:
|
| 66 |
+
import pytorch3d # noqa: F401
|
| 67 |
+
return
|
| 68 |
+
except ImportError:
|
| 69 |
+
pass
|
| 70 |
+
|
| 71 |
+
import tempfile
|
| 72 |
+
patch_dir = tempfile.mkdtemp(prefix="torch_cuda_patch_")
|
| 73 |
+
with open(os.path.join(patch_dir, "sitecustomize.py"), "w") as f:
|
| 74 |
+
f.write(
|
| 75 |
+
"try:\n"
|
| 76 |
+
" import torch.utils.cpp_extension as _c\n"
|
| 77 |
+
" _c._check_cuda_version = lambda *a, **k: None\n"
|
| 78 |
+
"except Exception:\n"
|
| 79 |
+
" pass\n"
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
env = os.environ.copy()
|
| 83 |
+
env["CUDA_HOME"] = CUDA_HOME
|
| 84 |
+
env["CUDA_PATH"] = CUDA_HOME
|
| 85 |
+
env["PATH"] = os.path.join(CUDA_HOME, "bin") + os.pathsep + env.get("PATH", "")
|
| 86 |
+
env["PYTHONPATH"] = patch_dir + os.pathsep + env.get("PYTHONPATH", "")
|
| 87 |
+
env["TORCH_CUDA_ARCH_LIST"] = "12.0"
|
| 88 |
+
env["FORCE_CUDA"] = "1"
|
| 89 |
+
# CUDA 13 changed default symbol visibility; pytorch3d's pulsar renderer
|
| 90 |
+
# needs the old behaviour or it fails to link with "undefined reference".
|
| 91 |
+
# https://github.com/facebookresearch/pytorch3d/issues/2011
|
| 92 |
+
env["NVCC_FLAGS"] = "-static-global-template-stub=false"
|
| 93 |
+
|
| 94 |
+
subprocess.check_call(
|
| 95 |
+
[sys.executable, "-m", "pip", "install", "--no-deps",
|
| 96 |
+
"setuptools", "wheel", "ninja", "packaging"],
|
| 97 |
+
)
|
| 98 |
+
subprocess.check_call(
|
| 99 |
+
[sys.executable, "-m", "pip", "install",
|
| 100 |
+
"--no-build-isolation", "--no-deps",
|
| 101 |
+
"git+https://github.com/facebookresearch/pytorch3d.git@stable"],
|
| 102 |
+
env=env,
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
# Pre-download the DUSt3R checkpoint at module scope (CPU-only). Using
|
| 107 |
+
# hf_hub_download lets us avoid a fresh wget every boot.
|
| 108 |
+
from huggingface_hub import hf_hub_download
|
| 109 |
|
| 110 |
+
os.makedirs("./checkpoints/", exist_ok=True)
|
| 111 |
+
if not os.path.exists("./checkpoints/DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth"):
|
| 112 |
+
try:
|
| 113 |
+
hf_hub_download(
|
| 114 |
+
repo_id="naver/DUSt3R_ViTLarge_BaseDecoder_512_dpt",
|
| 115 |
+
filename="DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth",
|
| 116 |
+
local_dir="./checkpoints/",
|
| 117 |
+
)
|
| 118 |
+
except Exception as _e:
|
| 119 |
+
print(f"[dust3r hf_hub_download fallback to wget] {_e}")
|
| 120 |
+
subprocess.check_call([
|
| 121 |
+
"wget", "-q", "-c",
|
| 122 |
+
"https://download.europe.naverlabs.com/ComputerVision/DUSt3R/DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth",
|
| 123 |
+
"-P", "checkpoints/",
|
| 124 |
+
])
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
# ---------------------------------------------------------------------------
|
| 128 |
+
# Original app
|
| 129 |
+
# ---------------------------------------------------------------------------
|
| 130 |
import random
|
| 131 |
import gradio as gr
|
|
|
|
| 132 |
from configs.infer_config import get_parser
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
# Build pytorch3d before any module-scope code tries to import it. We need a
|
| 136 |
+
# GPU here because pytorch3d's CUDA kernels link against the CUDA runtime
|
| 137 |
+
# headers — run inside @spaces.GPU.
|
| 138 |
+
_first_gpu_setup()
|
| 139 |
+
|
| 140 |
|
| 141 |
traj_examples = [
|
| 142 |
['0 -35; 0 0; 0 -0.1'],
|
|
|
|
| 156 |
|
| 157 |
max_seed = 2 ** 31
|
| 158 |
|
| 159 |
+
|
| 160 |
def download_model():
|
| 161 |
REPO_ID = 'Drexubery/ViewCrafter_25'
|
| 162 |
filename_list = ['model.ckpt']
|
|
|
|
| 164 |
local_file = os.path.join('./checkpoints/', filename)
|
| 165 |
if not os.path.exists(local_file):
|
| 166 |
hf_hub_download(repo_id=REPO_ID, filename=filename, local_dir='./checkpoints/', force_download=True)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
download_model()
|
| 170 |
+
parser = get_parser()
|
| 171 |
+
opts = parser.parse_args()
|
| 172 |
tmp = str(random.randint(10**(5-1), 10**5 - 1))
|
| 173 |
opts.save_dir = f'./{tmp}'
|
| 174 |
+
os.makedirs(opts.save_dir, exist_ok=True)
|
| 175 |
+
opts.device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 176 |
+
opts.config = './configs/inference_pvd_1024_gradio.yaml'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
|
| 178 |
|
| 179 |
from viewcrafter import ViewCrafter
|
|
|
|
| 203 |
def viewcrafter_demo(opts):
|
| 204 |
css = """#input_img {max-width: 1024px !important} #output_vid {max-width: 1024px; max-height:576px} #random_button {max-width: 100px !important}"""
|
| 205 |
image2video = ViewCrafter(opts, gradio = True)
|
| 206 |
+
image2video.run_both = spaces.GPU(image2video.run_both, duration=290)
|
| 207 |
with gr.Blocks(analytics_enabled=False, css=css) as viewcrafter_iface:
|
| 208 |
gr.Markdown("<div align='center'> <h1> ViewCrafter: Taming Video Diffusion Models for High-fidelity Novel View Synthesis </span> </h1> \
|
| 209 |
<h2 style='font-weight: 450; font-size: 1rem; margin: 0rem'>\
|
|
|
|
| 223 |
|
| 224 |
with gr.Row():
|
| 225 |
with gr.Column():
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
with gr.Column():
|
| 227 |
i2v_input_image = gr.Image(label="Input Image",elem_id="input_img")
|
| 228 |
with gr.Row():
|
|
|
|
| 233 |
left = gr.Button(value = "Left")
|
| 234 |
right = gr.Button(value = "Right")
|
| 235 |
up = gr.Button(value = "Up")
|
| 236 |
+
with gr.Row():
|
| 237 |
+
down = gr.Button(value = "Down")
|
| 238 |
zin = gr.Button(value = "Zoom in")
|
| 239 |
zout = gr.Button(value = "Zoom out")
|
| 240 |
+
with gr.Row():
|
| 241 |
custom = gr.Button(value = "Customize")
|
| 242 |
reset = gr.Button(value = "Reset")
|
| 243 |
|
|
|
|
| 249 |
gr.Markdown("<div align='left' style='font-size:18px;color: #000000'>Please refer to the <a href='https://github.com/Drexubery/ViewCrafter/blob/main/docs/gradio_tutorial.md' target='_blank'>tutorial</a> for customizing camera trajectory.</div>")
|
| 250 |
gr.Examples(examples=traj_examples,
|
| 251 |
inputs=[i2v_pose],
|
| 252 |
+
)
|
| 253 |
|
| 254 |
|
|
|
|
| 255 |
with gr.Column():
|
|
|
|
|
|
|
| 256 |
i2v_output_video = gr.Video(label="Generated Video",elem_id="output_vid",autoplay=True,show_share_button=True)
|
| 257 |
with gr.Row():
|
| 258 |
i2v_steps = gr.Slider(minimum=1, maximum=50, step=1, elem_id="i2v_steps", label="Sampling steps", value=50)
|
| 259 |
i2v_seed = gr.Slider(label='Random seed', minimum=0, maximum=max_seed, step=1, value=0)
|
| 260 |
+
i2v_end_btn = gr.Button("Generate video")
|
| 261 |
i2v_traj_video = gr.Video(label="Camera Trajectory",elem_id="traj_vid",autoplay=True,show_share_button=True)
|
| 262 |
|
| 263 |
+
|
| 264 |
gr.Examples(examples=img_examples,
|
| 265 |
inputs=[i2v_input_image,i2v_elevation, i2v_center_scale,],
|
| 266 |
+
)
|
|
|
|
| 267 |
|
| 268 |
|
| 269 |
|
|
|
|
| 310 |
|
| 311 |
viewcrafter_iface = viewcrafter_demo(opts)
|
| 312 |
viewcrafter_iface.queue(max_size=10)
|
| 313 |
+
viewcrafter_iface.launch()
|
|
|
|
|
|
lvdm/modules/encoders/condition.py
CHANGED
|
@@ -214,9 +214,16 @@ class FrozenOpenCLIPEmbedder(AbstractEncoder):
|
|
| 214 |
def encode_with_transformer(self, text):
|
| 215 |
x = self.model.token_embedding(text) # [batch_size, n_ctx, d_model]
|
| 216 |
x = x + self.model.positional_embedding
|
| 217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
x = self.text_transformer_forward(x, attn_mask=self.model.attn_mask)
|
| 219 |
-
|
|
|
|
| 220 |
x = self.model.ln_final(x)
|
| 221 |
return x
|
| 222 |
|
|
@@ -343,7 +350,8 @@ class FrozenOpenCLIPImageEmbedderV2(AbstractEncoder):
|
|
| 343 |
x = self.preprocess(x)
|
| 344 |
|
| 345 |
# to patches - whether to use dual patchnorm - https://arxiv.org/abs/2302.01327v1
|
| 346 |
-
|
|
|
|
| 347 |
# einops - rearrange(x, 'b c (h p1) (w p2) -> b (h w) (c p1 p2)')
|
| 348 |
x = x.reshape(x.shape[0], x.shape[1], self.model.visual.grid_size[0], self.model.visual.patch_size[0], self.model.visual.grid_size[1], self.model.visual.patch_size[1])
|
| 349 |
x = x.permute(0, 2, 4, 1, 3, 5)
|
|
|
|
| 214 |
def encode_with_transformer(self, text):
|
| 215 |
x = self.model.token_embedding(text) # [batch_size, n_ctx, d_model]
|
| 216 |
x = x + self.model.positional_embedding
|
| 217 |
+
# open-clip-torch >= 2.20 creates nn.MultiheadAttention with batch_first=True
|
| 218 |
+
# by default; skip the NLD <-> LND permutes when that's the case.
|
| 219 |
+
batch_first = getattr(
|
| 220 |
+
self.model.transformer.resblocks[0].attn, "batch_first", False
|
| 221 |
+
)
|
| 222 |
+
if not batch_first:
|
| 223 |
+
x = x.permute(1, 0, 2) # NLD -> LND
|
| 224 |
x = self.text_transformer_forward(x, attn_mask=self.model.attn_mask)
|
| 225 |
+
if not batch_first:
|
| 226 |
+
x = x.permute(1, 0, 2) # LND -> NLD
|
| 227 |
x = self.model.ln_final(x)
|
| 228 |
return x
|
| 229 |
|
|
|
|
| 350 |
x = self.preprocess(x)
|
| 351 |
|
| 352 |
# to patches - whether to use dual patchnorm - https://arxiv.org/abs/2302.01327v1
|
| 353 |
+
# open-clip-torch >= 2.20 removed the input_patchnorm attribute; default False.
|
| 354 |
+
if getattr(self.model.visual, "input_patchnorm", False):
|
| 355 |
# einops - rearrange(x, 'b c (h p1) (w p2) -> b (h w) (c p1 p2)')
|
| 356 |
x = x.reshape(x.shape[0], x.shape[1], self.model.visual.grid_size[0], self.model.visual.patch_size[0], self.model.visual.grid_size[1], self.model.visual.patch_size[1])
|
| 357 |
x = x.permute(0, 2, 4, 1, 3, 5)
|
requirements.txt
CHANGED
|
@@ -2,33 +2,29 @@ decord==0.6.0
|
|
| 2 |
einops==0.6.1
|
| 3 |
imageio==2.27.0
|
| 4 |
imageio-ffmpeg==0.4.8
|
| 5 |
-
torch==2.0.0
|
| 6 |
torchvision
|
| 7 |
kornia
|
| 8 |
matplotlib
|
| 9 |
moviepy==1.0.3
|
| 10 |
-
numpy
|
| 11 |
-
open-clip-torch
|
| 12 |
-
opencv-python
|
| 13 |
-
Pillow
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
tqdm==4.65.0
|
| 25 |
-
transformers==4.25.1
|
| 26 |
trimesh==4.4.3
|
| 27 |
omegaconf==2.3.0
|
| 28 |
-
triton
|
| 29 |
av
|
| 30 |
xformers
|
| 31 |
gradio
|
| 32 |
iopath
|
| 33 |
fvcore
|
| 34 |
-
|
|
|
|
| 2 |
einops==0.6.1
|
| 3 |
imageio==2.27.0
|
| 4 |
imageio-ffmpeg==0.4.8
|
|
|
|
| 5 |
torchvision
|
| 6 |
kornia
|
| 7 |
matplotlib
|
| 8 |
moviepy==1.0.3
|
| 9 |
+
numpy<2
|
| 10 |
+
open-clip-torch
|
| 11 |
+
opencv-python
|
| 12 |
+
Pillow
|
| 13 |
+
pyglet
|
| 14 |
+
pytorch-lightning
|
| 15 |
+
PyYAML
|
| 16 |
+
roma
|
| 17 |
+
scikit-image
|
| 18 |
+
scikit-learn
|
| 19 |
+
scipy
|
| 20 |
+
timm
|
| 21 |
+
tqdm
|
| 22 |
+
transformers
|
|
|
|
|
|
|
| 23 |
trimesh==4.4.3
|
| 24 |
omegaconf==2.3.0
|
|
|
|
| 25 |
av
|
| 26 |
xformers
|
| 27 |
gradio
|
| 28 |
iopath
|
| 29 |
fvcore
|
| 30 |
+
huggingface_hub
|
utils/pvd_utils.py
CHANGED
|
@@ -44,7 +44,16 @@ def save_video(data,images_path,folder=None):
|
|
| 44 |
images = [np.array(Image.open(os.path.join(folder_name,path))) for folder_name,path in zip(folder,data)]
|
| 45 |
stacked_images = np.stack(images, axis=0)
|
| 46 |
tensor_data = torch.from_numpy(stacked_images).to(torch.uint8)
|
| 47 |
-
torchvision.io.write_video
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
def get_input_dict(img_tensor,idx,dtype = torch.float32):
|
| 50 |
|
|
@@ -510,7 +519,11 @@ def visualizer_frame(camera_poses, highlight_index):
|
|
| 510 |
fig.canvas.draw()
|
| 511 |
width, height = fig.canvas.get_width_height()
|
| 512 |
|
| 513 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 514 |
# new_width = int(width * 0.6)
|
| 515 |
# start_x = (width - new_width) // 2 + new_width // 5
|
| 516 |
# end_x = start_x + new_width
|
|
|
|
| 44 |
images = [np.array(Image.open(os.path.join(folder_name,path))) for folder_name,path in zip(folder,data)]
|
| 45 |
stacked_images = np.stack(images, axis=0)
|
| 46 |
tensor_data = torch.from_numpy(stacked_images).to(torch.uint8)
|
| 47 |
+
# torchvision >= 0.22 removed io.write_video; fall back to imageio.
|
| 48 |
+
if hasattr(torchvision.io, "write_video"):
|
| 49 |
+
torchvision.io.write_video(images_path, tensor_data, fps=8, video_codec='h264', options={'crf': '10'})
|
| 50 |
+
else:
|
| 51 |
+
import imageio
|
| 52 |
+
frames_np = tensor_data.numpy() if hasattr(tensor_data, 'numpy') else np.asarray(tensor_data)
|
| 53 |
+
writer = imageio.get_writer(images_path, fps=8, codec='libx264', quality=8)
|
| 54 |
+
for frame in frames_np:
|
| 55 |
+
writer.append_data(frame)
|
| 56 |
+
writer.close()
|
| 57 |
|
| 58 |
def get_input_dict(img_tensor,idx,dtype = torch.float32):
|
| 59 |
|
|
|
|
| 519 |
fig.canvas.draw()
|
| 520 |
width, height = fig.canvas.get_width_height()
|
| 521 |
|
| 522 |
+
# matplotlib >= 3.10 removed tostring_rgb(); use buffer_rgba() and drop alpha.
|
| 523 |
+
if hasattr(fig.canvas, "tostring_rgb"):
|
| 524 |
+
img = np.frombuffer(fig.canvas.tostring_rgb(), dtype='uint8').reshape(height, width, 3)
|
| 525 |
+
else:
|
| 526 |
+
img = np.asarray(fig.canvas.buffer_rgba())[..., :3].copy()
|
| 527 |
# new_width = int(width * 0.6)
|
| 528 |
# start_x = (width - new_width) // 2 + new_width // 5
|
| 529 |
# end_x = start_x + new_width
|