Skip to content

Commit 0637732

Browse files
authored
fix nit batch inference (#374)
Signed-off-by: youliangt <youliangt@nvidia.com>
1 parent 267e2dc commit 0637732

3 files changed

Lines changed: 84 additions & 3 deletions

File tree

gr00t/model/policy.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def get_action(self, observations: Dict[str, Any]) -> Dict[str, Any]:
167167
"""
168168
# Create a copy to avoid mutating input
169169
obs_copy = observations.copy()
170-
170+
171171
is_batch = self._check_state_is_batched(obs_copy)
172172
if not is_batch:
173173
obs_copy = unsqueeze_dict_values(obs_copy)
@@ -348,6 +348,7 @@ def unsqueeze_dict_values(data: Dict[str, Any]) -> Dict[str, Any]:
348348
unsqueezed_data[k] = v
349349
return unsqueezed_data
350350

351+
351352
def squeeze_dict_values(data: Dict[str, Any]) -> Dict[str, Any]:
352353
"""
353354
Squeeze the values of a dictionary. This removes the batch dimension.
@@ -357,7 +358,7 @@ def squeeze_dict_values(data: Dict[str, Any]) -> Dict[str, Any]:
357358
if isinstance(v, np.ndarray):
358359
squeezed_data[k] = np.squeeze(v, axis=0) # Fixed: only remove batch dim
359360
elif isinstance(v, torch.Tensor):
360-
unsqueezed_data[k] = v.squeeze(0) # Fixed: only remove batch dim
361+
squeezed_data[k] = v.squeeze(0) # Fixed: only remove batch dim
361362
else:
362363
squeezed_data[k] = v
363-
return squeezed_data
364+
return squeezed_data

tests/labeled_frames_video.mp4

205 KB
Binary file not shown.

tests/test_load_video.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to extract and save a video frame at a specified time using different backends.
4+
"""
5+
6+
import argparse
7+
import os
8+
9+
from PIL import Image
10+
11+
from gr00t.utils.video import get_frames_by_timestamps
12+
13+
14+
def save_frames_at_time(
15+
video_path: str,
16+
time_seconds: float,
17+
output_dir: str = "frame_outputs",
18+
video_backend: str = "decord",
19+
):
20+
"""Extract and save frames from a video at a specific time using different backends."""
21+
22+
# Create output directory if it doesn't exist
23+
os.makedirs(output_dir, exist_ok=True)
24+
25+
# Get frame using torchvision_av backend
26+
print(f"Extracting frame at {time_seconds} seconds using {video_backend}...")
27+
28+
frame_torchvision = get_frames_by_timestamps(
29+
video_path, [time_seconds], video_backend=video_backend
30+
)[
31+
0
32+
] # Get first (and only) frame
33+
34+
print(f"{video_backend} frame shape: {frame_torchvision.shape}")
35+
36+
# Save frame
37+
output_path = os.path.join(output_dir, f"frame_{video_backend}_{time_seconds}s.png")
38+
Image.fromarray(frame_torchvision).save(output_path)
39+
print(f"Saved {video_backend} frame to: {output_path}")
40+
41+
42+
def main():
43+
import sys
44+
45+
parser = argparse.ArgumentParser(
46+
description="Extract and save video frame at a specific time using different backends"
47+
)
48+
parser.add_argument(
49+
"--video-path", type=str, help="Path to the video file", default="labeled_frames_video.mp4"
50+
)
51+
parser.add_argument(
52+
"--times",
53+
type=float,
54+
help="Time in seconds to extract the frame",
55+
nargs="+",
56+
default=[0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2],
57+
)
58+
parser.add_argument(
59+
"--output-dir",
60+
type=str,
61+
default="frame_outputs",
62+
help="Directory to save output frames (default: frame_outputs)",
63+
)
64+
parser.add_argument(
65+
"--video-backend", type=str, default="decord", help="Video backend to use (default: decord)"
66+
)
67+
args = parser.parse_args()
68+
69+
# Check if video file exists
70+
if not os.path.exists(args.video_path):
71+
print(f"Error: Video file '{args.video_path}' not found.")
72+
sys.exit(1)
73+
74+
# Save frames
75+
for time in args.times:
76+
save_frames_at_time(args.video_path, time, args.output_dir, args.video_backend)
77+
78+
79+
if __name__ == "__main__":
80+
main()

0 commit comments

Comments
 (0)