mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2026-10-17 19:55:43 +08:00
Compare commits
9 Commits
2bce7110d5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88e182f989 | ||
|
|
978cd99221 | ||
|
|
716c594eab | ||
|
|
87a6e51e34 | ||
|
|
fa22ad16c4 | ||
|
|
0a7d4c1a17 | ||
|
|
e73a7e7bfc | ||
|
|
a081d766b0 | ||
|
|
fdaf9bd6fe |
@@ -117,16 +117,12 @@ class Experiment(Configurable):
|
||||
will be saved here.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `data_source` is never initialized.
|
||||
data_source: DataSourceBase
|
||||
data_source_class_type: str = "ImplicitronDataSource"
|
||||
# pyre-fixme[13]: Attribute `model_factory` is never initialized.
|
||||
model_factory: ModelFactoryBase
|
||||
model_factory_class_type: str = "ImplicitronModelFactory"
|
||||
# pyre-fixme[13]: Attribute `optimizer_factory` is never initialized.
|
||||
optimizer_factory: OptimizerFactoryBase
|
||||
optimizer_factory_class_type: str = "ImplicitronOptimizerFactory"
|
||||
# pyre-fixme[13]: Attribute `training_loop` is never initialized.
|
||||
training_loop: TrainingLoopBase
|
||||
training_loop_class_type: str = "ImplicitronTrainingLoop"
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ class ImplicitronModelFactory(ModelFactoryBase):
|
||||
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `model` is never initialized.
|
||||
model: ImplicitronModelBase
|
||||
model_class_type: str = "GenericModel"
|
||||
resume: bool = True
|
||||
|
||||
@@ -169,7 +169,6 @@ class ImplicitronOptimizerFactory(OptimizerFactoryBase):
|
||||
gamma=self.gamma,
|
||||
)
|
||||
elif self.lr_policy.casefold() == "Exponential".casefold():
|
||||
# pyre-fixme[28]: Unexpected keyword argument `verbose`.
|
||||
scheduler = torch.optim.lr_scheduler.LambdaLR(
|
||||
optimizer,
|
||||
lambda epoch: self.gamma ** (epoch / self.exponential_lr_step_size),
|
||||
@@ -190,9 +189,7 @@ class ImplicitronOptimizerFactory(OptimizerFactoryBase):
|
||||
gamma = self.gamma ** (epoch_rest / self.exponential_lr_step_size)
|
||||
return gamma
|
||||
|
||||
# pyre-fixme[28]: Unexpected keyword argument `verbose`.
|
||||
scheduler = torch.optim.lr_scheduler.LambdaLR(
|
||||
# pyrefly: ignore [unexpected-keyword]
|
||||
optimizer,
|
||||
_get_lr,
|
||||
# pyrefly: ignore [unexpected-keyword]
|
||||
|
||||
@@ -36,7 +36,6 @@ class TrainingLoopBase(ReplaceableBase):
|
||||
evaluator: An EvaluatorBase instance, used to evaluate training results.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `evaluator` is never initialized.
|
||||
evaluator: Optional[EvaluatorBase]
|
||||
evaluator_class_type: Optional[str] = "ImplicitronEvaluator"
|
||||
|
||||
@@ -380,7 +379,6 @@ class ImplicitronTrainingLoop(TrainingLoopBase):
|
||||
|
||||
# update the stats logger
|
||||
stats.update(preds, time_start=t_start, stat_set=trainmode)
|
||||
# pyre-ignore [16]
|
||||
assert stats.it[trainmode] == it, "inconsistent stat iteration number!"
|
||||
|
||||
# print textual status update
|
||||
|
||||
@@ -23,7 +23,6 @@ def meshgrid_ij(
|
||||
Like torch.meshgrid was before PyTorch 1.10.0, i.e. with indexing set to ij
|
||||
"""
|
||||
if (
|
||||
# pyre-fixme[16]: Callable `meshgrid` has no attribute `__kwdefaults__`.
|
||||
torch.meshgrid.__kwdefaults__ is not None
|
||||
and "indexing" in torch.meshgrid.__kwdefaults__
|
||||
):
|
||||
|
||||
@@ -77,6 +77,20 @@ class _SymEig3x3(nn.Module):
|
||||
if inputs.shape[-2:] != (3, 3):
|
||||
raise ValueError("Only inputs of shape (..., 3, 3) are supported.")
|
||||
|
||||
# The thresholds and regularizers used below are absolute, so they are
|
||||
# only meaningful for inputs of order 1: rescale each matrix to unit
|
||||
# maximum magnitude and undo it on the eigenvalues. The clamp only
|
||||
# matters for the all-zero matrix. The scale is detached because the
|
||||
# decomposition is homogeneous of degree 1, so its Jacobian is
|
||||
# homogeneous of degree 0 and holding the scale constant is exact.
|
||||
scale = (
|
||||
inputs.detach()
|
||||
.abs()
|
||||
.amax(dim=(-2, -1), keepdim=True)
|
||||
.clamp(min=torch.finfo(inputs.dtype).tiny)
|
||||
)
|
||||
inputs = inputs / scale
|
||||
|
||||
inputs_diag = inputs.diagonal(dim1=-2, dim2=-1)
|
||||
inputs_trace = inputs_diag.sum(-1)
|
||||
q = inputs_trace / 3.0
|
||||
@@ -120,7 +134,7 @@ class _SymEig3x3(nn.Module):
|
||||
else:
|
||||
eigenvecs = None
|
||||
|
||||
return eigenvals, eigenvecs
|
||||
return eigenvals * scale.squeeze(-1), eigenvecs
|
||||
|
||||
def _construct_eigenvecs_set(
|
||||
self, inputs: torch.Tensor, eigenvals: torch.Tensor
|
||||
|
||||
@@ -159,8 +159,6 @@ INLINE DEVICE float3 WARP_SUM_FLOAT3(
|
||||
#define FFLOOR(a) floorf(a)
|
||||
#define FROUND(x) nearbyintf(x)
|
||||
#define FABS(a) abs(a)
|
||||
#define IASF(a, loc) (loc) = __int_as_float(a)
|
||||
#define FASI(a, loc) (loc) = __float_as_int(a)
|
||||
#define FABSLEQAS(a, b, c) \
|
||||
((a) <= (b) ? FSUB((b), (a)) <= (c) : FSUB((a), (b)) < (c))
|
||||
#define I2F(a) __int2float_rn(a)
|
||||
|
||||
@@ -114,8 +114,6 @@ INLINE float atomicMin(float* address, float val) {
|
||||
#define FMA(x, y, z) ((x) * (y) + (z))
|
||||
#define I2F(a) static_cast<float>(a)
|
||||
#define FRCP(x) (1.f / (x))
|
||||
#define IASF(x, loc) memcpy(&(loc), &(x), sizeof(x))
|
||||
#define FASI(x, loc) memcpy(&(loc), &(x), sizeof(x))
|
||||
#define DMAX(a, b) std::max((a), (b))
|
||||
#define DMIN(a, b) std::min((a), (b))
|
||||
#define DSATURATE(a) DMIN(1., DMAX(0., (a)))
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
#ifndef PULSAR_NATIVE_COMMANDS_ROUTING_H_
|
||||
#define PULSAR_NATIVE_COMMANDS_ROUTING_H_
|
||||
|
||||
#include <cstring>
|
||||
#include "../global.h"
|
||||
#if __cplusplus >= 202002L
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
// Commands available everywhere.
|
||||
#define MALLOC_HOST(VAR, TYPE, SIZE) \
|
||||
@@ -32,4 +36,37 @@
|
||||
#include "../host/commands.h"
|
||||
#endif
|
||||
|
||||
// Host + device int <-> float bit punning. Replaces IASF / FASI macros.
|
||||
IHD float pulsar_int_as_float(int v) noexcept {
|
||||
#ifdef __CUDA_ARCH__
|
||||
return __int_as_float(v);
|
||||
#elif defined(__HIP_DEVICE_COMPILE__)
|
||||
return __int_as_float(v);
|
||||
#else
|
||||
#if __cpp_lib_bit_cast >= 201806L
|
||||
return std::bit_cast<float>(v);
|
||||
#else
|
||||
float f;
|
||||
std::memcpy(&f, &v, sizeof(f));
|
||||
return f;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
IHD int pulsar_float_as_int(float v) noexcept {
|
||||
#ifdef __CUDA_ARCH__
|
||||
return __float_as_int(v);
|
||||
#elif defined(__HIP_DEVICE_COMPILE__)
|
||||
return __float_as_int(v);
|
||||
#else
|
||||
#if __cpp_lib_bit_cast >= 201806L
|
||||
return std::bit_cast<int>(v);
|
||||
#else
|
||||
int i;
|
||||
std::memcpy(&i, &v, sizeof(i));
|
||||
return i;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -121,8 +121,8 @@ GLOBAL void calc_gradients(
|
||||
grad_im_l[2]);
|
||||
// Start processing.
|
||||
for (int grad_idx = 0; grad_idx < n_track; ++grad_idx) {
|
||||
int sphere_idx;
|
||||
FASI(forw_info_d[fwi_loc + 3 + 2 * grad_idx], sphere_idx);
|
||||
int sphere_idx =
|
||||
pulsar_float_as_int(forw_info_d[fwi_loc + 3 + 2 * grad_idx]);
|
||||
PASSERT(
|
||||
sphere_idx == -1 ||
|
||||
sphere_idx >= 0 && static_cast<uint>(sphere_idx) < num_balls);
|
||||
|
||||
@@ -41,7 +41,8 @@ GLOBAL void fill_bg(
|
||||
// sphere IDs and intersection depths.
|
||||
for (int i = 0; i < renderer.n_track; ++i) {
|
||||
int sphere_id = -1;
|
||||
IASF(sphere_id, renderer.forw_info_d[write_loc + 3 + i * 2]);
|
||||
renderer.forw_info_d[write_loc + 3 + i * 2] =
|
||||
pulsar_int_as_float(sphere_id);
|
||||
renderer.forw_info_d[write_loc + 3 + i * 2 + 1] = -1.f;
|
||||
}
|
||||
if (mode == 0) {
|
||||
|
||||
@@ -406,7 +406,7 @@ GLOBAL void render(
|
||||
IMIN(n_track, tracker.get_n_hits()));
|
||||
for (int i = 0; i < n_track; ++i) {
|
||||
int sphere_id = tracker.get_closest_sphere_id(i);
|
||||
IASF(sphere_id, forw_info_d[write_loc + 3 + i * 2]);
|
||||
forw_info_d[write_loc + 3 + i * 2] = pulsar_int_as_float(sphere_id);
|
||||
forw_info_d[write_loc + 3 + i * 2 + 1] =
|
||||
tracker.get_closest_sphere_depth(i) == MAX_FLOAT
|
||||
? -1.f
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "./util.h"
|
||||
|
||||
#ifdef WITH_CUDA
|
||||
#include <c10/cuda/CUDAException.h>
|
||||
#include <c10/cuda/CUDAGuard.h>
|
||||
#endif
|
||||
|
||||
@@ -106,10 +107,10 @@ void Renderer::ensure_on_device(torch::Device device, bool /*non_blocking*/) {
|
||||
LOG_IF(INFO, PULSAR_LOG_INIT)
|
||||
<< "Transferring render buffers between devices.";
|
||||
int prev_active;
|
||||
cudaGetDevice(&prev_active);
|
||||
C10_CUDA_CHECK(cudaGetDevice(&prev_active));
|
||||
if (this->device_type == c10::DeviceType::CUDA) {
|
||||
LOG_IF(INFO, PULSAR_LOG_INIT) << " Destructing on CUDA.";
|
||||
cudaSetDevice(this->device_index);
|
||||
C10_CUDA_CHECK(cudaSetDevice(this->device_index));
|
||||
for (auto& nrend : this->renderer_vec) {
|
||||
PRE::destruct<true>(&nrend);
|
||||
}
|
||||
@@ -121,7 +122,7 @@ void Renderer::ensure_on_device(torch::Device device, bool /*non_blocking*/) {
|
||||
}
|
||||
if (device.type() == c10::DeviceType::CUDA) {
|
||||
LOG_IF(INFO, PULSAR_LOG_INIT) << " Constructing on CUDA.";
|
||||
cudaSetDevice(device.index());
|
||||
C10_CUDA_CHECK(cudaSetDevice(device.index()));
|
||||
for (auto& nrend : this->renderer_vec) {
|
||||
PRE::construct<true>(
|
||||
&nrend,
|
||||
@@ -149,7 +150,7 @@ void Renderer::ensure_on_device(torch::Device device, bool /*non_blocking*/) {
|
||||
this->n_track());
|
||||
}
|
||||
}
|
||||
cudaSetDevice(prev_active);
|
||||
C10_CUDA_CHECK(cudaSetDevice(prev_active));
|
||||
this->device_type = device.type();
|
||||
this->device_index = device.index();
|
||||
#else
|
||||
@@ -743,8 +744,8 @@ std::tuple<torch::Tensor, torch::Tensor> Renderer::forward(
|
||||
// moved to a CUDA device).
|
||||
#ifdef WITH_CUDA
|
||||
int prev_active;
|
||||
cudaGetDevice(&prev_active);
|
||||
cudaSetDevice(this->device_index);
|
||||
C10_CUDA_CHECK(cudaGetDevice(&prev_active));
|
||||
C10_CUDA_CHECK(cudaSetDevice(this->device_index));
|
||||
#ifdef PULSAR_TIMINGS_BATCHED_ENABLED
|
||||
START_TIME_CU(batch_forward);
|
||||
#endif
|
||||
@@ -789,7 +790,7 @@ std::tuple<torch::Tensor, torch::Tensor> Renderer::forward(
|
||||
std::cout << "Forward render batched time per example: "
|
||||
<< time_ms / static_cast<float>(batch_size) << "ms" << std::endl;
|
||||
#endif
|
||||
cudaSetDevice(prev_active);
|
||||
C10_CUDA_CHECK(cudaSetDevice(prev_active));
|
||||
#endif
|
||||
} else {
|
||||
#ifdef PULSAR_TIMINGS_BATCHED_ENABLED
|
||||
@@ -1100,8 +1101,8 @@ Renderer::backward(
|
||||
// the renderer to a CUDA device if not built with CUDA.
|
||||
#ifdef WITH_CUDA
|
||||
int prev_active;
|
||||
cudaGetDevice(&prev_active);
|
||||
cudaSetDevice(this->device_index);
|
||||
C10_CUDA_CHECK(cudaGetDevice(&prev_active));
|
||||
C10_CUDA_CHECK(cudaSetDevice(this->device_index));
|
||||
#ifdef PULSAR_TIMINGS_BATCHED_ENABLED
|
||||
START_TIME_CU(batch_backward);
|
||||
#endif
|
||||
@@ -1205,7 +1206,7 @@ Renderer::backward(
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
}
|
||||
cudaSetDevice(prev_active);
|
||||
C10_CUDA_CHECK(cudaSetDevice(prev_active));
|
||||
#ifdef PULSAR_TIMINGS_BATCHED_ENABLED
|
||||
STOP_TIME_CU(batch_backward);
|
||||
float time_ms;
|
||||
|
||||
@@ -52,11 +52,8 @@ class ImplicitronDataSource(DataSourceBase):
|
||||
data_loader_map_provider_class_type: identifies type for data_loader_map_provider.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `dataset_map_provider` is never initialized.
|
||||
dataset_map_provider: DatasetMapProviderBase
|
||||
# pyre-fixme[13]: Attribute `dataset_map_provider_class_type` is never initialized.
|
||||
dataset_map_provider_class_type: str
|
||||
# pyre-fixme[13]: Attribute `data_loader_map_provider` is never initialized.
|
||||
data_loader_map_provider: DataLoaderMapProviderBase
|
||||
data_loader_map_provider_class_type: str = "SequenceDataLoaderMapProvider"
|
||||
|
||||
@@ -78,7 +75,7 @@ class ImplicitronDataSource(DataSourceBase):
|
||||
)
|
||||
|
||||
try:
|
||||
from .sql_dataset_provider import ( # noqa: F401 # pyre-ignore
|
||||
from .sql_dataset_provider import ( # noqa: F401
|
||||
SqlIndexDatasetMapProvider,
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
@@ -100,7 +97,7 @@ class ImplicitronDataSource(DataSourceBase):
|
||||
"""
|
||||
DEPRECATED! The property will be removed in future versions.
|
||||
"""
|
||||
if self._all_train_cameras_cache is None: # pyre-ignore[16]
|
||||
if self._all_train_cameras_cache is None:
|
||||
all_train_cameras = self.dataset_map_provider.get_all_train_cameras()
|
||||
self._all_train_cameras_cache = (all_train_cameras,)
|
||||
|
||||
|
||||
@@ -297,7 +297,6 @@ class FrameData(Mapping[str, Any]):
|
||||
depth_map = self.depth_map
|
||||
if depth_map is not None:
|
||||
clamp_bbox_xyxy_depth = rescale_bbox(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
clamp_bbox_xyxy,
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
tuple(depth_map.shape[-2:]),
|
||||
@@ -312,7 +311,6 @@ class FrameData(Mapping[str, Any]):
|
||||
depth_mask = self.depth_mask
|
||||
if depth_mask is not None:
|
||||
clamp_bbox_xyxy_depth = rescale_bbox(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
clamp_bbox_xyxy,
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
tuple(depth_mask.shape[-2:]),
|
||||
|
||||
@@ -175,7 +175,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
self._filter_db() # also computes sequence indices
|
||||
self._extract_and_set_eval_batches()
|
||||
|
||||
# pyre-ignore
|
||||
self._frame_data_builder = FrameDataBuilder(
|
||||
dataset_root=self.dataset_root,
|
||||
load_images=self.load_images,
|
||||
@@ -220,7 +219,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
raise ValueError("This function can only join a list of JsonIndexDataset")
|
||||
# pyre-ignore[16]
|
||||
self.frame_annots.extend([fa for d in other_datasets for fa in d.frame_annots])
|
||||
# pyre-ignore[16]
|
||||
self.seq_annots.update(
|
||||
# https://gist.github.com/treyhunner/f35292e676efa0be1728
|
||||
functools.reduce(
|
||||
@@ -301,7 +299,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
self.frame_annots[idx]["frame_annotation"].frame_number: idx
|
||||
for idx in seq_idx
|
||||
}
|
||||
# pyre-ignore[16]
|
||||
for seq, seq_idx in self._seq_to_idx.items()
|
||||
}
|
||||
|
||||
@@ -374,7 +371,7 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
|
||||
# Deep copy the whole dataset except frame_annots, which are large so we
|
||||
# deep copy only the requested subset of frame_annots.
|
||||
memo = {id(self.frame_annots): None} # pyre-ignore[16]
|
||||
memo = {id(self.frame_annots): None}
|
||||
dataset_new = copy.deepcopy(self, memo)
|
||||
dataset_new.frame_annots = copy.deepcopy(
|
||||
[self.frame_annots[i] for i in valid_dataset_indices]
|
||||
@@ -402,11 +399,9 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
return dataset_new
|
||||
|
||||
def __str__(self) -> str:
|
||||
# pyre-ignore[16]
|
||||
return f"JsonIndexDataset #frames={len(self.frame_annots)}"
|
||||
|
||||
def __len__(self) -> int:
|
||||
# pyre-ignore[16]
|
||||
return len(self.frame_annots)
|
||||
|
||||
def _get_frame_type(self, entry: FrameAnnotsEntry) -> Optional[str]:
|
||||
@@ -418,7 +413,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
"""
|
||||
logger.info("Loading all train cameras.")
|
||||
cameras = []
|
||||
# pyre-ignore[16]
|
||||
for frame_idx, frame_annot in enumerate(tqdm(self.frame_annots)):
|
||||
frame_type = self._get_frame_type(frame_annot)
|
||||
if frame_type is None:
|
||||
@@ -429,16 +423,13 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
return join_cameras_as_batch(cameras)
|
||||
|
||||
def __getitem__(self, index) -> FrameData:
|
||||
# pyre-ignore[16]
|
||||
if index >= len(self.frame_annots):
|
||||
raise IndexError(f"index {index} out of range {len(self.frame_annots)}")
|
||||
|
||||
entry = self.frame_annots[index]["frame_annotation"]
|
||||
|
||||
# pyre-ignore
|
||||
frame_data = self._frame_data_builder.build(
|
||||
entry,
|
||||
# pyre-ignore
|
||||
self.seq_annots[entry.sequence_name],
|
||||
)
|
||||
# Optional field
|
||||
@@ -483,7 +474,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
for subset, frames in subset_to_seq_frame.items()
|
||||
for _, _, path in frames
|
||||
}
|
||||
# pyre-ignore[16]
|
||||
for frame in self.frame_annots:
|
||||
frame["subset"] = frame_path_to_subset.get(
|
||||
frame["frame_annotation"].image.path, None
|
||||
@@ -496,7 +486,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
|
||||
def _sort_frames(self) -> None:
|
||||
# Sort frames to have them grouped by sequence, ordered by timestamp
|
||||
# pyre-ignore[16]
|
||||
self.frame_annots = sorted(
|
||||
self.frame_annots,
|
||||
key=lambda f: (
|
||||
@@ -508,7 +497,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
def _filter_db(self) -> None:
|
||||
if self.remove_empty_masks:
|
||||
logger.info("Removing images with empty masks.")
|
||||
# pyre-ignore[16]
|
||||
old_len = len(self.frame_annots)
|
||||
|
||||
msg = "remove_empty_masks needs every MaskAnnotation.mass to be set."
|
||||
@@ -549,7 +537,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
|
||||
if len(self.limit_category_to) > 0:
|
||||
logger.info(f"Limiting dataset to categories: {self.limit_category_to}")
|
||||
# pyre-ignore[16]
|
||||
self.seq_annots = {
|
||||
name: entry
|
||||
for name, entry in self.seq_annots.items()
|
||||
@@ -587,7 +574,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
if self.n_frames_per_sequence > 0:
|
||||
logger.info(f"Taking max {self.n_frames_per_sequence} per sequence.")
|
||||
keep_idx = []
|
||||
# pyre-ignore[16]
|
||||
for seq, seq_indices in self._seq_to_idx.items():
|
||||
# infer the seed from the sequence name, this is reproducible
|
||||
# and makes the selection differ for different sequences
|
||||
@@ -617,7 +603,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
self._invalidate_seq_to_idx()
|
||||
|
||||
if filter_seq_annots:
|
||||
# pyre-ignore[16]
|
||||
self.seq_annots = {
|
||||
k: v
|
||||
for k, v in self.seq_annots.items()
|
||||
@@ -627,7 +612,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
|
||||
def _invalidate_seq_to_idx(self) -> None:
|
||||
seq_to_idx = defaultdict(list)
|
||||
# pyre-ignore[16]
|
||||
for idx, entry in enumerate(self.frame_annots):
|
||||
seq_to_idx[entry["frame_annotation"].sequence_name].append(idx)
|
||||
# pyre-ignore[16]
|
||||
@@ -658,7 +642,6 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
|
||||
|
||||
def category_to_sequence_names(self) -> Dict[str, List[str]]:
|
||||
c2seq = defaultdict(list)
|
||||
# pyre-ignore
|
||||
for sequence_name, sa in self.seq_annots.items():
|
||||
c2seq[sa.category].append(sequence_name)
|
||||
return dict(c2seq)
|
||||
|
||||
@@ -94,7 +94,6 @@ class JsonIndexDatasetMapProvider(DatasetMapProviderBase):
|
||||
path_manager_factory_class_type: The class type of `path_manager_factory`.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `category` is never initialized.
|
||||
category: str
|
||||
task_str: str = "singlesequence"
|
||||
dataset_root: str = _CO3D_DATASET_ROOT
|
||||
@@ -104,10 +103,8 @@ class JsonIndexDatasetMapProvider(DatasetMapProviderBase):
|
||||
test_restrict_sequence_id: int = -1
|
||||
assert_single_seq: bool = False
|
||||
only_test_set: bool = False
|
||||
# pyre-fixme[13]: Attribute `dataset` is never initialized.
|
||||
dataset: JsonIndexDataset
|
||||
dataset_class_type: str = "JsonIndexDataset"
|
||||
# pyre-fixme[13]: Attribute `path_manager_factory` is never initialized.
|
||||
path_manager_factory: PathManagerFactory
|
||||
path_manager_factory_class_type: str = "PathManagerFactory"
|
||||
|
||||
|
||||
@@ -169,9 +169,7 @@ class JsonIndexDatasetMapProviderV2(DatasetMapProviderBase):
|
||||
path_manager_factory_class_type: The class type of `path_manager_factory`.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `category` is never initialized.
|
||||
category: str
|
||||
# pyre-fixme[13]: Attribute `subset_name` is never initialized.
|
||||
subset_name: str
|
||||
dataset_root: str = _CO3DV2_DATASET_ROOT
|
||||
|
||||
@@ -183,10 +181,8 @@ class JsonIndexDatasetMapProviderV2(DatasetMapProviderBase):
|
||||
n_known_frames_for_test: int = 0
|
||||
|
||||
dataset_class_type: str = "JsonIndexDataset"
|
||||
# pyre-fixme[13]: Attribute `dataset` is never initialized.
|
||||
dataset: JsonIndexDataset
|
||||
|
||||
# pyre-fixme[13]: Attribute `path_manager_factory` is never initialized.
|
||||
path_manager_factory: PathManagerFactory
|
||||
path_manager_factory_class_type: str = "PathManagerFactory"
|
||||
|
||||
|
||||
@@ -76,12 +76,10 @@ class RenderedMeshDatasetMapProvider(DatasetMapProviderBase):
|
||||
resolution: int = 128
|
||||
use_point_light: bool = True
|
||||
gpu_idx: Optional[int] = 0
|
||||
# pyre-fixme[13]: Attribute `path_manager_factory` is never initialized.
|
||||
path_manager_factory: PathManagerFactory
|
||||
path_manager_factory_class_type: str = "PathManagerFactory"
|
||||
|
||||
def get_dataset_map(self) -> DatasetMap:
|
||||
# pyre-ignore[16]
|
||||
return DatasetMap(train=self.train_dataset, val=None, test=None)
|
||||
|
||||
def get_all_train_cameras(self) -> CamerasBase:
|
||||
@@ -117,10 +115,8 @@ class RenderedMeshDatasetMapProvider(DatasetMapProviderBase):
|
||||
device=device,
|
||||
use_point_light=self.use_point_light,
|
||||
)
|
||||
# pyre-ignore[16]
|
||||
self.poses = poses.cpu()
|
||||
# pyre-ignore[16]
|
||||
self.train_dataset = SingleSceneDataset( # pyre-ignore[28]
|
||||
self.train_dataset = SingleSceneDataset(
|
||||
# pyrefly: ignore [unexpected-keyword]
|
||||
object_name="cow",
|
||||
# pyrefly: ignore [unexpected-keyword]
|
||||
|
||||
@@ -99,11 +99,8 @@ class SingleSceneDatasetMapProviderBase(DatasetMapProviderBase):
|
||||
testing frame.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `base_dir` is never initialized.
|
||||
base_dir: str
|
||||
# pyre-fixme[13]: Attribute `object_name` is never initialized.
|
||||
object_name: str
|
||||
# pyre-fixme[13]: Attribute `path_manager_factory` is never initialized.
|
||||
path_manager_factory: PathManagerFactory
|
||||
path_manager_factory_class_type: str = "PathManagerFactory"
|
||||
n_known_frames_for_test: Optional[int] = None
|
||||
@@ -149,7 +146,6 @@ class SingleSceneDatasetMapProviderBase(DatasetMapProviderBase):
|
||||
split = np.concatenate([split, train_split])
|
||||
frame_types.extend([DATASET_TYPE_KNOWN] * len(train_split))
|
||||
|
||||
# pyre-ignore[28]
|
||||
return SingleSceneDataset(
|
||||
object_name=self.object_name,
|
||||
# pyre-ignore[16]
|
||||
|
||||
@@ -205,7 +205,7 @@ class SqlIndexDataset(DatasetBase, ReplaceableBase):
|
||||
logger.info(str(self))
|
||||
|
||||
if self.scoped_session:
|
||||
self._session_factory = sessionmaker(bind=self._sql_engine) # pyre-ignore
|
||||
self._session_factory = sessionmaker(bind=self._sql_engine)
|
||||
|
||||
if self.precompute_seq_to_idx:
|
||||
# This is deprecated and will be removed in the future.
|
||||
@@ -215,7 +215,7 @@ class SqlIndexDataset(DatasetBase, ReplaceableBase):
|
||||
)
|
||||
self._index["rowid"] = np.arange(len(self._index))
|
||||
groupby = self._index.groupby("sequence_name", sort=False)["rowid"]
|
||||
self._seq_to_indices = dict(groupby.apply(list)) # pyre-ignore
|
||||
self._seq_to_indices = dict(groupby.apply(list))
|
||||
del self._index["rowid"]
|
||||
|
||||
def __len__(self) -> int:
|
||||
@@ -280,7 +280,6 @@ class SqlIndexDataset(DatasetBase, ReplaceableBase):
|
||||
self.sequence_annotations_type.sequence_name == seq
|
||||
)
|
||||
if self.scoped_session:
|
||||
# pyre-ignore
|
||||
with scoped_session(self._session_factory)() as session:
|
||||
entry = session.scalars(stmt).one()
|
||||
seq_metadata = session.scalars(seq_stmt).one()
|
||||
@@ -404,7 +403,6 @@ class SqlIndexDataset(DatasetBase, ReplaceableBase):
|
||||
only dataset indices.
|
||||
"""
|
||||
if self.precompute_seq_to_idx and subset_filter is None:
|
||||
# pyre-ignore
|
||||
yield from self._seq_to_indices[seq_name]
|
||||
else:
|
||||
for _, _, idx in self.sequence_frames_in_order(seq_name, subset_filter):
|
||||
@@ -836,7 +834,7 @@ class SqlIndexDataset(DatasetBase, ReplaceableBase):
|
||||
|
||||
if self.scoped_session:
|
||||
stmt_text = str(stmt.compile(compile_kwargs={"literal_binds": True}))
|
||||
with scoped_session(self._session_factory)() as session: # pyre-ignore
|
||||
with scoped_session(self._session_factory)() as session:
|
||||
frame_no_ts = pd.read_sql_query(stmt_text, session.connection())
|
||||
else:
|
||||
with self._sql_engine.connect() as connection:
|
||||
|
||||
@@ -193,9 +193,9 @@ class SqlIndexDatasetMapProvider(DatasetMapProviderBase):
|
||||
|
||||
# this is a mould that is never constructed, used to build self._dataset_map values
|
||||
dataset_class_type: str = "SqlIndexDataset"
|
||||
dataset: SqlIndexDataset # pyre-ignore [13]
|
||||
dataset: SqlIndexDataset
|
||||
|
||||
path_manager_factory: PathManagerFactory # pyre-ignore [13]
|
||||
path_manager_factory: PathManagerFactory
|
||||
path_manager_factory_class_type: str = "PathManagerFactory"
|
||||
|
||||
def __post_init__(self):
|
||||
|
||||
@@ -306,7 +306,6 @@ def _unwrap_type(tp):
|
||||
|
||||
def _get_dataclass_field_default(field: Field) -> Any:
|
||||
if field.default_factory is not MISSING:
|
||||
# pyre-fixme[29]: `Union[dataclasses._MISSING_TYPE,
|
||||
# dataclasses._DefaultFactory[typing.Any]]` is not a function.
|
||||
return field.default_factory()
|
||||
elif field.default is not MISSING:
|
||||
|
||||
@@ -192,7 +192,6 @@ def rescale_bbox(
|
||||
assert bbox is not None
|
||||
assert np.prod(orig_res) > 1e-8
|
||||
# average ratio of dimensions
|
||||
# pyre-ignore
|
||||
rel_size = (new_res[0] / orig_res[0] + new_res[1] / orig_res[1]) / 2.0
|
||||
return bbox * rel_size
|
||||
|
||||
@@ -368,7 +367,6 @@ def adjust_camera_to_bbox_crop_(
|
||||
)
|
||||
|
||||
camera.focal_length = focal_length[None]
|
||||
# pyre-fixme[16]: `PerspectiveCameras` has no attribute `principal_point`.
|
||||
camera.principal_point = principal_point_cropped[None]
|
||||
|
||||
|
||||
@@ -397,8 +395,7 @@ def adjust_camera_to_image_scale_(
|
||||
image_size_wh_output,
|
||||
)
|
||||
camera.focal_length = focal_length_scaled[None]
|
||||
# pyre-fixme[16]: `PerspectiveCameras` has no attribute `principal_point`.
|
||||
camera.principal_point = principal_point_scaled[None] # pyre-ignore[16]
|
||||
camera.principal_point = principal_point_scaled[None]
|
||||
|
||||
|
||||
# NOTE this cache is per-worker; they are implemented as processes.
|
||||
|
||||
@@ -46,7 +46,6 @@ def get_implicitron_sequence_pointcloud(
|
||||
sequence_entries = [
|
||||
ei
|
||||
for ei in sequence_entries
|
||||
# pyre-ignore[16]
|
||||
if dataset.frame_annots[ei]["frame_annotation"].sequence_name
|
||||
== sequence_name
|
||||
]
|
||||
|
||||
@@ -321,7 +321,6 @@ def eval_batch(
|
||||
# only record depth metrics for the foreground
|
||||
_, abs_ = eval_depth(
|
||||
cloned_render["depth_render"],
|
||||
# pyre-fixme[6]: For 2nd param expected `Tensor` but got
|
||||
# `Optional[Tensor]`.
|
||||
frame_data.depth_map,
|
||||
get_best_scale=True,
|
||||
|
||||
@@ -220,6 +220,5 @@ class ResNetFeatureExtractor(FeatureExtractorBase):
|
||||
if self.feature_rescale != 1.0:
|
||||
out_feats = {k: self.feature_rescale * f for k, f in out_feats.items()}
|
||||
|
||||
# pyre-fixme[7]: Incompatible return type, expected `Dict[typing.Any, Tensor]`
|
||||
# but got `Dict[typing.Any, float]`
|
||||
return out_feats
|
||||
|
||||
@@ -222,42 +222,34 @@ class GenericModel(ImplicitronModelBase):
|
||||
|
||||
# ---- global encoder settings
|
||||
global_encoder_class_type: Optional[str] = None
|
||||
# pyre-fixme[13]: Attribute `global_encoder` is never initialized.
|
||||
global_encoder: Optional[GlobalEncoderBase]
|
||||
|
||||
# ---- raysampler
|
||||
raysampler_class_type: str = "AdaptiveRaySampler"
|
||||
# pyre-fixme[13]: Attribute `raysampler` is never initialized.
|
||||
raysampler: RaySamplerBase
|
||||
|
||||
# ---- renderer configs
|
||||
renderer_class_type: str = "MultiPassEmissionAbsorptionRenderer"
|
||||
# pyre-fixme[13]: Attribute `renderer` is never initialized.
|
||||
renderer: BaseRenderer
|
||||
|
||||
# ---- image feature extractor settings
|
||||
# (This is only created if view_pooler is enabled)
|
||||
# pyre-fixme[13]: Attribute `image_feature_extractor` is never initialized.
|
||||
image_feature_extractor: Optional[FeatureExtractorBase]
|
||||
image_feature_extractor_class_type: Optional[str] = None
|
||||
# ---- view pooler settings
|
||||
view_pooler_enabled: bool = False
|
||||
# pyre-fixme[13]: Attribute `view_pooler` is never initialized.
|
||||
view_pooler: Optional[ViewPooler]
|
||||
|
||||
# ---- implicit function settings
|
||||
implicit_function_class_type: str = "NeuralRadianceFieldImplicitFunction"
|
||||
# This is just a model, never constructed.
|
||||
# The actual implicit functions live in self._implicit_functions
|
||||
# pyre-fixme[13]: Attribute `implicit_function` is never initialized.
|
||||
implicit_function: ImplicitFunctionBase
|
||||
|
||||
# ----- metrics
|
||||
# pyre-fixme[13]: Attribute `view_metrics` is never initialized.
|
||||
view_metrics: ViewMetricsBase
|
||||
view_metrics_class_type: str = "ViewMetrics"
|
||||
|
||||
# pyre-fixme[13]: Attribute `regularization_metrics` is never initialized.
|
||||
regularization_metrics: RegularizationMetricsBase
|
||||
regularization_metrics_class_type: str = "RegularizationMetrics"
|
||||
|
||||
@@ -475,7 +467,6 @@ class GenericModel(ImplicitronModelBase):
|
||||
# pyrefly: ignore [unsupported-operation]
|
||||
custom_args["global_code"] = global_code
|
||||
|
||||
# pyre-fixme[29]: `Union[(self: Tensor) -> Any, Tensor, Module]` is not a
|
||||
# function.
|
||||
for func in self._implicit_functions:
|
||||
func.bind_args(**custom_args)
|
||||
@@ -499,7 +490,6 @@ class GenericModel(ImplicitronModelBase):
|
||||
# Unbind the custom arguments to prevent pytorch from storing
|
||||
# large buffers of intermediate results due to points in the
|
||||
# bound arguments.
|
||||
# pyre-fixme[29]: `Union[(self: Tensor) -> Any, Tensor, Module]` is not a
|
||||
# function.
|
||||
for func in self._implicit_functions:
|
||||
func.unbind_args()
|
||||
|
||||
@@ -65,7 +65,6 @@ class SequenceAutodecoder(GlobalEncoderBase, torch.nn.Module):
|
||||
of the frame's sequence identifier.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `autodecoder` is never initialized.
|
||||
autodecoder: Autodecoder
|
||||
|
||||
def __post_init__(self):
|
||||
|
||||
@@ -229,10 +229,8 @@ class MLPWithInputSkips(Configurable, torch.nn.Module):
|
||||
# if the skip tensor is None, we use `x` instead.
|
||||
z = x
|
||||
skipi = 0
|
||||
# pyre-fixme[6]: For 1st argument expected `Iterable[_T]` but got
|
||||
# `Union[Tensor, Module]`.
|
||||
for li, layer in enumerate(self.mlp):
|
||||
# pyre-fixme[58]: `in` is not supported for right operand type
|
||||
# `Union[Tensor, Module]`.
|
||||
if li in self._input_skips:
|
||||
if self._skip_affine_trans:
|
||||
@@ -273,7 +271,6 @@ class MLPDecoder(DecoderFunctionBase):
|
||||
|
||||
input_dim: int = 3
|
||||
param_groups: Dict[str, str] = field(default_factory=lambda: {})
|
||||
# pyre-fixme[13]: Attribute `network` is never initialized.
|
||||
network: MLPWithInputSkips
|
||||
|
||||
def __post_init__(self):
|
||||
@@ -351,7 +348,6 @@ class TransformerWithInputSkips(torch.nn.Module):
|
||||
self.last = torch.nn.Linear(dimout, output_dim)
|
||||
_xavier_init(self.last)
|
||||
|
||||
# pyre-fixme[8]: Attribute has type `Tuple[ModuleList, ModuleList]`; used as
|
||||
# `ModuleList`.
|
||||
self.layers_pool, self.layers_ray = (
|
||||
torch.nn.ModuleList(layers_pool),
|
||||
|
||||
@@ -177,7 +177,6 @@ class IdrFeatureField(ImplicitFunctionBase, torch.nn.Module):
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[An...
|
||||
x = self.linear_layers[layer_idx](x)
|
||||
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, other: Union[bool, complex,
|
||||
# float, int, Tensor]) -> Tensor, Module, Tensor]` is not a function.
|
||||
if layer_idx < self.num_layers - 2:
|
||||
# pyre-fixme[29]: `Union[Module, Tensor]` is not a function.
|
||||
|
||||
@@ -125,7 +125,6 @@ class NeuralRadianceFieldBase(ImplicitFunctionBase, torch.nn.Module):
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
rays_embedding = self.harmonic_embedding_dir(rays_directions_normed)
|
||||
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
return self.color_layer((self.intermediate_linear(features), rays_embedding))
|
||||
|
||||
@staticmethod
|
||||
@@ -196,7 +195,6 @@ class NeuralRadianceFieldBase(ImplicitFunctionBase, torch.nn.Module):
|
||||
embeds = create_embeddings_for_implicit_function(
|
||||
xyz_world=rays_points_world,
|
||||
# for 2nd param but got `Union[None, torch.Tensor, torch.nn.Module]`.
|
||||
# pyre-fixme[6]: For 2nd argument expected `Optional[(...) -> Any]` but
|
||||
# got `Union[None, Tensor, Module]`.
|
||||
xyz_embedding_function=(
|
||||
self.harmonic_embedding_xyz if self.input_xyz else None
|
||||
@@ -224,7 +222,6 @@ class NeuralRadianceFieldBase(ImplicitFunctionBase, torch.nn.Module):
|
||||
if camera is None:
|
||||
raise ValueError("Camera must be given if xyz_ray_dir_in_camera_coords")
|
||||
|
||||
# pyre-fixme[58]: `@` is not supported for operand types `Tensor` and
|
||||
# `Union[Tensor, Module]`.
|
||||
directions = ray_bundle.directions @ camera.R
|
||||
else:
|
||||
|
||||
@@ -171,7 +171,6 @@ class SRNPixelGenerator(Configurable, torch.nn.Module):
|
||||
# Obtain the harmonic embedding of the normalized ray directions.
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
rays_embedding = self._harmonic_embedding(rays_directions_normed)
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
return self._color_layer((features, rays_embedding))
|
||||
|
||||
def forward(
|
||||
@@ -208,7 +207,6 @@ class SRNPixelGenerator(Configurable, torch.nn.Module):
|
||||
if camera is None:
|
||||
raise ValueError("Camera must be given if xyz_ray_dir_in_camera_coords")
|
||||
|
||||
# pyre-fixme[58]: `@` is not supported for operand types `Tensor` and
|
||||
# `Union[Tensor, Module]`.
|
||||
directions = ray_bundle.directions @ camera.R
|
||||
else:
|
||||
@@ -331,9 +329,7 @@ class SRNRaymarchHyperNet(Configurable, torch.nn.Module):
|
||||
@registry.register
|
||||
class SRNImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
latent_dim: int = 0
|
||||
# pyre-fixme[13]: Attribute `raymarch_function` is never initialized.
|
||||
raymarch_function: SRNRaymarchFunction
|
||||
# pyre-fixme[13]: Attribute `pixel_generator` is never initialized.
|
||||
pixel_generator: SRNPixelGenerator
|
||||
|
||||
def __post_init__(self):
|
||||
@@ -389,9 +385,7 @@ class SRNHyperNetImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
|
||||
latent_dim_hypernet: int = 0
|
||||
latent_dim: int = 0
|
||||
# pyre-fixme[13]: Attribute `hypernet` is never initialized.
|
||||
hypernet: SRNRaymarchHyperNet
|
||||
# pyre-fixme[13]: Attribute `pixel_generator` is never initialized.
|
||||
pixel_generator: SRNPixelGenerator
|
||||
|
||||
def __post_init__(self):
|
||||
|
||||
@@ -844,7 +844,6 @@ class VoxelGridModule(Configurable, torch.nn.Module):
|
||||
"""
|
||||
|
||||
voxel_grid_class_type: str = "FullResolutionVoxelGrid"
|
||||
# pyre-fixme[13]: Attribute `voxel_grid` is never initialized.
|
||||
voxel_grid: VoxelGridBase
|
||||
|
||||
extents: Tuple[float, float, float] = (2.0, 2.0, 2.0)
|
||||
@@ -907,7 +906,6 @@ class VoxelGridModule(Configurable, torch.nn.Module):
|
||||
else:
|
||||
# Torch Module to hold parameters since they can only be registered
|
||||
# at object level.
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self.params = _RegistratedBufferDict(vars(params))
|
||||
|
||||
@staticmethod
|
||||
@@ -996,7 +994,6 @@ class VoxelGridModule(Configurable, torch.nn.Module):
|
||||
"""
|
||||
'''
|
||||
new_params = {}
|
||||
# pyre-fixme[29]: `Union[(self: Tensor) -> Any, Tensor, Module]` is not a
|
||||
# function.
|
||||
for name in self.params:
|
||||
key = prefix + "params." + name
|
||||
@@ -1035,7 +1032,6 @@ class VoxelGridModule(Configurable, torch.nn.Module):
|
||||
grid_values, _ = self.voxel_grid.change_resolution(
|
||||
new_grid_values, grid_values_with_wanted_resolution=old_grid_values
|
||||
)
|
||||
# pyre-fixme[16]: `VoxelGridModule` has no attribute `params`.
|
||||
self.params = torch.nn.ParameterDict(
|
||||
{
|
||||
k: torch.nn.Parameter(val)
|
||||
|
||||
@@ -142,11 +142,9 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
"""
|
||||
|
||||
# ---- voxel grid for density
|
||||
# pyre-fixme[13]: Attribute `voxel_grid_density` is never initialized.
|
||||
voxel_grid_density: VoxelGridModule
|
||||
|
||||
# ---- voxel grid for color
|
||||
# pyre-fixme[13]: Attribute `voxel_grid_color` is never initialized.
|
||||
voxel_grid_color: VoxelGridModule
|
||||
|
||||
# ---- harmonic embeddings density
|
||||
@@ -162,12 +160,10 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
|
||||
# ---- decoder function for density
|
||||
decoder_density_class_type: str = "MLPDecoder"
|
||||
# pyre-fixme[13]: Attribute `decoder_density` is never initialized.
|
||||
decoder_density: DecoderFunctionBase
|
||||
|
||||
# ---- decoder function for color
|
||||
decoder_color_class_type: str = "MLPDecoder"
|
||||
# pyre-fixme[13]: Attribute `decoder_color` is never initialized.
|
||||
decoder_color: DecoderFunctionBase
|
||||
|
||||
# ---- cuda streams
|
||||
@@ -190,25 +186,20 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
run_auto_creation(self)
|
||||
# pyre-fixme[16]: `VoxelGridImplicitFunction` has no attribute
|
||||
# `voxel_grid_scaffold`.
|
||||
self.voxel_grid_scaffold = self._create_voxel_grid_scaffold()
|
||||
# pyre-fixme[16]: `VoxelGridImplicitFunction` has no attribute
|
||||
# `harmonic_embedder_xyz_density`.
|
||||
self.harmonic_embedder_xyz_density = HarmonicEmbedding(
|
||||
**self.harmonic_embedder_xyz_density_args
|
||||
)
|
||||
# pyre-fixme[16]: `VoxelGridImplicitFunction` has no attribute
|
||||
# `harmonic_embedder_xyz_color`.
|
||||
self.harmonic_embedder_xyz_color = HarmonicEmbedding(
|
||||
**self.harmonic_embedder_xyz_color_args
|
||||
)
|
||||
# pyre-fixme[16]: `VoxelGridImplicitFunction` has no attribute
|
||||
# `harmonic_embedder_dir_color`.
|
||||
self.harmonic_embedder_dir_color = HarmonicEmbedding(
|
||||
**self.harmonic_embedder_dir_color_args
|
||||
)
|
||||
# pyre-fixme[16]: `VoxelGridImplicitFunction` has no attribute
|
||||
# `_scaffold_ready`.
|
||||
self._scaffold_ready = False
|
||||
|
||||
@@ -372,7 +363,6 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
feature dimensionality which `decoder_density` returns
|
||||
"""
|
||||
embeds_density = self.voxel_grid_density(points)
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
harmonic_embedding_density = self.harmonic_embedder_xyz_density(embeds_density)
|
||||
# shape = [..., density_dim]
|
||||
return self.decoder_density(harmonic_embedding_density)
|
||||
@@ -407,7 +397,6 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
if self.xyz_ray_dir_in_camera_coords:
|
||||
if camera is None:
|
||||
raise ValueError("Camera must be given if xyz_ray_dir_in_camera_coords")
|
||||
# pyre-fixme[58]: `@` is not supported for operand types `Tensor` and
|
||||
# `Union[Tensor, Module]`.
|
||||
directions = directions @ camera.R
|
||||
|
||||
@@ -417,13 +406,11 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
|
||||
# ########## embed with the harmonic function ########## #
|
||||
# Obtain the harmonic embedding of the voxel grid output.
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
harmonic_embedding_color = self.harmonic_embedder_xyz_color(embeds_color)
|
||||
|
||||
# Normalize the ray_directions to unit l2 norm.
|
||||
rays_directions_normed = torch.nn.functional.normalize(directions, dim=-1)
|
||||
# Obtain the harmonic embedding of the normalized ray directions.
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
harmonic_embedding_dir = self.harmonic_embedder_dir_color(
|
||||
rays_directions_normed
|
||||
)
|
||||
@@ -493,7 +480,6 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
an object inside, else False.
|
||||
"""
|
||||
# find bounding box
|
||||
# pyre-fixme[16]: Item `Tensor` of `Tensor | Module` has no attribute
|
||||
# `get_grid_points`.
|
||||
points = self.voxel_grid_scaffold.get_grid_points(epoch=epoch)
|
||||
assert self._scaffold_ready, "Scaffold has to be calculated before cropping."
|
||||
@@ -529,7 +515,6 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
"""
|
||||
|
||||
planes = []
|
||||
# pyre-fixme[16]: Item `Tensor` of `Tensor | Module` has no attribute
|
||||
# `get_grid_points`.
|
||||
points = self.voxel_grid_scaffold.get_grid_points(epoch=epoch)
|
||||
|
||||
@@ -550,9 +535,7 @@ class VoxelGridImplicitFunction(ImplicitFunctionBase, torch.nn.Module):
|
||||
stride=1,
|
||||
)
|
||||
occupancy_cube = density_cube > self.scaffold_empty_space_threshold
|
||||
# pyre-fixme[16]: Item `Tensor` of `Tensor | Module` has no attribute `params`.
|
||||
self.voxel_grid_scaffold.params["voxel_grid"] = occupancy_cube.float()
|
||||
# pyre-fixme[16]: `VoxelGridImplicitFunction` has no attribute
|
||||
# `_scaffold_ready`.
|
||||
self._scaffold_ready = True
|
||||
|
||||
|
||||
@@ -195,34 +195,27 @@ class OverfitModel(ImplicitronModelBase):
|
||||
|
||||
# ---- global encoder settings
|
||||
global_encoder_class_type: Optional[str] = None
|
||||
# pyre-fixme[13]: Attribute `global_encoder` is never initialized.
|
||||
global_encoder: Optional[GlobalEncoderBase]
|
||||
|
||||
# ---- raysampler
|
||||
raysampler_class_type: str = "AdaptiveRaySampler"
|
||||
# pyre-fixme[13]: Attribute `raysampler` is never initialized.
|
||||
raysampler: RaySamplerBase
|
||||
|
||||
# ---- renderer configs
|
||||
renderer_class_type: str = "MultiPassEmissionAbsorptionRenderer"
|
||||
# pyre-fixme[13]: Attribute `renderer` is never initialized.
|
||||
renderer: BaseRenderer
|
||||
|
||||
# ---- implicit function settings
|
||||
share_implicit_function_across_passes: bool = False
|
||||
implicit_function_class_type: str = "NeuralRadianceFieldImplicitFunction"
|
||||
# pyre-fixme[13]: Attribute `implicit_function` is never initialized.
|
||||
implicit_function: ImplicitFunctionBase
|
||||
coarse_implicit_function_class_type: Optional[str] = None
|
||||
# pyre-fixme[13]: Attribute `coarse_implicit_function` is never initialized.
|
||||
coarse_implicit_function: Optional[ImplicitFunctionBase]
|
||||
|
||||
# ----- metrics
|
||||
# pyre-fixme[13]: Attribute `view_metrics` is never initialized.
|
||||
view_metrics: ViewMetricsBase
|
||||
view_metrics_class_type: str = "ViewMetrics"
|
||||
|
||||
# pyre-fixme[13]: Attribute `regularization_metrics` is never initialized.
|
||||
regularization_metrics: RegularizationMetricsBase
|
||||
regularization_metrics_class_type: str = "RegularizationMetrics"
|
||||
|
||||
@@ -658,7 +651,6 @@ class OverfitModel(ImplicitronModelBase):
|
||||
|
||||
implicit_function_type = registry.get(
|
||||
ImplicitFunctionBase,
|
||||
# pyre-ignore: config is None allow to check if this is None.
|
||||
self.coarse_implicit_function_class_type,
|
||||
)
|
||||
expand_args_fields(implicit_function_type)
|
||||
|
||||
@@ -108,7 +108,6 @@ class ImplicitronRayBundle:
|
||||
def lengths(self) -> torch.Tensor:
|
||||
if self.bins is not None:
|
||||
# equivalent to: 0.5 * (bins[..., 1:] + bins[..., :-1]) but more efficient
|
||||
# pyre-ignore
|
||||
return torch.lerp(self.bins[..., :-1], self.bins[..., 1:], 0.5)
|
||||
# pyrefly: ignore [bad-return]
|
||||
return self._lengths
|
||||
|
||||
@@ -135,7 +135,6 @@ class LSTMRenderer(BaseRenderer, torch.nn.Module):
|
||||
break
|
||||
|
||||
# run the lstm marcher
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
state_h, state_c = self._lstm(
|
||||
raymarch_features.view(-1, raymarch_features.shape[-1]),
|
||||
states[-1],
|
||||
|
||||
@@ -84,7 +84,6 @@ class MultiPassEmissionAbsorptionRenderer(BaseRenderer, torch.nn.Module):
|
||||
"""
|
||||
|
||||
raymarcher_class_type: str = "EmissionAbsorptionRaymarcher"
|
||||
# pyre-fixme[13]: Attribute `raymarcher` is never initialized.
|
||||
raymarcher: RaymarcherBase
|
||||
|
||||
n_pts_per_ray_fine_training: int = 64
|
||||
|
||||
@@ -42,9 +42,7 @@ class RayPointRefiner(Configurable, torch.nn.Module):
|
||||
for Anti-Aliasing Neural Radiance Fields." ICCV 2021.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `n_pts_per_ray` is never initialized.
|
||||
n_pts_per_ray: int
|
||||
# pyre-fixme[13]: Attribute `random_sampling` is never initialized.
|
||||
random_sampling: bool
|
||||
add_input_samples: bool = True
|
||||
blurpool_weights: bool = False
|
||||
|
||||
@@ -207,7 +207,6 @@ class AbstractMaskRaySampler(RaySamplerBase, torch.nn.Module):
|
||||
"""
|
||||
sample_mask = None
|
||||
if (
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[An...
|
||||
self._sampling_mode[evaluation_mode] == RenderSamplingMode.MASK_SAMPLE
|
||||
and mask is not None
|
||||
):
|
||||
@@ -242,7 +241,6 @@ class AbstractMaskRaySampler(RaySamplerBase, torch.nn.Module):
|
||||
"Heterogeneous ray bundle is not supported for conical frustum computation yet"
|
||||
)
|
||||
elif self.cast_ray_bundle_as_cone:
|
||||
# pyre-fixme[9]: pixel_hw has type `Tuple[float, float]`; used as
|
||||
# `Tuple[Union[Tensor, Module], Union[Tensor, Module]]`.
|
||||
pixel_hw: Tuple[float, float] = (self.pixel_height, self.pixel_width)
|
||||
pixel_radii_2d = compute_radii(cameras, ray_bundle.xys[..., :2], pixel_hw)
|
||||
|
||||
@@ -571,7 +571,6 @@ def _get_sphere_intersection(
|
||||
# cam_loc = cam_loc.unsqueeze(-1)
|
||||
# ray_cam_dot = torch.bmm(ray_directions, cam_loc).squeeze()
|
||||
ray_cam_dot = (ray_directions * cam_loc).sum(-1) # n_images x n_rays
|
||||
# pyre-fixme[58]: `**` is not supported for operand types `Tensor` and `int`.
|
||||
under_sqrt = ray_cam_dot**2 - (cam_loc.norm(2, dim=-1) ** 2 - r**2)
|
||||
|
||||
under_sqrt = under_sqrt.reshape(-1)
|
||||
|
||||
@@ -27,7 +27,6 @@ from .rgb_net import RayNormalColoringNetwork
|
||||
class SignedDistanceFunctionRenderer(BaseRenderer, torch.nn.Module):
|
||||
render_features_dimensions: int = 3
|
||||
object_bounding_sphere: float = 1.0
|
||||
# pyre-fixme[13]: Attribute `ray_tracer` is never initialized.
|
||||
ray_tracer: RayTracing
|
||||
ray_normal_coloring_network_args: DictConfig = get_default_args_field(
|
||||
RayNormalColoringNetwork
|
||||
@@ -208,7 +207,6 @@ class SignedDistanceFunctionRenderer(BaseRenderer, torch.nn.Module):
|
||||
]
|
||||
normals_full.view(-1, 3)[surface_mask] = normals
|
||||
render_full.view(-1, self.render_features_dimensions)[surface_mask] = (
|
||||
# pyre-fixme[29]: `Union[Tensor, Module]` is not a function.
|
||||
self._rgb_network(
|
||||
features,
|
||||
differentiable_surface_points[None],
|
||||
|
||||
@@ -532,7 +532,6 @@ def _get_ray_dir_dot_prods(camera: CamerasBase, pts: torch.Tensor):
|
||||
|
||||
# does not produce nans randomly unlike get_camera_center() below
|
||||
cam_centers_rep = -torch.bmm(
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[Any, A...
|
||||
camera_rep.T[:, None],
|
||||
camera_rep.R.permute(0, 2, 1),
|
||||
).reshape(-1, *([1] * (pts.ndim - 2)), 3)
|
||||
@@ -632,7 +631,6 @@ def _avgmaxstd_reduction_function(
|
||||
x_aggr = torch.cat(pooled_features, dim=-1)
|
||||
|
||||
# zero out features that were all masked out
|
||||
# pyre-fixme[16]: `bool` has no attribute `type_as`.
|
||||
any_active = (w.max(dim=dim, keepdim=True).values > 1e-4).type_as(x_aggr)
|
||||
x_aggr = x_aggr * any_active[..., None]
|
||||
|
||||
@@ -660,7 +658,6 @@ def _std_reduction_function(
|
||||
):
|
||||
if mu is None:
|
||||
mu = _avg_reduction_function(x, w, dim=dim)
|
||||
# pyre-fixme[58]: `**` is not supported for operand types `Tensor` and `int`.
|
||||
std = wmean((x - mu) ** 2, w, dim=dim, eps=1e-2).clamp(1e-4).sqrt()
|
||||
# FIXME: somehow this is extremely heavy in mem?
|
||||
return std
|
||||
|
||||
@@ -34,10 +34,8 @@ class ViewPooler(Configurable, torch.nn.Module):
|
||||
from a set of source images. FeatureAggregator executes step (4) above.
|
||||
"""
|
||||
|
||||
# pyre-fixme[13]: Attribute `view_sampler` is never initialized.
|
||||
view_sampler: ViewSampler
|
||||
feature_aggregator_class_type: str = "AngleWeightedReductionFeatureAggregator"
|
||||
# pyre-fixme[13]: Attribute `feature_aggregator` is never initialized.
|
||||
feature_aggregator: FeatureAggregatorBase
|
||||
|
||||
def __post_init__(self):
|
||||
|
||||
@@ -312,7 +312,6 @@ class _Registry:
|
||||
raise ValueError(
|
||||
f"{name} resolves to {result} which does not subclass {base_class_wanted}"
|
||||
)
|
||||
# pyre-ignore[7]
|
||||
return result
|
||||
|
||||
def get_all(
|
||||
|
||||
@@ -51,7 +51,6 @@ def cleanup_eval_depth(
|
||||
# the threshold is a sigma-multiple of the standard deviation of the depth
|
||||
mu = wmean(depth.view(ba, -1, 1), mask.view(ba, -1)).view(ba, 1)
|
||||
std = (
|
||||
# pyre-fixme[58]: `**` is not supported for operand types `Tensor` and `int`.
|
||||
wmean((depth.view(ba, -1) - mu).view(ba, -1, 1) ** 2, mask.view(ba, -1))
|
||||
.clamp(1e-4)
|
||||
.sqrt()
|
||||
|
||||
@@ -182,10 +182,12 @@ def generate_eval_video_cameras(
|
||||
)
|
||||
|
||||
test_cameras = PerspectiveCameras(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
focal_length=focal_length,
|
||||
principal_point=principal_point,
|
||||
R=R,
|
||||
T=T,
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
device=focal_length.device,
|
||||
)
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ def eval_depth(
|
||||
|
||||
df = gt - pred
|
||||
|
||||
# pyre-fixme[58]: `**` is not supported for operand types `Tensor` and `int`.
|
||||
mse_depth = (dmask * (df**2)).sum((1, 2, 3)) / dmask_mass
|
||||
abs_depth = (dmask * df.abs()).sum((1, 2, 3)) / dmask_mass
|
||||
|
||||
@@ -115,10 +114,8 @@ def calc_mse(
|
||||
Calculates the mean square error between tensors `x` and `y`.
|
||||
"""
|
||||
if mask is None:
|
||||
# pyre-fixme[58]: `**` is not supported for operand types `Tensor` and `int`.
|
||||
return torch.mean((x - y) ** 2)
|
||||
else:
|
||||
# pyre-fixme[58]: `**` is not supported for operand types `Tensor` and `int`.
|
||||
return (((x - y) ** 2) * mask).sum() / mask.expand_as(x).sum().clamp(1e-5)
|
||||
|
||||
|
||||
@@ -146,7 +143,6 @@ def calc_bce(
|
||||
mask_bg = (1 - mask_fg) * mask
|
||||
weight = mask_fg / mask_fg.sum().clamp(1.0) + mask_bg / mask_bg.sum().clamp(1.0)
|
||||
# weight sum should be at this point ~2
|
||||
# pyre-fixme[58]: `/` is not supported for operand types `int` and `Tensor`.
|
||||
weight = weight * (weight.numel() / weight.sum().clamp(1.0))
|
||||
else:
|
||||
weight = torch.ones_like(gt) * mask
|
||||
|
||||
@@ -49,7 +49,6 @@ def get_stats_path(fl, eval_results: bool = False) -> str:
|
||||
break
|
||||
else:
|
||||
flstats = "%s_stats.jgz" % fl
|
||||
# pyre-fixme[61]: `flstats` is undefined, or not always defined.
|
||||
return flstats
|
||||
|
||||
|
||||
@@ -148,15 +147,12 @@ def find_last_checkpoint(
|
||||
)
|
||||
if len(fls) > 0:
|
||||
break
|
||||
# pyre-fixme[61]: `fls` is undefined, or not always defined.
|
||||
if len(fls) == 0:
|
||||
fl = None
|
||||
else:
|
||||
if all_checkpoints:
|
||||
# pyre-fixme[61]: `fls` is undefined, or not always defined.
|
||||
fl = [f[0 : -len(ext)] + ".pth" for f in fls]
|
||||
else:
|
||||
# pyre-fixme[61]: `ext` is undefined, or not always defined.
|
||||
fl = fls[-1][0 : -len(ext)] + ".pth"
|
||||
|
||||
return fl
|
||||
|
||||
@@ -62,7 +62,6 @@ def rasterize_sparse_ray_bundle(
|
||||
|
||||
max_size = torch.max(camera_counts).item()
|
||||
features_depth_ras = packed_to_padded(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
features_depth_ras[:, 0],
|
||||
first_idxs,
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
|
||||
@@ -218,7 +218,6 @@ def load_obj(
|
||||
"""
|
||||
data_dir = "./"
|
||||
if isinstance(f, (str, bytes, Path)):
|
||||
# pyre-fixme[6]: For 1st argument expected `PathLike[Variable[AnyStr <:
|
||||
# [str, bytes]]]` but got `Union[Path, bytes, str]`.
|
||||
data_dir = os.path.dirname(f)
|
||||
if path_manager is None:
|
||||
@@ -713,6 +712,7 @@ def save_obj(
|
||||
faces_normals_idx: LongTensor of shape (F, 3) giving the index into
|
||||
normals for each vertex in the face.
|
||||
verts_uvs: FloatTensor of shape (V, 2) giving the uv coordinate per vertex.
|
||||
When provided with faces_uvs, UVs are saved even without a texture_map.
|
||||
faces_uvs: LongTensor of shape (F, 3) giving the index into verts_uvs for
|
||||
each vertex in the face.
|
||||
texture_map: FloatTensor of shape (H, W, 3) representing the texture map
|
||||
@@ -758,7 +758,8 @@ def save_obj(
|
||||
if path_manager is None:
|
||||
path_manager = PathManager()
|
||||
|
||||
save_texture = all(t is not None for t in [faces_uvs, verts_uvs, texture_map])
|
||||
save_uvs = faces_uvs is not None and verts_uvs is not None
|
||||
save_texture = save_uvs and texture_map is not None
|
||||
output_path = Path(f)
|
||||
|
||||
# Save the .obj file
|
||||
@@ -779,7 +780,7 @@ def save_obj(
|
||||
faces_normals_idx=faces_normals_idx,
|
||||
verts_uvs=verts_uvs,
|
||||
faces_uvs=faces_uvs,
|
||||
save_texture=save_texture,
|
||||
save_uvs=save_uvs,
|
||||
save_normals=normals is not None,
|
||||
)
|
||||
|
||||
@@ -817,7 +818,7 @@ def _save(
|
||||
faces_normals_idx: Optional[torch.Tensor] = None,
|
||||
verts_uvs: Optional[torch.Tensor] = None,
|
||||
faces_uvs: Optional[torch.Tensor] = None,
|
||||
save_texture: bool = False,
|
||||
save_uvs: bool = False,
|
||||
save_normals: bool = False,
|
||||
) -> None:
|
||||
if len(verts) and (verts.dim() != 2 or verts.size(1) != 3):
|
||||
@@ -833,26 +834,24 @@ def _save(
|
||||
return
|
||||
|
||||
verts, faces = verts.cpu(), faces.cpu()
|
||||
vert_rows = verts.detach().cpu().numpy()
|
||||
|
||||
lines = ""
|
||||
lines = []
|
||||
|
||||
if decimal_places is None:
|
||||
float_str = "%f"
|
||||
else:
|
||||
float_str = "%" + ".%df" % decimal_places
|
||||
|
||||
if len(verts):
|
||||
V, D = verts.shape
|
||||
for i in range(V):
|
||||
vert = [float_str % verts[i, j] for j in range(D)]
|
||||
lines += "v %s\n" % " ".join(vert)
|
||||
for vert in vert_rows:
|
||||
lines.append("v %s\n" % " ".join(float_str % v for v in vert))
|
||||
|
||||
if save_normals:
|
||||
assert normals is not None
|
||||
assert faces_normals_idx is not None
|
||||
lines += _write_normals(normals, faces_normals_idx, float_str)
|
||||
lines.append(_write_normals(normals, float_str))
|
||||
|
||||
if save_texture:
|
||||
if save_uvs:
|
||||
assert faces_uvs is not None
|
||||
assert verts_uvs is not None
|
||||
|
||||
@@ -865,15 +864,13 @@ def _save(
|
||||
raise ValueError(message)
|
||||
|
||||
verts_uvs, faces_uvs = verts_uvs.cpu(), faces_uvs.cpu()
|
||||
uv_rows = verts_uvs.detach().cpu().numpy()
|
||||
|
||||
# Save verts uvs after verts
|
||||
if len(verts_uvs):
|
||||
uV, uD = verts_uvs.shape
|
||||
for i in range(uV):
|
||||
uv = [float_str % verts_uvs[i, j] for j in range(uD)]
|
||||
lines += "vt %s\n" % " ".join(uv)
|
||||
for uv in uv_rows:
|
||||
lines.append("vt %s\n" % " ".join(float_str % u for u in uv))
|
||||
|
||||
f.write(lines)
|
||||
f.write("".join(lines))
|
||||
|
||||
if torch.any(faces >= verts.shape[0]) or torch.any(faces < 0):
|
||||
warnings.warn("Faces have invalid indices")
|
||||
@@ -882,31 +879,21 @@ def _save(
|
||||
_write_faces(
|
||||
f,
|
||||
faces,
|
||||
faces_uvs if save_texture else None,
|
||||
faces_uvs if save_uvs else None,
|
||||
faces_normals_idx if save_normals else None,
|
||||
)
|
||||
|
||||
|
||||
def _write_normals(
|
||||
normals: torch.Tensor, faces_normals_idx: torch.Tensor, float_str: str
|
||||
) -> str:
|
||||
if faces_normals_idx.dim() != 2 or faces_normals_idx.size(1) != 3:
|
||||
message = (
|
||||
"'faces_normals_idx' should either be empty or of shape (num_faces, 3)."
|
||||
)
|
||||
raise ValueError(message)
|
||||
|
||||
def _write_normals(normals: torch.Tensor, float_str: str) -> str:
|
||||
if normals.dim() != 2 or normals.size(1) != 3:
|
||||
message = "'normals' should either be empty or of shape (num_verts, 3)."
|
||||
raise ValueError(message)
|
||||
|
||||
normals, faces_normals_idx = normals.cpu(), faces_normals_idx.cpu()
|
||||
normal_rows = normals.detach().cpu().numpy()
|
||||
|
||||
lines = []
|
||||
V, D = normals.shape
|
||||
for i in range(V):
|
||||
normal = [float_str % normals[i, j] for j in range(D)]
|
||||
lines.append("vn %s\n" % " ".join(normal))
|
||||
for normal in normal_rows:
|
||||
lines.append("vn %s\n" % " ".join(float_str % n for n in normal))
|
||||
return "".join(lines)
|
||||
|
||||
|
||||
@@ -916,31 +903,37 @@ def _write_faces(
|
||||
faces_uvs: Optional[torch.Tensor],
|
||||
faces_normals_idx: Optional[torch.Tensor],
|
||||
) -> None:
|
||||
face_rows = faces.detach().cpu().numpy()
|
||||
uv_rows = faces_uvs.detach().cpu().numpy() if faces_uvs is not None else None
|
||||
normal_rows = (
|
||||
faces_normals_idx.detach().cpu().numpy()
|
||||
if faces_normals_idx is not None
|
||||
else None
|
||||
)
|
||||
|
||||
F, P = faces.shape
|
||||
for i in range(F):
|
||||
if faces_normals_idx is not None:
|
||||
if faces_uvs is not None:
|
||||
face_row = face_rows[i]
|
||||
if normal_rows is not None:
|
||||
normal_row = normal_rows[i]
|
||||
if uv_rows is not None:
|
||||
uv_row = uv_rows[i]
|
||||
# Format faces as {verts_idx}/{verts_uvs_idx}/{verts_normals_idx}
|
||||
face = [
|
||||
"%d/%d/%d"
|
||||
% (
|
||||
faces[i, j] + 1,
|
||||
faces_uvs[i, j] + 1,
|
||||
faces_normals_idx[i, j] + 1,
|
||||
)
|
||||
"%d/%d/%d" % (face_row[j] + 1, uv_row[j] + 1, normal_row[j] + 1)
|
||||
for j in range(P)
|
||||
]
|
||||
else:
|
||||
# Format faces as {verts_idx}//{verts_normals_idx}
|
||||
face = [
|
||||
"%d//%d" % (faces[i, j] + 1, faces_normals_idx[i, j] + 1)
|
||||
for j in range(P)
|
||||
"%d//%d" % (face_row[j] + 1, normal_row[j] + 1) for j in range(P)
|
||||
]
|
||||
elif faces_uvs is not None:
|
||||
elif uv_rows is not None:
|
||||
uv_row = uv_rows[i]
|
||||
# Format faces as {verts_idx}/{verts_uvs_idx}
|
||||
face = ["%d/%d" % (faces[i, j] + 1, faces_uvs[i, j] + 1) for j in range(P)]
|
||||
face = ["%d/%d" % (face_row[j] + 1, uv_row[j] + 1) for j in range(P)]
|
||||
else:
|
||||
face = ["%d" % (faces[i, j] + 1) for j in range(P)]
|
||||
face = ["%d" % (face_row[j] + 1) for j in range(P)]
|
||||
|
||||
if i + 1 < F:
|
||||
f.write("f %s\n" % " ".join(face))
|
||||
|
||||
@@ -122,16 +122,13 @@ def corresponding_cameras_alignment(
|
||||
|
||||
# create a new cameras object and set the R and T accordingly
|
||||
cameras_src_aligned = cameras_src.clone()
|
||||
# pyre-fixme[6]: For 2nd argument expected `Tensor` but got `Union[Tensor, Module]`.
|
||||
cameras_src_aligned.R = torch.bmm(align_t_R.expand_as(cameras_src.R), cameras_src.R)
|
||||
cameras_src_aligned.T = (
|
||||
torch.bmm(
|
||||
align_t_T[:, None].repeat(cameras_src.R.shape[0], 1, 1),
|
||||
# pyre-fixme[6]: For 2nd argument expected `Tensor` but got
|
||||
# `Union[Tensor, Module]`.
|
||||
cameras_src.R,
|
||||
)[:, 0]
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, other: Union[bool, complex,
|
||||
# float, int, Tensor]) -> Tensor, Tensor, Module]` is not a function.
|
||||
+ cameras_src.T * align_t_s
|
||||
)
|
||||
@@ -180,8 +177,6 @@ def _align_camera_extrinsics(
|
||||
R_A = (U V^T)^T
|
||||
```
|
||||
"""
|
||||
# pyre-fixme[6]: For 1st argument expected `Tensor` but got `Union[Tensor, Module]`.
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, dim0: int, dim1: int) -> Tensor,
|
||||
# Tensor, Module]` is not a function.
|
||||
RRcov = torch.bmm(cameras_src.R, cameras_tgt.R.transpose(2, 1)).mean(0)
|
||||
U, _, V = torch.svd(RRcov)
|
||||
@@ -212,11 +207,7 @@ def _align_camera_extrinsics(
|
||||
T_A = mean(B) - mean(A) * s_A
|
||||
```
|
||||
"""
|
||||
# pyre-fixme[6]: For 1st argument expected `Tensor` but got `Union[Tensor, Module]`.
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[Any, Any, ...
|
||||
A = torch.bmm(cameras_src.R, cameras_src.T[:, :, None])[:, :, 0]
|
||||
# pyre-fixme[6]: For 1st argument expected `Tensor` but got `Union[Tensor, Module]`.
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[Any, Any, ...
|
||||
B = torch.bmm(cameras_src.R, cameras_tgt.T[:, :, None])[:, :, 0]
|
||||
Amu = A.mean(0, keepdim=True)
|
||||
Bmu = B.mean(0, keepdim=True)
|
||||
|
||||
@@ -103,7 +103,6 @@ def cot_laplacian(
|
||||
s = 0.5 * (A + B + C)
|
||||
# note that the area can be negative (close to 0) causing nans after sqrt()
|
||||
# we clip it to a small positive value
|
||||
# pyre-fixme[16]: `float` has no attribute `clamp`.
|
||||
area = (s * (s - A) * (s - B) * (s - C)).clamp(min=eps).sqrt()
|
||||
|
||||
# Compute cotangents of angles, of shape (sum(F_n), 3)
|
||||
|
||||
@@ -340,8 +340,11 @@ def corresponding_points_alignment(
|
||||
total_weight = torch.clamp(num_points, 1)
|
||||
# special handling for heterogeneous point clouds and/or input weights
|
||||
if weights is not None:
|
||||
# pyrefly: ignore [bad-index]
|
||||
Xc *= weights[:, :, None]
|
||||
# pyrefly: ignore [bad-index]
|
||||
Yc *= weights[:, :, None]
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
total_weight = torch.clamp(weights.sum(1), eps)
|
||||
|
||||
if (num_points < (dim + 1)).any():
|
||||
|
||||
@@ -156,7 +156,6 @@ def estimate_pointcloud_local_coord_frames(
|
||||
if disambiguate_directions:
|
||||
# disambiguate normal
|
||||
n = _disambiguate_vector_directions(
|
||||
# pyrefly: ignore [unsupported-operation]
|
||||
points_centered,
|
||||
knns,
|
||||
# pyrefly: ignore [unsupported-operation]
|
||||
@@ -164,7 +163,6 @@ def estimate_pointcloud_local_coord_frames(
|
||||
)
|
||||
# disambiguate the main curvature
|
||||
z = _disambiguate_vector_directions(
|
||||
# pyrefly: ignore [unsupported-operation]
|
||||
points_centered,
|
||||
knns,
|
||||
# pyrefly: ignore [unsupported-operation]
|
||||
|
||||
@@ -168,9 +168,7 @@ def sample_farthest_points_naive(
|
||||
sample_idx_batch[0] = selected_idx
|
||||
|
||||
# If the pointcloud has fewer than K points then only iterate over the min
|
||||
# pyre-fixme[6]: For 1st param expected `SupportsRichComparisonT` but got
|
||||
# `Tensor`.
|
||||
# pyre-fixme[6]: For 2nd param expected `SupportsRichComparisonT` but got
|
||||
# `Tensor`.
|
||||
k_n = min(lengths[n], K[n])
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@ def wmean(
|
||||
args = {"dim": dim, "keepdim": keepdim}
|
||||
|
||||
if weight is None:
|
||||
# pyre-fixme[6]: For 1st param expected `Optional[dtype]` but got
|
||||
# `Union[Tuple[int], int]`.
|
||||
return x.mean(**args)
|
||||
|
||||
@@ -101,7 +100,6 @@ def wmean(
|
||||
):
|
||||
raise ValueError("wmean: weights are not compatible with the tensor")
|
||||
|
||||
# pyre-fixme[6]: For 1st param expected `Optional[dtype]` but got
|
||||
# `Union[Tuple[int], int]`.
|
||||
return (x * weight[..., None]).sum(**args) / weight[..., None].sum(**args).clamp(
|
||||
eps
|
||||
|
||||
@@ -228,7 +228,6 @@ def softmax_rgb_blend(
|
||||
|
||||
# Also apply exp normalize trick for the background color weight.
|
||||
# Clamp to ensure delta is never 0.
|
||||
# pyre-fixme[6]: Expected `Tensor` for 1st param but got `float`.
|
||||
delta = torch.exp((eps - z_inv_max) / blend_params.gamma).clamp(min=eps)
|
||||
|
||||
# Normalize weights.
|
||||
|
||||
@@ -65,10 +65,8 @@ def _opencv_from_cameras_projection(
|
||||
cameras: PerspectiveCameras,
|
||||
image_size: torch.Tensor,
|
||||
) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, memory_format:
|
||||
# Optional[memory_format] = ...) -> Tensor, Tensor, Module]` is not a function.
|
||||
R_pytorch3d = cameras.R.clone()
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, memory_format:
|
||||
# Optional[memory_format] = ...) -> Tensor, Tensor, Module]` is not a function.
|
||||
T_pytorch3d = cameras.T.clone()
|
||||
focal_pytorch3d = cameras.focal_length
|
||||
|
||||
@@ -230,9 +230,7 @@ class CamerasBase(TensorProperties):
|
||||
a Transform3d object which represents a batch of transforms
|
||||
of shape (N, 3, 3)
|
||||
"""
|
||||
# pyre-fixme[16]: `CamerasBase` has no attribute `R`.
|
||||
self.R: torch.Tensor = kwargs.get("R", self.R)
|
||||
# pyre-fixme[16]: `CamerasBase` has no attribute `T`.
|
||||
self.T: torch.Tensor = kwargs.get("T", self.T)
|
||||
world_to_view_transform = self.get_world_to_view_transform(R=self.R, T=self.T)
|
||||
view_to_proj_transform = self.get_projection_transform(**kwargs)
|
||||
@@ -409,9 +407,7 @@ class CamerasBase(TensorProperties):
|
||||
kwargs = {}
|
||||
|
||||
tensor_types = {
|
||||
# pyre-fixme[16]: Module `cuda` has no attribute `BoolTensor`.
|
||||
"bool": (torch.BoolTensor, torch.cuda.BoolTensor),
|
||||
# pyre-fixme[16]: Module `cuda` has no attribute `LongTensor`.
|
||||
"long": (torch.LongTensor, torch.cuda.LongTensor),
|
||||
}
|
||||
if not isinstance(
|
||||
@@ -429,14 +425,13 @@ class CamerasBase(TensorProperties):
|
||||
index = [index]
|
||||
|
||||
if isinstance(index, tensor_types["bool"]):
|
||||
# pyre-fixme[16]: Item `List` of `Union[List[int], BoolTensor,
|
||||
# LongTensor]` has no attribute `ndim`.
|
||||
# pyre-fixme[16]: Item `List` of `Union[List[int], BoolTensor,
|
||||
# LongTensor]` has no attribute `shape`.
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
if index.ndim != 1 or index.shape[0] != len(self):
|
||||
raise ValueError(
|
||||
# pyre-fixme[16]: Item `List` of `Union[List[int], BoolTensor,
|
||||
# LongTensor]` has no attribute `shape`.
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
f"Boolean index of shape {index.shape} does not match cameras"
|
||||
)
|
||||
elif max(index) >= len(self):
|
||||
@@ -1179,7 +1174,6 @@ class PerspectiveCameras(CamerasBase):
|
||||
|
||||
unprojection_transform = to_camera_transform.inverse()
|
||||
xy_inv_depth = torch.cat(
|
||||
# pyre-fixme[6]: For 1st argument expected `Union[List[Tensor],
|
||||
# tuple[Tensor, ...]]` but got `Tuple[Tensor, float]`.
|
||||
(xy_depth[..., :2], torch.reciprocal(xy_depth[..., 2:3])),
|
||||
dim=-1, # type: ignore
|
||||
@@ -1750,7 +1744,7 @@ def look_at_view_transform(
|
||||
elev, # pyrefly: ignore [bad-argument-type]
|
||||
azim, # pyrefly: ignore [bad-argument-type]
|
||||
degrees=degrees,
|
||||
device=device, # pyrefly: ignore [bad-argument-type]
|
||||
device=device,
|
||||
)
|
||||
+ at
|
||||
)
|
||||
@@ -1798,11 +1792,13 @@ def get_ndc_to_screen_transform(
|
||||
image_size = torch.tensor(image_size, device=cameras.device)
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
image_size = image_size.view(-1, 2) # of shape (1 or B)x2
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
height, width = image_size.unbind(1)
|
||||
|
||||
# For non square images, we scale the points such that smallest side
|
||||
# has range [-1, 1] and the largest side has range [-u, u], with u > 1.
|
||||
# This convention is consistent with the PyTorch3D renderer
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
scale = (image_size.min(dim=1).values - 0.0) / 2.0
|
||||
|
||||
K[:, 0, 0] = scale
|
||||
|
||||
@@ -183,7 +183,6 @@ class HarmonicEmbedding(torch.nn.Module):
|
||||
so the input might be xyz.
|
||||
"""
|
||||
return self.get_output_dim_static(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
input_dims,
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
len(self._frequencies),
|
||||
|
||||
@@ -236,7 +236,6 @@ class MultinomialRaysampler(torch.nn.Module):
|
||||
# is not batched and does not support partial permutation
|
||||
_, width, height, _ = xy_grid.shape
|
||||
weights = xy_grid.new_ones(batch_size, width * height)
|
||||
# pyre-fixme[6]: For 2nd param expected `int` but got `Union[bool,
|
||||
# float, int]`.
|
||||
rays_idx = _safe_multinomial(weights, n_rays_per_image)[..., None].expand(
|
||||
-1, -1, 2
|
||||
|
||||
@@ -170,7 +170,6 @@ class ImplicitRenderer(torch.nn.Module):
|
||||
# given sampled rays, call the volumetric function that
|
||||
# evaluates the densities and features at the locations of the
|
||||
# ray points
|
||||
# pyre-fixme[23]: Unable to unpack `object` into 2 values.
|
||||
rays_densities, rays_features = volumetric_function(
|
||||
ray_bundle=ray_bundle, cameras=cameras, **kwargs
|
||||
)
|
||||
|
||||
@@ -182,17 +182,38 @@ def _get_culled_faces(face_verts: torch.Tensor, frustum: ClipFrustum) -> torch.T
|
||||
faces_culled = torch.zeros(
|
||||
[face_verts.shape[0]], dtype=torch.bool, device=face_verts.device
|
||||
)
|
||||
if not frustum.cull:
|
||||
return faces_culled
|
||||
|
||||
# With a perspective camera the xy coordinates are in NDC space, where the
|
||||
# perspective divide mirrors vertices behind the camera through the origin.
|
||||
# A face with such a vertex can therefore have all 3 xy coordinates outside
|
||||
# the same plane while the part of it in front of the camera still crosses
|
||||
# the frustum, so only faces lying entirely in front of the clipping plane
|
||||
# may be culled on the x and y axes. The z axis uses world coordinates and
|
||||
# is unaffected.
|
||||
xy_cullable = None
|
||||
if frustum.perspective_correct:
|
||||
if frustum.z_clip_value is not None:
|
||||
verts_in_front = face_verts[:, :, 2] >= frustum.z_clip_value
|
||||
else:
|
||||
verts_in_front = face_verts[:, :, 2] > 0
|
||||
xy_cullable = verts_in_front.all(dim=1)
|
||||
|
||||
for plane in clipping_planes:
|
||||
clip_value, axis, op = plane
|
||||
# If clip_value is None then don't clip along that plane
|
||||
if frustum.cull and clip_value is not None:
|
||||
if clip_value is not None:
|
||||
if op == "<":
|
||||
verts_clipped = face_verts[:, axis] < clip_value
|
||||
verts_clipped = face_verts[:, :, axis] < clip_value
|
||||
else:
|
||||
verts_clipped = face_verts[:, axis] > clip_value
|
||||
verts_clipped = face_verts[:, :, axis] > clip_value
|
||||
|
||||
# If all verts are clipped then face is outside the frustum
|
||||
faces_culled |= verts_clipped.sum(1) == 3
|
||||
plane_culled = verts_clipped.all(dim=1)
|
||||
if axis != 2 and xy_cullable is not None:
|
||||
plane_culled &= xy_cullable
|
||||
faces_culled |= plane_culled
|
||||
|
||||
return faces_culled
|
||||
|
||||
@@ -496,7 +517,6 @@ def clip_faces(
|
||||
|
||||
# Solve for the points p4, p5 that intersect the clipping plane
|
||||
p, p_barycentric = _find_verts_intersecting_clipping_plane(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
faces_case3,
|
||||
p1_face_ind,
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
@@ -540,12 +560,10 @@ def clip_faces(
|
||||
faces_case4 = face_verts_unclipped[case4_unclipped_idx]
|
||||
|
||||
# index (0, 1, or 2) of the vertex behind the clipping plane
|
||||
# pyre-fixme[61]: `faces_clipped_verts` is undefined, or not always defined.
|
||||
p1_face_ind = torch.where(faces_clipped_verts[case4_unclipped_idx])[1]
|
||||
|
||||
# Solve for the points p4, p5 that intersect the clipping plane
|
||||
p, p_barycentric = _find_verts_intersecting_clipping_plane(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
faces_case4,
|
||||
p1_face_ind,
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
|
||||
@@ -453,7 +453,6 @@ class TexturesAtlas(TexturesBase):
|
||||
msg = "Expected atlas to be of shape (N, F, R, R, C); got %r"
|
||||
raise ValueError(msg % repr(atlas.ndim))
|
||||
self._atlas_padded = atlas
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._atlas_list = None
|
||||
self.device = atlas.device
|
||||
|
||||
@@ -537,7 +536,6 @@ class TexturesAtlas(TexturesBase):
|
||||
self._atlas_padded = [
|
||||
torch.empty((0, 0, 0, 3), dtype=torch.float32, device=self.device)
|
||||
] * self._N
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._atlas_list = _padded_to_list_wrapper(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
self._atlas_padded,
|
||||
@@ -803,7 +801,6 @@ class TexturesUV(TexturesBase):
|
||||
msg = "Expected faces_uvs to be of shape (N, F, 3); got %r"
|
||||
raise ValueError(msg % repr(faces_uvs.shape))
|
||||
self._faces_uvs_padded = faces_uvs
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._faces_uvs_list = None
|
||||
self.device = faces_uvs.device
|
||||
|
||||
@@ -840,7 +837,6 @@ class TexturesUV(TexturesBase):
|
||||
msg = "Expected verts_uvs to be of shape (N, V, 2); got %r"
|
||||
raise ValueError(msg % repr(verts_uvs.shape))
|
||||
self._verts_uvs_padded = verts_uvs
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._verts_uvs_list = None
|
||||
|
||||
if verts_uvs.device != self.device:
|
||||
@@ -853,7 +849,6 @@ class TexturesUV(TexturesBase):
|
||||
if isinstance(maps, (list, tuple)):
|
||||
self._maps_list = maps
|
||||
else:
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._maps_list = None
|
||||
self._maps_padded = self._format_maps_padded(maps)
|
||||
|
||||
@@ -1099,7 +1094,6 @@ class TexturesUV(TexturesBase):
|
||||
torch.empty((0, 3), dtype=torch.float32, device=self.device)
|
||||
] * self._N
|
||||
else:
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._faces_uvs_list = padded_to_list(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
self._faces_uvs_padded,
|
||||
@@ -1132,7 +1126,7 @@ class TexturesUV(TexturesBase):
|
||||
# The number of vertices in the mesh and in verts_uvs can differ
|
||||
# e.g. if a vertex is shared between 3 faces, it can
|
||||
# have up to 3 different uv coordinates.
|
||||
# pyrefly: ignore [bad-assignment, missing-attribute]
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
self._verts_uvs_list = list(self._verts_uvs_padded.unbind(0))
|
||||
# pyrefly: ignore [bad-return]
|
||||
return self._verts_uvs_list
|
||||
@@ -1755,7 +1749,6 @@ class TexturesVertex(TexturesBase):
|
||||
msg = "Expected verts_features to be of shape (N, V, C); got %r"
|
||||
raise ValueError(msg % repr(verts_features.shape))
|
||||
self._verts_features_padded = verts_features
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._verts_features_list = None
|
||||
self.device = verts_features.device
|
||||
|
||||
@@ -1832,7 +1825,6 @@ class TexturesVertex(TexturesBase):
|
||||
torch.empty((0, 3), dtype=torch.float32, device=self.device)
|
||||
] * self._N
|
||||
else:
|
||||
# pyrefly: ignore [bad-assignment]
|
||||
self._verts_features_list = padded_to_list(
|
||||
# pyrefly: ignore [bad-argument-type]
|
||||
self._verts_features_padded,
|
||||
|
||||
@@ -288,7 +288,6 @@ class _OpenGLMachinery:
|
||||
bary_coords = []
|
||||
zbufs = []
|
||||
|
||||
# pyre-ignore Incompatible parameter type [6]
|
||||
for mesh_id, mesh in enumerate(meshes_gl_ndc):
|
||||
pix_to_face, bary_coord, zbuf = self._rasterize_mesh(
|
||||
mesh,
|
||||
@@ -385,13 +384,11 @@ class _OpenGLMachinery:
|
||||
|
||||
# Free GL resources.
|
||||
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo)
|
||||
# pyre-fixme[16]: Module `GL_3_0` has no attribute `glDeleteFramebuffers`.
|
||||
gl.glDeleteFramebuffers(1, [self.fbo])
|
||||
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
|
||||
del self.fbo
|
||||
|
||||
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, self.mesh_buffer_object)
|
||||
# pyre-fixme[16]: Module `GL_1_5` has no attribute `glDeleteBuffers`.
|
||||
gl.glDeleteBuffers(1, [self.mesh_buffer_object])
|
||||
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, 0)
|
||||
del self.mesh_buffer_object
|
||||
@@ -408,7 +405,6 @@ class _OpenGLMachinery:
|
||||
projection matrix: A 3x3 float tensor.
|
||||
"""
|
||||
gl.glUseProgram(self.program)
|
||||
# pyre-fixme[16]: Module `GL_2_0` has no attribute `glUniformMatrix4fv`.
|
||||
gl.glUniformMatrix4fv(
|
||||
self.perspective_projection_uniform,
|
||||
1,
|
||||
|
||||
@@ -471,7 +471,6 @@ class Meshes:
|
||||
):
|
||||
raise ValueError("Vertex normals tensor has incorrect dimensions.")
|
||||
self._verts_normals_packed = struct_utils.padded_to_packed(
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
verts_normals,
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
split_size=self._num_verts_per_mesh.tolist(),
|
||||
@@ -511,7 +510,9 @@ class Meshes:
|
||||
index = index.squeeze(1) if index.numel() > 0 else index
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
index = index.tolist()
|
||||
# pyrefly: ignore [not-iterable]
|
||||
verts = [self.verts_list()[i] for i in index]
|
||||
# pyrefly: ignore [not-iterable]
|
||||
faces = [self.faces_list()[i] for i in index]
|
||||
else:
|
||||
raise IndexError(index)
|
||||
|
||||
@@ -411,10 +411,13 @@ class Pointclouds:
|
||||
index = index.squeeze(1) if index.numel() > 0 else index
|
||||
# pyrefly: ignore [missing-attribute]
|
||||
index = index.tolist()
|
||||
# pyrefly: ignore [not-iterable]
|
||||
points = [self.points_list()[i] for i in index]
|
||||
if normals_list is not None:
|
||||
# pyrefly: ignore [not-iterable]
|
||||
normals = [normals_list[i] for i in index]
|
||||
if features_list is not None:
|
||||
# pyrefly: ignore [not-iterable]
|
||||
features = [features_list[i] for i in index]
|
||||
else:
|
||||
raise IndexError(index)
|
||||
|
||||
@@ -61,7 +61,6 @@ def _is_heterogeneous_ray_bundle(struct: Union[List[Struct], Struct]) -> bool:
|
||||
True if something is a HeterogeneousRayBundle or ImplicitronRayBundle
|
||||
and cant be reduced to RayBundle else False
|
||||
"""
|
||||
# pyre-ignore[16]
|
||||
return hasattr(struct, "camera_counts") and struct.camera_counts is not None
|
||||
|
||||
|
||||
@@ -586,15 +585,11 @@ def _add_struct_from_batch(
|
||||
if isinstance(batched_struct, CamerasBase):
|
||||
# we can't index directly into camera batches
|
||||
R, T = batched_struct.R, batched_struct.T
|
||||
# pyre-fixme[6]: For 1st argument expected
|
||||
# `pyre_extensions.PyreReadOnly[Sized]` but got `Union[Tensor, Module]`.
|
||||
r_idx = min(scene_num, len(R) - 1)
|
||||
# pyre-fixme[6]: For 1st argument expected
|
||||
# `pyre_extensions.PyreReadOnly[Sized]` but got `Union[Tensor, Module]`.
|
||||
t_idx = min(scene_num, len(T) - 1)
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[Any, A...
|
||||
R = R[r_idx].unsqueeze(0)
|
||||
# pyre-fixme[29]: `Union[(self: TensorBase, indices: Union[None, slice[Any, A...
|
||||
T = T[t_idx].unsqueeze(0)
|
||||
struct = CamerasBase(device=batched_struct.device, R=R, T=T)
|
||||
elif _is_ray_bundle(batched_struct) and not _is_heterogeneous_ray_bundle(
|
||||
@@ -616,7 +611,6 @@ def _add_struct_from_batch(
|
||||
struct = RayBundle(
|
||||
**{
|
||||
attr: getattr(batched_struct, attr)[
|
||||
# pyre-ignore[16]
|
||||
first_idxs[struct_idx] : first_idxs[struct_idx + 1]
|
||||
]
|
||||
for attr in ["origins", "directions", "lengths", "xys"]
|
||||
|
||||
@@ -59,7 +59,6 @@ def texturesuv_image_matplotlib(
|
||||
for i in indices:
|
||||
# setting clip_on=False makes it obvious when
|
||||
# we have UV coordinates outside the correct range
|
||||
# pyre-fixme[6]: For 1st argument expected `Tuple[float, float]` but got
|
||||
# `ndarray[Any, Any]`.
|
||||
ax.add_patch(Circle(centers[i], radius, color=color, clip_on=False))
|
||||
|
||||
|
||||
@@ -955,6 +955,60 @@ class TestMeshObjIO(TestCaseMixin, unittest.TestCase):
|
||||
with open(obj_file, "r") as actual_file:
|
||||
self.assertEqual(actual_file.read(), expected_obj_file)
|
||||
|
||||
def test_save_obj_with_uvs_without_texture_map(self):
|
||||
verts = torch.tensor(
|
||||
[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0]],
|
||||
dtype=torch.float32,
|
||||
)
|
||||
faces = torch.tensor([[0, 2, 1]], dtype=torch.int64)
|
||||
verts_uvs = torch.tensor(
|
||||
[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]],
|
||||
dtype=torch.float32,
|
||||
)
|
||||
faces_uvs = torch.tensor([[3, 1, 2]], dtype=torch.int64)
|
||||
normals = torch.tensor([[0.0, 0.0, 1.0], [0.0, 1.0, 0.0]])
|
||||
faces_normals_idx = torch.tensor([[1, 0, 1]], dtype=torch.int64)
|
||||
|
||||
for save_normals in (False, True):
|
||||
with (
|
||||
self.subTest(save_normals=save_normals),
|
||||
TemporaryDirectory() as temp_dir,
|
||||
):
|
||||
obj_file = Path(temp_dir) / "mesh.obj"
|
||||
save_obj(
|
||||
obj_file,
|
||||
verts,
|
||||
faces,
|
||||
verts_uvs=verts_uvs,
|
||||
faces_uvs=faces_uvs,
|
||||
normals=normals if save_normals else None,
|
||||
faces_normals_idx=faces_normals_idx if save_normals else None,
|
||||
)
|
||||
|
||||
self.assertEqual(os.listdir(temp_dir), ["mesh.obj"])
|
||||
obj_text = obj_file.read_text()
|
||||
self.assertNotIn("mtllib", obj_text)
|
||||
self.assertNotIn("usemtl", obj_text)
|
||||
expected_face = (
|
||||
"f 1/4/2 3/2/1 2/3/2" if save_normals else "f 1/4 3/2 2/3"
|
||||
)
|
||||
self.assertIn(expected_face, obj_text)
|
||||
|
||||
loaded_verts, loaded_faces, aux = load_obj(
|
||||
obj_file, load_textures=False
|
||||
)
|
||||
self.assertClose(loaded_verts, verts)
|
||||
self.assertClose(loaded_faces.verts_idx, faces)
|
||||
self.assertClose(aux.verts_uvs, verts_uvs)
|
||||
self.assertClose(loaded_faces.textures_idx, faces_uvs)
|
||||
self.assertIsNone(aux.material_colors)
|
||||
self.assertIsNone(aux.texture_images)
|
||||
if save_normals:
|
||||
self.assertClose(aux.normals, normals)
|
||||
self.assertClose(loaded_faces.normals_idx, faces_normals_idx)
|
||||
else:
|
||||
self.assertIsNone(aux.normals)
|
||||
|
||||
def test_save_obj_with_texture(self):
|
||||
verts = torch.tensor(
|
||||
[[0.01, 0.2, 0.301], [0.2, 0.03, 0.408], [0.3, 0.4, 0.05], [0.6, 0.7, 0.8]],
|
||||
|
||||
@@ -159,6 +159,38 @@ class TestICP(TestCaseMixin, unittest.TestCase):
|
||||
self.assertClose(s_init, s, atol=atol)
|
||||
self.assertClose(Xt_init, Xt, atol=atol)
|
||||
|
||||
@staticmethod
|
||||
def _init_heterogeneous_icp_problem(batch_size, max_n_points, device):
|
||||
"""
|
||||
Generate a batch of randomly-sized point clouds `X` together with
|
||||
`Y`, a rigidly moved copy of each cloud with a few extra points
|
||||
added, so that the clouds in `Y` have different sizes from those
|
||||
in `X`.
|
||||
|
||||
`Y` deliberately covers the whole of `X`. Two independent random
|
||||
clouds instead make the problem ill-posed: with `estimate_scale`,
|
||||
ICP then usually collapses `X` onto a single point of `Y`, driving
|
||||
the scale to ~1e-16 and the rmse to zero. That solution fits
|
||||
perfectly but leaves the rotation completely unconstrained, so two
|
||||
runs of the same algorithm may return wildly different rotations
|
||||
and can't be compared with each other.
|
||||
"""
|
||||
n_points = torch.randint(
|
||||
low=6, high=max_n_points, size=(batch_size,), device=device
|
||||
)
|
||||
X_list = [torch.randn(int(n), 3, device=device) for n in n_points]
|
||||
R = rotation_conversions.axis_angle_to_matrix(
|
||||
0.15 * torch.randn(batch_size, 3, device=device)
|
||||
)
|
||||
T = 0.1 * torch.randn(batch_size, 3, device=device)
|
||||
Y_list = []
|
||||
for i, X in enumerate(X_list):
|
||||
n_extra = int(torch.randint(low=1, high=5, size=(), device=device))
|
||||
covered = torch.cat([X, torch.randn(n_extra, 3, device=device)], dim=0)
|
||||
Y_list.append(covered @ R[i] + T[i] + 0.01 * torch.randn_like(covered))
|
||||
|
||||
return Pointclouds(X_list), Pointclouds(Y_list)
|
||||
|
||||
def test_heterogeneous_inputs(self, batch_size=7):
|
||||
"""
|
||||
Tests whether we get the same result when running ICP on
|
||||
@@ -171,17 +203,9 @@ class TestICP(TestCaseMixin, unittest.TestCase):
|
||||
for estimate_scale in (True, False):
|
||||
for max_n_points in (10, 30, 100):
|
||||
# initialize ground truth point clouds
|
||||
X_pcl, Y_pcl = [
|
||||
TestCorrespondingPointsAlignment.init_point_cloud(
|
||||
batch_size=batch_size,
|
||||
n_points=max_n_points,
|
||||
dim=3,
|
||||
device=device,
|
||||
use_pointclouds=True,
|
||||
random_pcl_size=True,
|
||||
)
|
||||
for _ in range(2)
|
||||
]
|
||||
X_pcl, Y_pcl = self._init_heterogeneous_icp_problem(
|
||||
batch_size, max_n_points, device
|
||||
)
|
||||
|
||||
# get the padded versions and their num of points
|
||||
X_padded = X_pcl.points_padded()
|
||||
@@ -227,8 +251,11 @@ class TestICP(TestCaseMixin, unittest.TestCase):
|
||||
torch.cat([x.RTs[i] for x in icp_results], dim=0) for i in range(3)
|
||||
]
|
||||
|
||||
# check that both sets of transforms are the same
|
||||
atol = 1e-5
|
||||
# check that both sets of transforms are the same.
|
||||
# The two runs sum over a different number of points - the
|
||||
# batched one includes the (zero-weighted) padding - so they
|
||||
# round differently, by up to ~1e-5 on the transformed clouds.
|
||||
atol = 1e-4
|
||||
self.assertClose(R_pcl, R, atol=atol)
|
||||
self.assertClose(T_pcl, T, atol=atol)
|
||||
self.assertClose(s_pcl, s, atol=atol)
|
||||
|
||||
@@ -31,6 +31,7 @@ from pytorch3d.renderer.mesh import (
|
||||
convert_clipped_rasterization_to_original_faces,
|
||||
TexturesUV,
|
||||
)
|
||||
from pytorch3d.renderer.mesh.clip import _get_culled_faces
|
||||
from pytorch3d.renderer.mesh.rasterize_meshes import _RasterizeFaceVerts
|
||||
from pytorch3d.renderer.mesh.rasterizer import MeshRasterizer, RasterizationSettings
|
||||
from pytorch3d.renderer.mesh.renderer import MeshRenderer
|
||||
@@ -194,6 +195,77 @@ class TestRenderMeshesClipping(TestCaseMixin, unittest.TestCase):
|
||||
)
|
||||
return clipped_faces
|
||||
|
||||
def test_cull_faces_uses_coordinate_axis(self):
|
||||
"""
|
||||
A face is culled when all 3 of its vertices are outside the same
|
||||
clipping plane, not when one vertex is outside it on all 3 axes.
|
||||
"""
|
||||
planes_and_faces = (
|
||||
({"left": -1.0}, [-2.0, 0.0, 1.0]),
|
||||
({"right": 1.0}, [2.0, 0.0, 1.0]),
|
||||
({"top": -1.0}, [0.0, -2.0, 1.0]),
|
||||
({"bottom": 1.0}, [0.0, 2.0, 1.0]),
|
||||
({"znear": 0.0}, [0.0, 0.0, -1.0]),
|
||||
({"zfar": 2.0}, [0.0, 0.0, 3.0]),
|
||||
)
|
||||
for frustum_kwargs, vertex in planes_and_faces:
|
||||
with self.subTest(frustum_kwargs=frustum_kwargs):
|
||||
face_verts = torch.tensor([[vertex, vertex, vertex]])
|
||||
faces_culled = _get_culled_faces(
|
||||
face_verts, ClipFrustum(**frustum_kwargs)
|
||||
)
|
||||
self.assertTrue(faces_culled.item())
|
||||
|
||||
# A face intersecting the left plane must remain visible regardless of
|
||||
# which of its vertices is first in the face.
|
||||
face_verts = torch.tensor(
|
||||
[[[-2.0, -2.0, -2.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]]
|
||||
)
|
||||
for order in ([0, 1, 2], [1, 2, 0], [2, 0, 1]):
|
||||
with self.subTest(order=order):
|
||||
faces_culled = _get_culled_faces(
|
||||
face_verts[:, order], ClipFrustum(left=-1.0)
|
||||
)
|
||||
self.assertFalse(faces_culled.item())
|
||||
|
||||
def test_cull_faces_straddling_perspective_camera(self):
|
||||
"""
|
||||
The perspective divide mirrors vertices behind the camera through the
|
||||
origin, so a face straddling the camera plane can have all 3 of its
|
||||
projected vertices outside the same plane while the part of it in front
|
||||
of the camera still crosses the frustum. Such faces must not be culled
|
||||
on the x and y axes.
|
||||
"""
|
||||
# xy are in NDC and z is in world coordinates. Only the first vertex is
|
||||
# in front of the camera, and the edges joining it to the other two
|
||||
# cross the frustum before reaching z = 0.
|
||||
straddling = torch.tensor(
|
||||
[[[-1.1, 0.0, 1.0], [-100.0, 0.0, -1.0], [-100.0, 0.1, -1.0]]]
|
||||
)
|
||||
# The same projected face with every vertex in front of the camera is
|
||||
# genuinely outside the left plane.
|
||||
in_front = straddling.clone()
|
||||
in_front[:, :, 2] = 1.0
|
||||
|
||||
for frustum_kwargs in ({}, {"z_clip_value": 1e-2}):
|
||||
with self.subTest(frustum_kwargs=frustum_kwargs):
|
||||
frustum = ClipFrustum(
|
||||
left=-1.0, perspective_correct=True, **frustum_kwargs
|
||||
)
|
||||
self.assertFalse(_get_culled_faces(straddling, frustum).item())
|
||||
self.assertTrue(_get_culled_faces(in_front, frustum).item())
|
||||
|
||||
# An orthographic projection leaves the xy coordinates of vertices
|
||||
# behind the camera usable, so there the face is culled.
|
||||
frustum = ClipFrustum(left=-1.0, perspective_correct=False)
|
||||
self.assertTrue(_get_culled_faces(straddling, frustum).item())
|
||||
|
||||
# Culling on the z axis uses world coordinates and is unaffected.
|
||||
behind = straddling.clone()
|
||||
behind[:, :, 2] = -1.0
|
||||
frustum = ClipFrustum(znear=0.0, perspective_correct=True)
|
||||
self.assertTrue(_get_culled_faces(behind, frustum).item())
|
||||
|
||||
def test_grad(self):
|
||||
"""
|
||||
Check that gradient flow is unaffected when the camera is inside the mesh
|
||||
|
||||
@@ -66,6 +66,51 @@ class TestSymEig3x3(TestCaseMixin, unittest.TestCase):
|
||||
rtol=rtol,
|
||||
)
|
||||
|
||||
def test_is_eigen_scaled_gpu(self):
|
||||
self._test_is_eigen_scaled(self._gpu)
|
||||
|
||||
def test_is_eigen_scaled_cpu(self):
|
||||
self._test_is_eigen_scaled(self._cpu)
|
||||
|
||||
def _test_is_eigen_scaled(self, device):
|
||||
"""
|
||||
The decomposition is homogeneous, so scaling the input must not affect
|
||||
the relative accuracy of the result.
|
||||
"""
|
||||
test_input = self.create_random_sym3x3(device, n=self.TEST_BATCH_SIZE)
|
||||
|
||||
for scale in (1e-6, 1e-4, 1e-2, 1e2, 1e4, 1e6):
|
||||
scaled_input = test_input * scale
|
||||
|
||||
self._test_is_not_nan_or_inf(scaled_input)
|
||||
self._test_is_eigen(scaled_input, atol=1e-04 * scale, rtol=1e-02)
|
||||
self._test_eigenvectors_are_orthonormal(scaled_input)
|
||||
|
||||
def test_mixed_magnitudes_gpu(self):
|
||||
self._test_mixed_magnitudes(self._gpu)
|
||||
|
||||
def test_mixed_magnitudes_cpu(self):
|
||||
self._test_mixed_magnitudes(self._cpu)
|
||||
|
||||
def _test_mixed_magnitudes(self, device):
|
||||
"""
|
||||
Each matrix in a batch must be conditioned on its own magnitude, so
|
||||
matrices spanning many orders of magnitude can be batched together.
|
||||
"""
|
||||
test_input = self.create_random_sym3x3(device, n=self.TEST_BATCH_SIZE)
|
||||
scales = torch.logspace(-6, 6, self.TEST_BATCH_SIZE, device=device)[
|
||||
:, None, None
|
||||
]
|
||||
scaled_input = test_input * scales
|
||||
|
||||
eigenvalues, eigenvectors = symeig3x3(scaled_input, eigenvectors=True)
|
||||
reconstruction = (
|
||||
eigenvectors @ eigenvalues.diag_embed() @ eigenvectors.transpose(-2, -1)
|
||||
)
|
||||
|
||||
self.assertClose(test_input, reconstruction / scales, atol=1e-04, rtol=1e-02)
|
||||
self._test_eigenvectors_are_orthonormal(scaled_input)
|
||||
|
||||
def test_eigenvectors_are_orthonormal_gpu(self):
|
||||
test_input = self.create_random_sym3x3(self._gpu, n=self.TEST_BATCH_SIZE)
|
||||
|
||||
@@ -192,21 +237,31 @@ class TestSymEig3x3(TestCaseMixin, unittest.TestCase):
|
||||
def test_degenerate_eigenvalues_cpu(self):
|
||||
self._test_degenerate_eigenvalues(self._cpu)
|
||||
|
||||
def _test_degenerate_eigenvalues(self, device):
|
||||
def test_degenerate_eigenvalues_scaled_gpu(self):
|
||||
for scale in (1e-6, 1e6):
|
||||
self._test_degenerate_eigenvalues(self._gpu, scale=scale)
|
||||
|
||||
def test_degenerate_eigenvalues_scaled_cpu(self):
|
||||
for scale in (1e-6, 1e6):
|
||||
self._test_degenerate_eigenvalues(self._cpu, scale=scale)
|
||||
|
||||
def _test_degenerate_eigenvalues(self, device, scale: float = 1.0):
|
||||
"""
|
||||
Test degenerate eigenvalues like zero-valued and with 2-/3-multiplicity
|
||||
Test degenerate eigenvalues like zero-valued and with 2-/3-multiplicity.
|
||||
These are the cases held together by the regularizers inside the
|
||||
decomposition, which only bite at the right input magnitude.
|
||||
"""
|
||||
# Error tolerances for degenerate values are increased as things might become
|
||||
# numerically unstable
|
||||
deg_atol = 1e-3
|
||||
deg_atol = 1e-3 * scale
|
||||
deg_rtol = 1.0
|
||||
|
||||
# Construct random orthonormal sets
|
||||
test_eigenvecs = random_rotations(n=self.TEST_BATCH_SIZE, device=device)
|
||||
|
||||
# Construct random eigenvalues
|
||||
test_eigenvals = torch.randn(
|
||||
(self.TEST_BATCH_SIZE, 3), device=test_eigenvecs.device
|
||||
test_eigenvals = (
|
||||
torch.randn((self.TEST_BATCH_SIZE, 3), device=test_eigenvecs.device) * scale
|
||||
)
|
||||
self._test_eigenvalues_and_eigenvectors(
|
||||
test_eigenvecs, test_eigenvals, atol=deg_atol, rtol=deg_rtol
|
||||
|
||||
Reference in New Issue
Block a user