Transformers
Safetensors
trace_anything
feature-extraction
trace-anything
4d
trajectory-field
video
video-to-3d
custom_code
Instructions to use bigshanedogg/Trace-Anything with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use bigshanedogg/Trace-Anything with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("bigshanedogg/Trace-Anything", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download ta_layers.py from bigshanedogg/Trace-Anything: direct link, hf CLI and curl.
- Browser
- Download file 29 kB
-
https://huggingface.co/bigshanedogg/Trace-Anything/resolve/main/ta_layers.py
- Command line
-
hf download hf://bigshanedogg/Trace-Anything/ta_layers.py
-
curl -L -o ta_layers.py https://huggingface.co/bigshanedogg/Trace-Anything/resolve/main/ta_layers.py
29 kB
| # ruff: noqa | |
| # fmt: off | |
| """Trace Anything, vendored verbatim from ByteDance-Seed/TraceAnything @ 54677b5e7bf11510c2e8c917a509988ad379f8eb (trace_anything/): the files below | |
| concatenated, package-internal imports replaced by relative imports of the other vendored files (generated by scripts/model_ports/common/vendor_flat.py; | |
| do not edit by hand). Code license: Apache-2.0.""" | |
| # ============================================================================================================== | |
| # trace_anything/layers/blocks.py | |
| # ============================================================================================================== | |
| # Copyright (c) 2025 Bytedance Ltd. and/or its affiliates | |
| # Copyright (c) Meta Platforms, Inc. and affiliates. | |
| # All rights reserved. | |
| # This source code is licensed under the license found in the | |
| # LICENSE file in the root directory of this source tree. | |
| # Copyright (C) 2022-present Naver Corporation. All rights reserved. | |
| # Licensed under CC BY-NC-SA 4.0 (non-commercial use only). | |
| # -------------------------------------------------------- | |
| # Main encoder/decoder blocks | |
| # -------------------------------------------------------- | |
| # References: | |
| # timm | |
| # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py | |
| # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/helpers.py | |
| # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/drop.py | |
| # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/mlp.py | |
| # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/patch_embed.py | |
| import collections.abc | |
| from itertools import repeat | |
| import math | |
| import torch | |
| import torch.nn as nn | |
| from torch.nn.functional import scaled_dot_product_attention | |
| from torch.nn.attention import SDPBackend | |
| def _ntuple(n): | |
| def parse(x): | |
| if isinstance(x, collections.abc.Iterable) and not isinstance(x, str): | |
| return x | |
| return tuple(repeat(x, n)) | |
| return parse | |
| to_2tuple = _ntuple(2) | |
| def drop_path( | |
| x, drop_prob: float = 0.0, training: bool = False, scale_by_keep: bool = True | |
| ): | |
| """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).""" | |
| if drop_prob == 0.0 or not training: | |
| return x | |
| keep_prob = 1 - drop_prob | |
| shape = (x.shape[0],) + (1,) * ( | |
| x.ndim - 1 | |
| ) # work with diff dim tensors, not just 2D ConvNets | |
| random_tensor = x.new_empty(shape).bernoulli_(keep_prob) | |
| if keep_prob > 0.0 and scale_by_keep: | |
| random_tensor.div_(keep_prob) | |
| return x * random_tensor | |
| class DropPath(nn.Module): | |
| """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).""" | |
| def __init__(self, drop_prob: float = 0.0, scale_by_keep: bool = True): | |
| super(DropPath, self).__init__() | |
| self.drop_prob = drop_prob | |
| self.scale_by_keep = scale_by_keep | |
| def forward(self, x): | |
| return drop_path(x, self.drop_prob, self.training, self.scale_by_keep) | |
| def extra_repr(self): | |
| return f"drop_prob={round(self.drop_prob,3):0.3f}" | |
| class Mlp(nn.Module): | |
| """MLP as used in Vision Transformer, MLP-Mixer and related networks""" | |
| def __init__( | |
| self, | |
| in_features, | |
| hidden_features=None, | |
| out_features=None, | |
| act_layer=nn.GELU, | |
| bias=True, | |
| drop=0.0, | |
| ): | |
| super().__init__() | |
| out_features = out_features or in_features | |
| hidden_features = hidden_features or in_features | |
| bias = to_2tuple(bias) | |
| drop_probs = to_2tuple(drop) | |
| self.fc1 = nn.Linear(in_features, hidden_features, bias=bias[0]) | |
| self.act = act_layer() | |
| self.drop1 = nn.Dropout(drop_probs[0]) | |
| self.fc2 = nn.Linear(hidden_features, out_features, bias=bias[1]) | |
| self.drop2 = nn.Dropout(drop_probs[1]) | |
| def forward(self, x): | |
| x = self.fc1(x) | |
| x = self.act(x) | |
| x = self.drop1(x) | |
| x = self.fc2(x) | |
| x = self.drop2(x) | |
| return x | |
| class Attention(nn.Module): | |
| def __init__( | |
| self, dim, rope=None, num_heads=8, qkv_bias=False, attn_drop=0.0, proj_drop=0.0, | |
| attn_mask=None, is_causal=False, attn_implementation="pytorch_naive", | |
| attn_bias_for_inference_enabled=False, | |
| ): | |
| super().__init__() | |
| self.num_heads = num_heads | |
| head_dim = dim // num_heads | |
| self.scale = head_dim**-0.5 | |
| # use attention biasing to accommodate for longer sequences than during training | |
| self.attn_bias_for_inference_enabled = attn_bias_for_inference_enabled | |
| gamma = 1.0 | |
| train_seqlen = 20 | |
| inference_seqlen = 137 | |
| self.attn_bias_scale = head_dim**-0.5 * (gamma * math.log(inference_seqlen) / math.log(train_seqlen))**0.5 | |
| self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) | |
| self.dropout_p = attn_drop | |
| self.attn_drop = nn.Dropout(attn_drop) | |
| self.proj = nn.Linear(dim, dim) | |
| self.proj_drop = nn.Dropout(proj_drop) | |
| self.rope = rope | |
| self.attn_mask = attn_mask | |
| self.is_causal = is_causal | |
| self.attn_implementation = attn_implementation | |
| def forward(self, x, xpos): | |
| B, N, C = x.shape | |
| qkv = ( | |
| self.qkv(x) | |
| .reshape(B, N, 3, self.num_heads, C // self.num_heads) | |
| .transpose(1, 3) | |
| ) | |
| q, k, v = [qkv[:, :, i] for i in range(3)] | |
| # q,k,v = qkv.unbind(2) # make torchscript happy (cannot use tensor as tuple) | |
| if self.rope is not None: | |
| with torch.autocast(device_type=next(self.parameters()).device.type, dtype=torch.float32): # FIXME: for some reason Lightning didn't pick up torch.cuda.amp.custom_fwd when using bf16-true | |
| q = self.rope(q, xpos) if xpos is not None else q | |
| k = self.rope(k, xpos) if xpos is not None else k | |
| if not self.training and self.attn_bias_for_inference_enabled: | |
| scale = self.attn_bias_scale | |
| else: | |
| scale = self.scale | |
| # Important: For the fusion Transformer, we forward through the attention with bfloat16 precision | |
| # If you are not using this block for the fusion Transformer, you should double check the precision of the input and output | |
| if self.attn_implementation == "pytorch_naive": | |
| assert self.attn_mask is None, "attn_mask not supported for pytorch_naive implementation of scaled dot product attention" | |
| assert self.is_causal is False, "is_causal not supported for pytorch_naive implementation of scaled dot product attention" | |
| dtype = k.dtype | |
| with torch.autocast("cuda", dtype=torch.bfloat16): | |
| x = (q @ k.transpose(-2, -1)) * scale | |
| x = x.softmax(dim=-1) | |
| x = self.attn_drop(x) | |
| if dtype == torch.float32: # if input was FP32, cast back to FP32 | |
| x = x.to(torch.float32) | |
| x = (x @ v).transpose(1, 2).reshape(B, N, C) | |
| x = self.proj(x) | |
| x = self.proj_drop(x) | |
| elif self.attn_implementation == "flash_attention": | |
| with torch.nn.attention.sdpa_kernel(SDPBackend.FLASH_ATTENTION): | |
| dtype = k.dtype | |
| with torch.autocast("cuda", dtype=torch.bfloat16): | |
| x = scaled_dot_product_attention(q, k, v, attn_mask=self.attn_mask, dropout_p=self.dropout_p, is_causal=self.is_causal, scale=scale) | |
| if dtype == torch.float32: # if input was FP32, cast back to FP32 | |
| x = x.to(torch.float32) | |
| x = x.transpose(1, 2).reshape(B, N, C) | |
| x = self.proj(x) | |
| x = self.proj_drop(x) | |
| elif self.attn_implementation == "pytorch_auto": | |
| with torch.nn.attention.sdpa_kernel([SDPBackend.EFFICIENT_ATTENTION,]): | |
| dtype = k.dtype | |
| with torch.autocast("cuda", dtype=torch.bfloat16): | |
| x = scaled_dot_product_attention(q, k, v, attn_mask=self.attn_mask, dropout_p=self.dropout_p, is_causal=self.is_causal, scale=scale) | |
| if dtype == torch.float32: # if input was FP32, cast back to FP32 | |
| x = x.to(torch.float32) | |
| x = x.transpose(1, 2).reshape(B, N, C) | |
| x = self.proj(x) | |
| x = self.proj_drop(x) | |
| else: | |
| raise ValueError(f"Unknown attn_implementation: {self.attn_implementation}") | |
| return x | |
| class Block(nn.Module): | |
| def __init__( | |
| self, | |
| dim, | |
| num_heads, | |
| mlp_ratio=4.0, | |
| qkv_bias=False, | |
| drop=0.0, | |
| attn_drop=0.0, | |
| drop_path=0.0, | |
| act_layer=nn.GELU, | |
| norm_layer=nn.LayerNorm, | |
| rope=None, | |
| attn_implementation="pytorch_naive", | |
| attn_bias_for_inference_enabled=False, | |
| ): | |
| super().__init__() | |
| self.norm1 = norm_layer(dim) | |
| self.attn = Attention( | |
| dim, | |
| rope=rope, | |
| num_heads=num_heads, | |
| qkv_bias=qkv_bias, | |
| attn_drop=attn_drop, | |
| proj_drop=drop, | |
| attn_implementation=attn_implementation, | |
| attn_bias_for_inference_enabled=attn_bias_for_inference_enabled, | |
| ) | |
| # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here | |
| self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() | |
| self.norm2 = norm_layer(dim) | |
| mlp_hidden_dim = int(dim * mlp_ratio) | |
| self.mlp = Mlp( | |
| in_features=dim, | |
| hidden_features=mlp_hidden_dim, | |
| act_layer=act_layer, | |
| drop=drop, | |
| ) | |
| def forward(self, x, xpos): | |
| x = x + self.drop_path(self.attn(self.norm1(x), xpos)) | |
| x = x + self.drop_path(self.mlp(self.norm2(x))) | |
| return x | |
| class CrossAttention(nn.Module): | |
| def __init__( | |
| self, dim, rope=None, num_heads=8, qkv_bias=False, attn_drop=0.0, proj_drop=0.0, attn_mask=None, is_causal=False, attn_implementation="pytorch_naive" | |
| ): | |
| super().__init__() | |
| self.num_heads = num_heads | |
| head_dim = dim // num_heads | |
| self.scale = head_dim**-0.5 | |
| self.projq = nn.Linear(dim, dim, bias=qkv_bias) | |
| self.projk = nn.Linear(dim, dim, bias=qkv_bias) | |
| self.projv = nn.Linear(dim, dim, bias=qkv_bias) | |
| self.dropout_p = attn_drop | |
| self.attn_drop = nn.Dropout(attn_drop) | |
| self.proj = nn.Linear(dim, dim) | |
| self.proj_drop = nn.Dropout(proj_drop) | |
| self.rope = rope | |
| self.attn_mask = attn_mask | |
| self.is_causal = is_causal | |
| self.attn_implementation = attn_implementation | |
| def forward(self, query, key, value, qpos, kpos): | |
| B, Nq, C = query.shape | |
| Nk = key.shape[1] | |
| Nv = value.shape[1] | |
| q = ( | |
| self.projq(query) | |
| .reshape(B, Nq, self.num_heads, C // self.num_heads) | |
| .permute(0, 2, 1, 3) | |
| ) | |
| k = ( | |
| self.projk(key) | |
| .reshape(B, Nk, self.num_heads, C // self.num_heads) | |
| .permute(0, 2, 1, 3) | |
| ) | |
| v = ( | |
| self.projv(value) | |
| .reshape(B, Nv, self.num_heads, C // self.num_heads) | |
| .permute(0, 2, 1, 3) | |
| ) | |
| if self.rope is not None: | |
| with torch.autocast(device_type=next(self.parameters()).device.type, dtype=torch.float32): # FIXME: for some reason Lightning didn't pick up torch.cuda.amp.custom_fwd when using bf16-true | |
| q = self.rope(q, qpos) if qpos is not None else q | |
| k = self.rope(k, kpos) if kpos is not None else k | |
| if self.attn_implementation == "pytorch_naive": | |
| assert self.attn_mask is None, "attn_mask not supported for pytorch_naive implementation of scaled dot product attention" | |
| assert self.is_causal is False, "is_causal not supported for pytorch_naive implementation of scaled dot product attention" | |
| attn = (q @ k.transpose(-2, -1)) * self.scale | |
| attn = attn.softmax(dim=-1) | |
| attn = self.attn_drop(attn) | |
| x = (attn @ v).transpose(1, 2).reshape(B, Nq, C) | |
| x = self.proj(x) | |
| x = self.proj_drop(x) | |
| elif self.attn_implementation == "flash_attention": | |
| with torch.nn.attention.sdpa_kernel(SDPBackend.FLASH_ATTENTION): | |
| # cast to BF16 to use flash_attention | |
| q = q.to(torch.bfloat16) | |
| k = k.to(torch.bfloat16) | |
| v = v.to(torch.bfloat16) | |
| x = scaled_dot_product_attention(q, k, v, attn_mask=self.attn_mask, dropout_p=self.dropout_p, is_causal=self.is_causal, scale=self.scale) | |
| # cast back to FP32 | |
| x = x.to(torch.float32) | |
| x = x.transpose(1, 2).reshape(B, Nq, C) | |
| x = self.proj(x) | |
| x = self.proj_drop(x) | |
| else: | |
| raise ValueError(f"Unknown attn_implementation: {self.attn_implementation}") | |
| return x | |
| class DecoderBlock(nn.Module): | |
| def __init__( | |
| self, | |
| dim, | |
| num_heads, | |
| mlp_ratio=4.0, | |
| qkv_bias=False, | |
| drop=0.0, | |
| attn_drop=0.0, | |
| drop_path=0.0, | |
| act_layer=nn.GELU, | |
| norm_layer=nn.LayerNorm, | |
| norm_mem=True, | |
| rope=None, | |
| attn_implementation="pytorch_naive", | |
| ): | |
| super().__init__() | |
| self.norm1 = norm_layer(dim) | |
| self.attn = Attention( | |
| dim, | |
| rope=rope, | |
| num_heads=num_heads, | |
| qkv_bias=qkv_bias, | |
| attn_drop=attn_drop, | |
| proj_drop=drop, | |
| attn_implementation=attn_implementation, | |
| ) | |
| self.cross_attn = CrossAttention( | |
| dim, | |
| rope=rope, | |
| num_heads=num_heads, | |
| qkv_bias=qkv_bias, | |
| attn_drop=attn_drop, | |
| proj_drop=drop, | |
| attn_implementation=attn_implementation, | |
| ) | |
| self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() | |
| self.norm2 = norm_layer(dim) | |
| self.norm3 = norm_layer(dim) | |
| mlp_hidden_dim = int(dim * mlp_ratio) | |
| self.mlp = Mlp( | |
| in_features=dim, | |
| hidden_features=mlp_hidden_dim, | |
| act_layer=act_layer, | |
| drop=drop, | |
| ) | |
| self.norm_y = norm_layer(dim) if norm_mem else nn.Identity() | |
| def forward(self, x, y, xpos, ypos): | |
| x = x + self.drop_path(self.attn(self.norm1(x), xpos)) | |
| y_ = self.norm_y(y) | |
| x = x + self.drop_path(self.cross_attn(self.norm2(x), y_, y_, xpos, ypos)) | |
| x = x + self.drop_path(self.mlp(self.norm3(x))) | |
| return x, y | |
| # patch embedding | |
| class PositionGetter(object): | |
| """return positions of patches""" | |
| def __init__(self): | |
| self.cache_positions = {} | |
| def __call__(self, b, h, w, device): | |
| if not (h, w) in self.cache_positions: | |
| x = torch.arange(w, device=device) | |
| y = torch.arange(h, device=device) | |
| self.cache_positions[h, w] = torch.cartesian_prod(y, x) # (h, w, 2) | |
| pos = self.cache_positions[h, w].view(1, h * w, 2).expand(b, -1, 2).clone() | |
| return pos | |
| class PatchEmbed(nn.Module): | |
| """just adding _init_weights + position getter compared to timm.models.layers.patch_embed.PatchEmbed""" | |
| def __init__( | |
| self, | |
| img_size=224, | |
| patch_size=16, | |
| in_chans=3, | |
| embed_dim=768, | |
| norm_layer=None, | |
| flatten=True, | |
| ): | |
| super().__init__() | |
| img_size = to_2tuple(img_size) | |
| patch_size = to_2tuple(patch_size) | |
| self.img_size = img_size | |
| self.patch_size = patch_size | |
| self.grid_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1]) | |
| self.num_patches = self.grid_size[0] * self.grid_size[1] | |
| self.flatten = flatten | |
| self.proj = nn.Conv2d( | |
| in_chans, embed_dim, kernel_size=patch_size, stride=patch_size | |
| ) | |
| self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity() | |
| self.position_getter = PositionGetter() | |
| def forward(self, x): | |
| B, C, H, W = x.shape | |
| torch._assert( | |
| H == self.img_size[0], | |
| f"Input image height ({H}) doesn't match model ({self.img_size[0]}).", | |
| ) | |
| torch._assert( | |
| W == self.img_size[1], | |
| f"Input image width ({W}) doesn't match model ({self.img_size[1]}).", | |
| ) | |
| x = self.proj(x) | |
| pos = self.position_getter(B, x.size(2), x.size(3), x.device) | |
| if self.flatten: | |
| x = x.flatten(2).transpose(1, 2).contiguous() # BCHW -> BNC | |
| x = self.norm(x) | |
| return x, pos | |
| def _init_weights(self): | |
| w = self.proj.weight.data | |
| torch.nn.init.xavier_uniform_(w.view([w.shape[0], -1])) | |
| # ============================================================================================================== | |
| # trace_anything/layers/pos_embed.py | |
| # ============================================================================================================== | |
| # Copyright (c) 2025 Bytedance Ltd. and/or its affiliates | |
| # Copyright (c) Meta Platforms, Inc. and affiliates. | |
| # All rights reserved. | |
| # This source code is licensed under the license found in the | |
| # LICENSE file in the root directory of this source tree. | |
| # Copyright (C) 2022-present Naver Corporation. All rights reserved. | |
| # Licensed under CC BY-NC-SA 4.0 (non-commercial use only). | |
| # -------------------------------------------------------- | |
| # Position embedding utils | |
| # -------------------------------------------------------- | |
| import numpy as np | |
| import torch | |
| # -------------------------------------------------------- | |
| # 2D sine-cosine position embedding | |
| # References: | |
| # MAE: https://github.com/facebookresearch/mae/blob/main/util/pos_embed.py | |
| # Transformer: https://github.com/tensorflow/models/blob/master/official/nlp/transformer/model_utils.py | |
| # MoCo v3: https://github.com/facebookresearch/moco-v3 | |
| # -------------------------------------------------------- | |
| def get_2d_sincos_pos_embed(embed_dim, grid_size, n_cls_token=0): | |
| """ | |
| grid_size: int of the grid height and width | |
| return: | |
| pos_embed: [grid_size*grid_size, embed_dim] or [n_cls_token+grid_size*grid_size, embed_dim] (w/ or w/o cls_token) | |
| """ | |
| grid_h = np.arange(grid_size, dtype=np.float32) | |
| grid_w = np.arange(grid_size, dtype=np.float32) | |
| grid = np.meshgrid(grid_w, grid_h) # here w goes first | |
| grid = np.stack(grid, axis=0) | |
| grid = grid.reshape([2, 1, grid_size, grid_size]) | |
| pos_embed = get_2d_sincos_pos_embed_from_grid(embed_dim, grid) | |
| if n_cls_token > 0: | |
| pos_embed = np.concatenate( | |
| [np.zeros([n_cls_token, embed_dim]), pos_embed], axis=0 | |
| ) | |
| return pos_embed | |
| def get_2d_sincos_pos_embed_from_grid(embed_dim, grid): | |
| assert embed_dim % 2 == 0 | |
| # use half of dimensions to encode grid_h | |
| emb_h = get_1d_sincos_pos_embed_from_grid(embed_dim // 2, grid[0]) # (H*W, D/2) | |
| emb_w = get_1d_sincos_pos_embed_from_grid(embed_dim // 2, grid[1]) # (H*W, D/2) | |
| emb = np.concatenate([emb_h, emb_w], axis=1) # (H*W, D) | |
| return emb | |
| def get_1d_sincos_pos_embed_from_grid(embed_dim, pos): | |
| """ | |
| embed_dim: output dimension for each position | |
| pos: a list of positions to be encoded: size (M,) | |
| out: (M, D) | |
| """ | |
| assert embed_dim % 2 == 0 | |
| omega = np.arange(embed_dim // 2, dtype=float) | |
| omega /= embed_dim / 2.0 | |
| omega = 1.0 / 10000**omega # (D/2,) | |
| pos = pos.reshape(-1) # (M,) | |
| out = np.einsum("m,d->md", pos, omega) # (M, D/2), outer product | |
| emb_sin = np.sin(out) # (M, D/2) | |
| emb_cos = np.cos(out) # (M, D/2) | |
| emb = np.concatenate([emb_sin, emb_cos], axis=1) # (M, D) | |
| return emb | |
| # -------------------------------------------------------- | |
| # Interpolate position embeddings for high-resolution | |
| # References: | |
| # MAE: https://github.com/facebookresearch/mae/blob/main/util/pos_embed.py | |
| # DeiT: https://github.com/facebookresearch/deit | |
| # -------------------------------------------------------- | |
| def interpolate_pos_embed(model, checkpoint_model): | |
| if "pos_embed" in checkpoint_model: | |
| pos_embed_checkpoint = checkpoint_model["pos_embed"] | |
| embedding_size = pos_embed_checkpoint.shape[-1] | |
| num_patches = model.patch_embed.num_patches | |
| num_extra_tokens = model.pos_embed.shape[-2] - num_patches | |
| # height (== width) for the checkpoint position embedding | |
| orig_size = int((pos_embed_checkpoint.shape[-2] - num_extra_tokens) ** 0.5) | |
| # height (== width) for the new position embedding | |
| new_size = int(num_patches**0.5) | |
| # class_token and dist_token are kept unchanged | |
| if orig_size != new_size: | |
| print( | |
| "Position interpolate from %dx%d to %dx%d" | |
| % (orig_size, orig_size, new_size, new_size) | |
| ) | |
| extra_tokens = pos_embed_checkpoint[:, :num_extra_tokens] | |
| # only the position tokens are interpolated | |
| pos_tokens = pos_embed_checkpoint[:, num_extra_tokens:] | |
| pos_tokens = pos_tokens.reshape( | |
| -1, orig_size, orig_size, embedding_size | |
| ).permute(0, 3, 1, 2) | |
| pos_tokens = torch.nn.functional.interpolate( | |
| pos_tokens, | |
| size=(new_size, new_size), | |
| mode="bicubic", | |
| align_corners=False, | |
| ) | |
| pos_tokens = pos_tokens.permute(0, 2, 3, 1).flatten(1, 2) | |
| new_pos_embed = torch.cat((extra_tokens, pos_tokens), dim=1) | |
| checkpoint_model["pos_embed"] = new_pos_embed | |
| # ---------------------------------------------------------- | |
| # RoPE2D: RoPE implementation in 2D | |
| # ---------------------------------------------------------- | |
| try: | |
| from fast3r.croco.models.curope import cuRoPE2D | |
| RoPE2D = cuRoPE2D | |
| except ImportError: | |
| print( | |
| "Warning, cannot find cuda-compiled version of RoPE2D, using a slow pytorch version instead" | |
| ) | |
| class RoPE2D(torch.nn.Module): | |
| def __init__(self, freq=100.0, F0=1.0): | |
| super().__init__() | |
| self.base = freq | |
| self.F0 = F0 | |
| self.cache = {} | |
| def get_cos_sin(self, D, seq_len, device, dtype): | |
| if (D, seq_len, device, dtype) not in self.cache: | |
| inv_freq = 1.0 / ( | |
| self.base ** (torch.arange(0, D, 2).float().to(device) / D) | |
| ) | |
| t = torch.arange(seq_len, device=device, dtype=inv_freq.dtype) | |
| freqs = torch.einsum("i,j->ij", t, inv_freq).to(dtype) | |
| freqs = torch.cat((freqs, freqs), dim=-1) | |
| cos = freqs.cos() # (Seq, Dim) | |
| sin = freqs.sin() | |
| self.cache[D, seq_len, device, dtype] = (cos, sin) | |
| return self.cache[D, seq_len, device, dtype] | |
| def rotate_half(x): | |
| x1, x2 = x[..., : x.shape[-1] // 2], x[..., x.shape[-1] // 2 :] | |
| return torch.cat((-x2, x1), dim=-1) | |
| def apply_rope1d(self, tokens, pos1d, cos, sin): | |
| assert pos1d.ndim == 2 | |
| cos = torch.nn.functional.embedding(pos1d, cos)[:, None, :, :] | |
| sin = torch.nn.functional.embedding(pos1d, sin)[:, None, :, :] | |
| return (tokens * cos) + (self.rotate_half(tokens) * sin) | |
| def forward(self, tokens, positions): | |
| """ | |
| input: | |
| * tokens: batch_size x nheads x ntokens x dim | |
| * positions: batch_size x ntokens x 2 (y and x position of each token) | |
| output: | |
| * tokens after appplying RoPE2D (batch_size x nheads x ntokens x dim) | |
| """ | |
| assert ( | |
| tokens.size(3) % 2 == 0 | |
| ), "number of dimensions should be a multiple of two" | |
| D = tokens.size(3) // 2 | |
| assert positions.ndim == 3 and positions.shape[-1] == 2 # Batch, Seq, 2 | |
| cos, sin = self.get_cos_sin( | |
| D, int(positions.max()) + 1, tokens.device, tokens.dtype | |
| ) | |
| # split features into two along the feature dimension, and apply rope1d on each half | |
| y, x = tokens.chunk(2, dim=-1) | |
| y = self.apply_rope1d(y, positions[:, :, 0], cos, sin) | |
| x = self.apply_rope1d(x, positions[:, :, 1], cos, sin) | |
| tokens = torch.cat((y, x), dim=-1) | |
| return tokens | |
| # ============================================================================================================== | |
| # trace_anything/layers/patch_embed.py | |
| # ============================================================================================================== | |
| # Copyright (c) 2025 Bytedance Ltd. and/or its affiliates | |
| # Copyright (c) Meta Platforms, Inc. and affiliates. | |
| # All rights reserved. | |
| # This source code is licensed under the license found in the | |
| # LICENSE file in the root directory of this source tree. | |
| # Copyright (C) 2024-present Naver Corporation. All rights reserved. | |
| # Licensed under CC BY-NC-SA 4.0 (non-commercial use only). | |
| # | |
| # -------------------------------------------------------- | |
| # PatchEmbed implementation for DUST3R, | |
| # in particular ManyAR_PatchEmbed that Handle images with non-square aspect ratio | |
| # -------------------------------------------------------- | |
| import torch | |
| def get_patch_embed(patch_embed_cls, img_size, patch_size, enc_embed_dim): | |
| assert patch_embed_cls in ["PatchEmbedDust3R", "ManyAR_PatchEmbed"] | |
| patch_embed = eval(patch_embed_cls)(img_size, patch_size, 3, enc_embed_dim) | |
| return patch_embed | |
| class PatchEmbedDust3R(PatchEmbed): | |
| def forward(self, x, **kw): | |
| B, C, H, W = x.shape | |
| assert ( | |
| H % self.patch_size[0] == 0 | |
| ), f"Input image height ({H}) is not a multiple of patch size ({self.patch_size[0]})." | |
| assert ( | |
| W % self.patch_size[1] == 0 | |
| ), f"Input image width ({W}) is not a multiple of patch size ({self.patch_size[1]})." | |
| x = self.proj(x) | |
| pos = self.position_getter(B, x.size(2), x.size(3), x.device) | |
| if self.flatten: | |
| x = x.flatten(2).transpose(1, 2) # BCHW -> BNC | |
| x = self.norm(x) | |
| return x, pos | |
| class ManyAR_PatchEmbed(PatchEmbed): | |
| """Handle images with non-square aspect ratio. | |
| All images in the same batch have the same aspect ratio. | |
| true_shape = [(height, width) ...] indicates the actual shape of each image. | |
| """ | |
| def __init__( | |
| self, | |
| img_size=224, | |
| patch_size=16, | |
| in_chans=3, | |
| embed_dim=768, | |
| norm_layer=None, | |
| flatten=True, | |
| ): | |
| self.embed_dim = embed_dim | |
| super().__init__(img_size, patch_size, in_chans, embed_dim, norm_layer, flatten) | |
| def forward(self, img, true_shape): | |
| B, C, H, W = img.shape | |
| assert W >= H, f"img should be in landscape mode, but got {W=} {H=}" | |
| assert ( | |
| H % self.patch_size[0] == 0 | |
| ), f"Input image height ({H}) is not a multiple of patch size ({self.patch_size[0]})." | |
| assert ( | |
| W % self.patch_size[1] == 0 | |
| ), f"Input image width ({W}) is not a multiple of patch size ({self.patch_size[1]})." | |
| assert true_shape.shape == ( | |
| B, | |
| 2, | |
| ), f"true_shape has the wrong shape={true_shape.shape}" | |
| # size expressed in tokens | |
| W //= self.patch_size[0] | |
| H //= self.patch_size[1] | |
| n_tokens = H * W | |
| height, width = true_shape.T | |
| is_landscape = width >= height | |
| is_portrait = ~is_landscape | |
| # linear projection, transposed if necessary | |
| if is_landscape.any(): | |
| new_landscape_content = self.proj(img[is_landscape]) | |
| new_landscape_content = new_landscape_content.permute(0, 2, 3, 1).flatten(1, 2) | |
| if is_portrait.any(): | |
| new_protrait_content = self.proj(img[is_portrait].swapaxes(-1, -2)) | |
| new_protrait_content = new_protrait_content.permute(0, 2, 3, 1).flatten(1, 2) | |
| # allocate space for result and set the content | |
| x = img.new_empty((B, n_tokens, self.embed_dim), dtype=next(self.named_parameters())[1].dtype) # dynamically set dtype based on the current precision | |
| if is_landscape.any(): | |
| x[is_landscape] = new_landscape_content | |
| if is_portrait.any(): | |
| x[is_portrait] = new_protrait_content | |
| # allocate space for result and set the content | |
| pos = img.new_empty((B, n_tokens, 2), dtype=torch.int64) | |
| if is_landscape.any(): | |
| pos[is_landscape] = self.position_getter(1, H, W, pos.device).expand(is_landscape.sum(), -1, -1) | |
| if is_portrait.any(): | |
| pos[is_portrait] = self.position_getter(1, W, H, pos.device).expand(is_portrait.sum(), -1, -1) | |
| x = self.norm(x) | |
| return x, pos | |