Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement lgm #1621

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ If you would like to try on your computer:
|:-----------|------------:|:------------:|:------------:|:------------:|:------------:|
| [<img src="neural_rendering/nerf/output.png" width=128px>](neural_rendering/nerf/) | [nerf](/neural_rendering/nerf/) | [NeRF: Neural Radiance Fields](https://github.com/bmild/nerf) | Tensorflow | 1.2.10 and later | [EN](https://medium.com/axinc-ai/nerf-machine-learning-model-to-generate-and-render-3d-models-from-multiple-viewpoint-images-599631dc2075) [JP](https://medium.com/axinc/nerf-%E8%A4%87%E6%95%B0%E3%81%AE%E8%A6%96%E7%82%B9%E3%81%AE%E7%94%BB%E5%83%8F%E3%81%8B%E3%82%893d%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E7%94%9F%E6%88%90%E3%81%97%E3%81%A6%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%83%A2%E3%83%87%E3%83%AB-2d6bee7ff22f) |
| [<img src="neural_rendering/tripo_sr/render.gif" width=128px>](neural_rendering/tripo_sr/) | [TripoSR](/neural_rendering/tripo_sr/) | [TripoSR](https://github.com/VAST-AI-Research/TripoSR) | Pytorch | 1.2.6 and later |
| [<img src="neural_rendering/lgm/output.gif" width=128px>](neural_rendering/lgm/) | [LGM](/neural_rendering/lgm/) | [LGM](https://github.com/3DTopia/LGM) | Pytorch | 1.5.0 and later |

## NSFW detector

Expand Down
21 changes: 21 additions & 0 deletions neural_rendering/lgm/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 3D Topia

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
71 changes: 71 additions & 0 deletions neural_rendering/lgm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# LGM

## Image-to-3D
### Input
![Input](catstatue_rgba.png)

(Image from https://github.com/3DTopia/LGM/blob/main/data_test/catstatue_rgba.png)

### Output
![Output](output.gif)

## Text-to-3D
### Input
Prompt:
```
a hamburger
```

### Output
![Output](hamburger.gif)

## Install
This model requires C++ Compiler.
```
pip3 install -r requirements.txt

git clone https://github.com/MrSecant/diff-gaussian-rasterization.git c-diff-gaussian-rasterization
pip install -e ./c-diff-gaussian-rasterization
```

## Usage
Automatically downloads the onnx and prototxt files on the first run.
It is necessary to be connected to the Internet while downloading.

For the sample image,
``` bash
$ python3 lgm.py
```

If you want to specify the input image, put the image path after the `--input` option.
You can use `--savepath` option to change the name of the output file to save.
```bash
$ python3 lgm.py --input IMAGE_PATH --savepath SAVE_IMAGE_PATH
```

For Text-to-3D, specify the input prompt after the `--prompt` option.
``` bash
$ python3 lgm.py --prompt "a hamburger"
```

## Reference

- [LGM](https://github.com/3DTopia/LGM)

## Framework

Pytorch

## Model Format

ONNX opset=17

## Netron

[unet_image.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/unet_image.onnx.prototxt)
[unet_text.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/unet_text.onnx.prototxt)
[vae_encoder.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/vae_encoder.onnx.prototxt)
[vae_decoder.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/vae_decoder.onnx.prototxt)
[text_encoder.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/text_encoder.onnx.prototxt)
[image_encoder.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/image_encoder.onnx.prototxt)
[lgm.onnx.prototxt](https://netron.app/?url=https://storage.googleapis.com/ailia-models/lgm/lgm.onnx.prototxt)
Binary file added neural_rendering/lgm/catstatue_rgba.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
144 changes: 144 additions & 0 deletions neural_rendering/lgm/df/configuration_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# coding=utf-8
# Copyright 2023 The HuggingFace Inc. team.
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

""" ConfigMixin base class and utilities."""

import functools
import inspect

from collections import OrderedDict
from typing import Any, Dict


class FrozenDict(OrderedDict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

for key, value in self.items():
setattr(self, key, value)

self.__frozen = True


class ConfigMixin:
def register_to_config(self, **kwargs):
if not hasattr(self, "_internal_dict"):
internal_dict = kwargs
else:
internal_dict = {**self._internal_dict, **kwargs}

self._internal_dict = FrozenDict(internal_dict)

@classmethod
def from_config(cls, config_dict, **kwargs):
init_dict, _, hidden_dict = cls.extract_init_dict(config_dict, **kwargs)

# Return model and optionally state and/or unused_kwargs
model = cls(**init_dict)

# make sure to also save config parameters that might be used for compatible classes
model.register_to_config(**hidden_dict)

return model

@staticmethod
def _get_init_keys(cls):
return set(dict(inspect.signature(cls.__init__).parameters).keys())

@classmethod
def extract_init_dict(cls, config_dict, **kwargs):
# 0. Copy origin config dict
original_dict = dict(config_dict.items())

# 1. Retrieve expected config attributes from __init__ signature
expected_keys = cls._get_init_keys(cls)
expected_keys.remove("self")

# remove private attributes
config_dict = {k: v for k, v in config_dict.items() if not k.startswith("_")}

# 3. Create keyword arguments that will be passed to __init__ from expected keyword arguments
init_dict = {}
for key in expected_keys:
# if config param is passed to kwarg and is present in config dict
# it should overwrite existing config dict key
if key in kwargs and key in config_dict:
config_dict[key] = kwargs.pop(key)

if key in kwargs:
# overwrite key
init_dict[key] = kwargs.pop(key)
elif key in config_dict:
# use value from config dict
init_dict[key] = config_dict.pop(key)

# 6. Define unused keyword arguments
unused_kwargs = {**config_dict, **kwargs}

# 7. Define "hidden" config parameters that were saved for compatible classes
hidden_config_dict = {k: v for k, v in original_dict.items() if k not in init_dict}

return init_dict, unused_kwargs, hidden_config_dict

@property
def config(self) -> Dict[str, Any]:
"""
Returns the config of the class as a frozen dictionary

Returns:
`Dict[str, Any]`: Config of the class.
"""
return self._internal_dict


def register_to_config(init):
r"""
Decorator to apply on the init of classes inheriting from [`ConfigMixin`] so that all the arguments are
automatically sent to `self.register_for_config`. To ignore a specific argument accepted by the init but that
shouldn't be registered in the config, use the `ignore_for_config` class variable

Warning: Once decorated, all private arguments (beginning with an underscore) are trashed and not sent to the init!
"""

@functools.wraps(init)
def inner_init(self, *args, **kwargs):
# Ignore private kwargs in the init.
init_kwargs = {k: v for k, v in kwargs.items() if not k.startswith("_")}
config_init_kwargs = {k: v for k, v in kwargs.items() if k.startswith("_")}

# Get positional arguments aligned with kwargs
new_kwargs = {}
signature = inspect.signature(init)
parameters = {
name: p.default for i, (name, p) in enumerate(signature.parameters.items()) if i > 0
}
for arg, name in zip(args, parameters.keys()):
new_kwargs[name] = arg

# Then add all kwargs
new_kwargs.update(
{
k: init_kwargs.get(k, default)
for k, default in parameters.items()
if k not in new_kwargs
}
)

new_kwargs = {**config_init_kwargs, **new_kwargs}
getattr(self, "register_to_config")(**new_kwargs)
init(self, *args, **init_kwargs)

return inner_init
Empty file.
Loading