mirror of
https://github.com/nerfstudio-project/nerfstudio.git
synced 2026-11-11 18:44:21 +08:00
* testing; need to merge * fixing wrong base file in models/base * pushed input parser into datasets class to abstract away fetching data in dataloader * slight name chage and all * nits * added dataparser * added licnese
14 KiB
14 KiB
In [1]:
# COLLAPSED
%load_ext autoreload
%autoreload 2
from __future__ import annotations
from typing import Dict, Optional, Tuple, List
import torch
from nerfactory.utils.config import DataManagerConfig, ModelConfig, PipelineConfig, ViewerConfig
from nerfactory.datamanagers.base import DataManager
from nerfactory.datamanagers.structs import DatasetInputs
from nerfactory.models.base import Model
from nerfactory.pipelines.base import Pipeline
from nerfactory.models.instant_ngp import NGPModel
from nerfactory.cameras.rays import RayBundleIn [ ]:
class CustomDataManagerConfig(DataManagerConfig):
_target = "CustomDataManager"
scene_names: List[str] = ["chair", "drums", "fern", "lego"]
steps_per_add_cameras: int = 100 # every X iterations, add more cameras
num_cameras_per_add: int = 10 # number of cameras to add
class CustomDataManager(DataManager):
"""A custom dataloader that incrementally adds cameras and has multiple scenes."""
config: CustomDataManagerConfig
def populate_train_modules(self):
"""Populate the train dataloader modules."""
self.scene_name_to_image_sampler = {}
self.scene_name_to_collider = {} # TODO(ethan): move colliders to the dataloader
for scene_name in self.config.scene_names:
dataset_inputs: DatasetInputs = None # TODO
image_dataset = ImageDataset(dataset_inputs)
image_sampler = CacheImageDataloader(image_dataset=image_dataset) # a torch dataloader
self.scene_name_to_image_sampler[scene_name] = image_sampler
self.train_pixel_sampler = PixelSampler
self.train_ray_generator = RayGenerator # nn.Module
def populate_eval_modules(self):
"""Populate the eval dataloader modules."""
# we'll mostly rely on the train dataloader modules
self.eval_pixel_sampler = EvalPixelSampler # this will sample entire images
def sample_images(self) -> List[Image]:
images = []
for scene_name in self.scene_name_to_image_sampler.keys():
image_sampler = self.scene_name_to_image_sampler[scene_name]
x = image_sampler.forward() # note that empty forward calls next()
images.append(x)
return images
def next_train(self, step: int) -> Tuple[RayBundle, Dict]:
"""Get the next batch of training data by stringing together the train modules."""
# grab some images from each scene
images = self.sample_images()
pixels = self.train_pixel_sampler.forward(images)
ray_bundle = self.train_ray_generator(pixels)
# shape should be (H, W, :)
ray_bundle.metadata["scene_indices"] = None # TODO(ethan): populate this with a tensor of scene indices
dict_ = {}
return ray_bundle, dict_
def next_eval(self, step: int) -> Tuple[RayBundle, Dict]:
"""Get the next batch of eval data by stringing together the eval modules."""
# grab some images from each scene
images = self.sample_images()
pixels = self.train_pixel_sampler.forward(images)
ray_bundle = self.eval_ray_generator(pixels) # notice this is eval and not train
# shape should be (H, W, :)
ray_bundle.metadata["scene_indices"] = None # TODO(ethan): populate this with a tensor of scene indices
dict_ = {}
return ray_bundle, dict_
class CustomNGPModelConfig(ModelConfig):
_target = "CustomNGPModel"
coarse_field: str = "temp"
fine_field: str = "temp2"
class CustomNGPModel(Model):
"""An instant ngp model modified slightly to output semantics."""
config: SceneConditionNGPModelConfig
def populate_modules(self):
self.ngp_model = NGPModel(coarse_field=self.config.coarse_field, fine_field=self.config.fine_field)
def get_outputs(self, ray_bundle: RayBundle) -> Dict[str, torch.Tensor]:
# TODO(ethan): pass in batch from the forward function
# TODO(ethan): rename batch to something else
outputs = self.ngp_model.forward(ray_bundle)
outputs["semantics"] = torch.rand_like(outputs["rgb"])
return outputs
def get_loss_dict(self):
return {}
class CustomPipeline(Pipeline):
"""The Instant NGP pipeline."""
config: PipelineConfig
def train_step(self, step: int):
ray_bundle, batch = self.dataloader.next_train(step=step)
# TODO: maybe run a CNN on the data before passing into model
model_outputs, loss_dict, metrics_dict = self.model(ray_bundle, batch)
# TODO: update pixel sampler state with loss map to show the flexibilty of our Pipeline
self.dataloader.pixel_sampler.update_loss_map()
return model_outputs, loss_dict, metrics_dict
def eval_step(self):
ray_bundle, batch = self.dataloader.next_eval(step=step)In [ ]:
dataloader = DataManager()
model = SceneConditionNGPModel()
pipeline = CustomPipeline.from_dataloader_and_model(dataloader=dataloader, model=model)In [ ]:
import pprint
import hydra
hydra.core.global_hydra.GlobalHydra.instance().clear()
from hydra import compose, initialize
initialize(version_base="1.2", config_path="../configs/")
config_name = "graph_instant_ngp.yaml"
config = compose(config_name)
pipeline_config = config.pipeline
pprint.pprint(pipeline_config)
print("----------------------------------------------------")
# from nerfactory.pipelines.base import setup_pipeline
# pipeline = setup_pipeline(pipeline_config, device="cuda")
pipeline = pipeline_config.setup()In [ ]:
pipeline.get_train_loss_dict()In [ ]: