Skip to content

Commit 0c9ef1d

Browse files
authored
Merge branch 'main' into bugfix-display-icon
2 parents 5dcc1ad + 4f134e5 commit 0c9ef1d

3 files changed

Lines changed: 52 additions & 13 deletions

File tree

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@ A set of tools to visualize and interact with sequences of 3D data with cross-pl
88
## Installation
99
Basic Installation:
1010
```commandline
11-
pip install aitviewer
11+
uv pip install aitviewer
1212
```
13+
or drop the `uv` if you do not use it.
14+
1315
Note that this does not install the GPU-version of PyTorch automatically. If your environment already contains it, you should be good to go, otherwise install it manually.
1416

15-
Or install locally (if you need to extend or modify code)
17+
This installs PyQt6. If you require PyQt5, install via
18+
19+
```commandline
20+
uv pip install aitviewer[pyqt5]
21+
```
22+
23+
If you need to extend or modify the code, install from source via
1624
```commandline
1725
git clone git@github.com:eth-ait/aitviewer.git
1826
cd aitviewer
1927
pip install -e .
2028
```
2129

22-
On macOS with Apple Silicon it is recommended to use PyQt6. Please check [this issue](https://github.com/eth-ait/aitviewer/issues/22) for installation instructions.
23-
2430
For more advanced installation and for installing SMPL body models, please refer to the [documentation](https://eth-ait.github.io/aitviewer/parametric_human_models/supported_models.html) .
2531

2632
## Features
@@ -41,18 +47,19 @@ For more advanced installation and for installing SMPL body models, please refer
4147

4248

4349
## Quickstart
44-
Display an SMPL T-pose (Requires SMPL models):
50+
Display an SMPL-X T-pose (Requires SMPL models to be installed):
4551
```py
52+
from aitviewer.models.smpl import SMPLLayer
4653
from aitviewer.renderables.smpl import SMPLSequence
4754
from aitviewer.viewer import Viewer
4855

49-
if __name__ == '__main__':
56+
if __name__ == "__main__":
5057
v = Viewer()
51-
v.scene.add(SMPLSequence.t_pose())
58+
smpl_layer = SMPLLayer(model_type="smplx", gender="neutral")
59+
v.scene.add(SMPLSequence.reference_pose(smpl_layer))
5260
v.run()
5361
```
5462

55-
5663
## Projects using the aitviewer
5764
A sampling of projects using the aitviewer. Let us know if you want to be added to this list!
5865
- Fan et al., [HOLD: Category-agnostic 3D Reconstruction of Interacting Hands and Objects from Video](https://github.com/zc-alexfan/hold), CVPR 2024

aitviewer/viewer.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (C) 2022-2026 ETH Zurich, Manuel Kaufmann, Velko Vechev, Dario Mylonopoulos
22
import copy
33
import os
4+
import subprocess
45
import sys
56
from array import array
67
from collections import namedtuple
@@ -31,6 +32,41 @@
3132
from aitviewer.utils.perf_timer import PerfTimer
3233
from aitviewer.utils.utils import get_video_paths, video_to_gif
3334

35+
36+
class FFmpegWriter:
37+
"""Thin ffmpeg pipe writer, replaces scikit-video which broke on NumPy 2.0."""
38+
39+
def __init__(self, path, inputdict, outputdict):
40+
self._path = path
41+
self._inputdict = inputdict
42+
self._outputdict = outputdict
43+
self._proc = None
44+
45+
def _start(self, frame):
46+
h, w = frame.shape[:2]
47+
pix_fmt = "rgba" if frame.ndim == 3 and frame.shape[2] == 4 else "rgb24"
48+
input_args = [a for k, v in self._inputdict.items() for a in (k, str(v))]
49+
output_args = [a for k, v in self._outputdict.items() for a in (k, str(v))]
50+
cmd = (
51+
["ffmpeg", "-y"]
52+
+ input_args
53+
+ ["-f", "rawvideo", "-pix_fmt", pix_fmt, "-s", f"{w}x{h}", "-i", "pipe:0"]
54+
+ output_args
55+
+ [self._path]
56+
)
57+
self._proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
58+
59+
def writeFrame(self, frame):
60+
if self._proc is None:
61+
self._start(frame)
62+
self._proc.stdin.write(frame.tobytes())
63+
64+
def close(self):
65+
if self._proc is not None:
66+
self._proc.stdin.close()
67+
self._proc.wait()
68+
69+
3470
MeshMouseIntersection = namedtuple(
3571
"MeshMouseIntersection",
3672
"node instance_id tri_id vert_id point_world point_local bc_coords",
@@ -1876,9 +1912,6 @@ def export_video(
18761912
quality="medium",
18771913
ensure_no_overwrite=True,
18781914
):
1879-
# Load this module to reduce load time.
1880-
import skvideo.io
1881-
18821915
if rotate_camera and not isinstance(self.scene.camera, ViewerCamera):
18831916
print("Cannot export a video with camera rotation while using a camera that is not a ViewerCamera")
18841917
return
@@ -1974,7 +2007,7 @@ def export_video(
19742007
}
19752008
)
19762009

1977-
writer = skvideo.io.FFmpegWriter(
2010+
writer = FFmpegWriter(
19782011
path_video,
19792012
inputdict={
19802013
"-framerate": str(output_fps),

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ dependencies = [
4040
"roma>=1.2.3",
4141
"joblib",
4242
"scikit-image>=0.9.0",
43-
"scikit-video",
4443
"Pillow",
4544
"websockets",
4645
"usd-core>=23.5",

0 commit comments

Comments
 (0)