NVlabs

Stars and mentions

Last 30 days, Oct 4 – Nov 2

GitHub stars1,683
mentions60
066132198264Oct 4Oct 18Nov 2
UTC days · repositories NVlabs owns11 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-23

crates.io—
npm—
PyPI653
0164328492656Oct 4Oct 18Nov 2
Oct 31crates.io: 0/11 packages observed · npm: 0/1 packages observed · PyPI: 1/3 packages observed

Across 15 known packages in repositories NVlabs owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete. PyPI excludes known mirrors.

Top repositories

NVlabs’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside NVlabs’s account where NVlabs opened or reviewed pull requests in the past 365 days.

Who noticed NVlabs

Everyone who starred or forked NVlabs’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

60posts
Nov 32 posts
  1. Reddit · · r/BestGitHubRepos · u/amootiranian · NVlabs/motionbricks

    MotionBricks: Scalable Real-Time Motions with Modular Latent Generative Model and Smart Primitives (561 stars) What it does All text below is quoted directly from the project README. >MotionBricks is a modular latent generative model that animates characters and robots in real time. This repository provides: - Pretrained models for the SOMA body model and the Unitree G1 robot. They ship as ONNX files, with the pretrained checkpoints on Hugging Face. - A Python runtime, built on Warp, Newton, and TensorRT, that chains generations into continuous motion. - Two demos: an Inbetweener that generates motion between poses you place, and a Scene Preview where a character walks, runs, vaults, ducks, and sits its way through a scene. - Two editors to author your own Smart Primitives and scenes. - Smart Primitives turn target poses into building blocks for navigation and object interaction, so behaviors like vaulting and sitting snap together like bricks, with no retraining. >The runtime uses TensorRT, which requires an NVIDIA GPU. The demos were tested on Windows and Linux (x86-64) with an NVIDIA GeForce RTX 4090. Repository NVlabs/motionbricks Repository stats |Metric|Value| |:-|:-| |Stars|561| |Forks|55| |Last release|None| |Languages|Python 100%| |Contributors|1| |AI contributor accounts (Claude / Codex / Cursor / Copilot)|None| |AI co-authored commits|None| Main contributor |Field|Value| |:-|:-| |Name|Olivier Dionne| |GitHub|@oldio| |Commits to this repo|2 (top contributor)| |Company / Location|Nvidia / QC, Canada| |Followers|14| ────────────────────────────── 📌 If you want to browse more repos like this, we've organized them by category and rankings here: bestgithubrepositories.com 🗂️ We're also archiving repos where possible, so useful projects don't disappear when they're removed from GitHub.

    2 points
  2. NVIDIA MotionBricksをMacBook Pro M4で動かしてみた!(ONNX) NVIDIA MotionBricksをMacBook Pro M4で動かしてみた!ONNX Runtimeで人体動作を生成してGIFにする はじめに こんにちは、しゅんです。 かなり久しぶりのQiita投稿になりました。気がつけばもう11月ですね。今年なかなか記事を書けていませんでしたが、Advent Calendar 2026も始まったので、また少しずつ面白い技術やAIモデルを実際に試した結果を共有していきたいと思います。 今回はNVIDIAが公開した MotionBricks を試してみました。 公式デモはNVIDIA GPUとTensorRTを使う構成ですが、「ONNXモデルが公開されているなら、Macでも動かせるのでは?」と思ったので、手元のMacBook Pro M4で実験してみました。 先に結果を書くと、CUDAやTensorRTを使わず、ONNX RuntimeのCPU実行で人体モーションの生成に成功しました! さらに、生成された骨格を簡単なGIFとして出力できました。 今回は初回の動作確認なので、モデルの比較や複雑なアプリへの組み込みは行いません。まずは、公式の歩行データを使って推論を実行し、その結果を見ていきます。 MotionBricksとは? MotionBricks は、NVIDIAが公開した人体・ロボットのモーション生成モデルです。直近の4つの姿勢と、最大4つの目標姿勢を手がかりに、その間の動作を生成する仕組みです。 モデルは大きく、移動経路を予測する部分、姿勢の変化を生成する部分、モーションへ復号する部分で構成されています。生成した短い動作をつなげることで、連続した動作にも応用できます。 今回使用するのは人間向けの SOMAモデル(30関節) です。公式にはUnitree G1向けのモデルも公開されていますが、今回は使用しません。 - 公式サイト:nvlabs.github.io - 公式GitHub:NVlabs/motionbricks - 論文:arxiv.org - ONNX推論の説明:github.com/NVlabs/motionbricks/blob/main/docs/onn… 今回試すこと 公式の歩行モーション(BVH)を入力に、MotionBricksから新しい骨格モーションを生成してみます。生成した結果はNumPyの.npzで保存し、Matplotlibを使ってGIFでも確認します。 なお、今回は CPUでのONNX推論の確認 です。Core MLへの変換やApple GPUでの高速化、公式デモと同等の連続動作再生までは検証していません。 実行環境 | 項目 | 環境 | | --- | --- | | PC | MacBook Pro M4 / 32GB RAM | | OS | macOS | | Python | 3.12.11 | | ONNX Runtime | 1.31.1 | | NumPy | 2.5.4 | | モデル | MotionBricks SOMA FP32(ONNX) | | 推論デバイス | CPUExecutionProvider | | 可視化 | Matplotlib / Pillow | MotionBricksの公式PythonランタイムはTensorRTを前提としていて、READMEでもNVIDIA GPUが必要とされています。そのままuv syncして公式のデモを起動するのではなく、今回は 公開済みONNXモデルをONNX Runtimeから直接読み込む 方法を試しました。 1. 公式リポジトリをClone まず、公式リポジトリをCloneします。大きなモデルファイルやサンプルデータはGit LFSで管理されているので、少し時間がかかる場合があります。 git lfs install git clone https://github.com/NVlabs/motionbricks.git cd motionbricks Clone後、次のファイルが存在することを確認しました。 motionbricks/assets/onnx/soma/ ├── mmm_v6_soma_fp16.onnx ├── mmm_v6_soma_fp32.onnx └── soma_n1.json 今回使うのはmmm_v6_soma_fp32.onnxです。Clone後にモデルがLFSのポインタだけになっている場合は、git lfs pullで取得してください。 2. Mac用の最小環境を用意 Python 3.12の仮想環境を作ります。公式ランタイムのCUDA/TensorRT依存関係はインストールしません。 # uvが未導入ならインストール brew install uv uv venv --python 3.12 uv pip install onnxruntime numpy scipy matplotlib pillow ここで必要なのはONNX Runtimeと、BVHの処理・GIF出力に使うライブラリです。 まずはモデルの読み込みだけ試しました。 import onnxruntime as ort session = ort.InferenceSession( "motionbricks/assets/onnx/soma/mmm_v6_soma_fp32.onnx", providers=["CPUExecutionProvider"], ) print(session.get_providers()) 結果: Model loaded in 0.90s Providers: ['CPUExecutionProvider'] SUCCESS: MotionBricks ONNX model loaded on Mac ここではあくまでモデルの読み込みに成功しただけなので、続けて実際のモーション生成を試します。 3. 実際にモーションを生成してみる 今回は、公式リポジトリ内にある以下の歩行BVHファイルを使用しました。 assets/motions/soma/locomotion/bs_1d_linear/Neutral_walk_forward_002__A057.bvh このサンプルは120Hzですが、モデルが扱う姿勢は30Hzなので、4つの直近姿勢と4つの目標姿勢を30Hz間隔で取り出して、SOMAのONNX入力テンソルを構成します。 ONNXの出力には、腰の位置、関節位置、関節回転などの特徴量が含まれています。そこから骨格座標を復元して、.npzとGIFに保存する簡単なスクリプトを作成しました。 motionbricks_macos_first_motion.pyをCloneしたリポジトリの直下に置きます。以下は今回実際に使用したコード全文です。(先頭のdocstringに残っている~/Downloads/の使用例は作成時のパスです。今回の実行コマンドは後述のとおりです。) #!/usr/bin/env python3 """First real MotionBricks SOMA generation on macOS using ONNX Runtime (CPU). Uses NVIDIA's bundled SOMA walking BVH clip as conditioning, converts its world-space joints into the official SOMA ONNX tensor representation, and exports the predicted 3D skeleton and a static/orbiting camera GIF. Run from the motionbricks repository root: uv pip install scipy matplotlib pillow .venv/bin/python ~/Downloads/motionbricks_macos_first_motion.py """ from __future__ import annotations import argparse import json import math from pathlib import Path import time import numpy as np import onnxruntime as ort from scipy.spatial.transform import Rotation SAMPLE_BVH = Path("assets/motions/soma/locomotion/bs_1d_linear/Neutral_walk_forward_002__A057.bvh") SOMA_DIR = Path("motionbricks/assets/onnx/soma") def parse_bvh(path: Path): """Parse BVH hierarchy and motion channels without importing CUDA/Warp.""" lines = path.read_text(encoding="utf-8").splitlines() nodes: list[dict] = [] stack: list[int] = [] end_site = False at_motion = None for i, line in enumerate(lines): tok = line.strip().split() if not tok: continue if tok[0] == "MOTION": at_motion = i break if tok[0] in ("ROOT", "JOINT"): nodes.append(dict(name=tok[1].rsplit(":", 1)[-1], parent=stack[-1] if stack else -1, offset=np.zeros(3), channels=[], start=0)) stack.append(len(nodes) - 1) elif tok[:2] == ["End", "Site"]: end_site = True elif tok[0] == "OFFSET" and not end_site: nodes[stack[-1]]["offset"] = np.array([float(v) for v in tok[1:4]]) * .01 elif tok[0] == "CHANNELS": nodes[stack[-1]]["channels"] = tok[2:] elif tok[0] == "}": if end_site: end_site = False else: stack.pop() if at_motion is None: raise ValueError("BVH has no MOTION section") pos = 0 for n in nodes: n["start"] = pos pos += len(n["channels"]) frame_count, frame_time = None, None motion_start = None for i in range(at_motion+1, len(lines)): line = lines[i].strip() if line.startswith("Frames:"): frame_count = int(line.split(":", 1)[1]) elif line.startswith("Frame Time:"): frame_time = float(line.split(":", 1)[1]) motion_start = i + 1 break if frame_count is None or not frame_time or motion_start is None: raise ValueError("BVH missing Frames or Frame Time") data = np.loadtxt(lines[motion_start:motion_start+frame_count], dtype=np.float64) if data.ndim == 1: data = data[None] if data.shape != (frame_count, pos): raise ValueError(f"Unexpected BVH samples {data.shape}; expected {(frame_count, pos)}") return nodes, data, frame_time def global_joints(nodes, frame): """Match official BVH loader: Euler channels composed in channel order; cm to m.""" positions = np.zeros((len(nodes), 3)) rotations: list[Rotation] = [] axes = dict(X=np.array([1., 0., 0.]), Y=np.array([0., 1., 0.]), Z=np.array([0., 0., 1.])) for i, n in enumerate(nodes): offset = n["offset"].copy() local_rot = Rotation.identity() for j, channel in enumerate(n["channels"]): value = frame[n["start"] + j] if channel.endswith("position"): offset["XYZ".index(channel[0])] = value * .01 elif channel.endswith("rotation"): local_rot = local_rot * Rotation.from_rotvec(np.deg2rad(value) * axes[channel[0]]) parent = n["parent"] if parent >= 0: positions[i] = positions[parent] + rotations[parent].apply(offset) rotations.append(rotations[parent] * local_rot) else: positions[i] = offset rotations.append(local_rot) return positions, rotations def heading(right, left): across = right - left across[1] = 0. d = np.linalg.norm(across) if d < 1.e-6: return 0. forward = np.cross([0., 1., 0.], across/d) return float(np.arctan2(forward[0], forward[2])) def encode_sample(nodes, data, step, names, context_end=1., target_start=1.8): bvhnames = {n["name"]: i for i, n in enumerate(nodes)} missing = [name for name in names if name not in bvhnames] if missing: raise ValueError("BVH missing joints present in SOMA ONNX contract: " + ", ".join(missing)) picks = [context_end - (3 - i)/30. for i in range(4)] + [target_start + i/30. for i in range(4)] idxs = [round(t/step) for t in picks] if max(idxs) >= len(data) or min(idxs) < 0: raise ValueError(f"BVH too short ({len(data)} frames) for requested sample indices {idxs}") src = [global_joints(nodes, data[i]) for i in idxs] mapidx = [bvhnames[name] for name in names] positions = np.stack([p[mapidx] for p, _ in src]) rots = [[r[i] for i in mapidx] for _, r in src] initial_heading = heading(positions[3,26].copy(), positions[3,22].copy()) # Official SOMA alignment: center ground plane on last context Hips and face +Z. origin = positions[3,0].copy(); origin[1] = 0. inv_align = Rotation.from_euler("y", -initial_heading) aligned_pos = inv_align.apply(positions - origin) aligned_rot = [[inv_align * r for r in rs] for rs in rots] h = np.array([heading(p[26].copy(), p[22].copy()) for p in aligned_pos]) global_root_values = np.zeros((1,8,5),np.float32) local_root_values = np.zeros((1,8,4),np.float32) local_poses = np.zeros((1,8,267),np.float32) for i in range(8): root = aligned_pos[i,0] global_root_values[0,i] = [*root, math.cos(h[i]), math.sin(h[i])] next_i = i if i in (3,7) else i+1 d = np.arctan2(math.sin(h[next_i]-h[i]),math.cos(h[next_i]-h[i])) local_root_values[0,i] = [d*30., (aligned_pos[next_i,0,0]-root[0])*30., (aligned_pos[next_i,0,2]-root[2])*30., root[1]] local_poses[0,i,:87] = (aligned_pos[i,1:] - np.array([root[0],0.,root[2]])).ravel() for j, r in enumerate(aligned_rot[i]): M = r.as_matrix() local_poses[0,i,87+j*6:87+(j+1)*6] = np.r_[M[:,0], M[:,1]] masks = np.ones((1,8),np.int32) local_masks = masks.copy(); local_masks[0,[3,7]]=0 return { "global_root_values": global_root_values, "local_root_values": local_root_values, "local_poses": local_poses, "has_global_root_values": masks, "has_local_root_values": local_masks, "has_local_poses": masks.copy(), "allowed_pred_num_tokens": np.ones((1,11),np.int32) } def draw_gif(pts, parents, output: Path, orbit=False): import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation, PillowWriter span = np.ptp(pts.reshape(-1,3), axis=0) mid = np.mean([pts.reshape(-1,3).min(axis=0), pts.reshape(-1,3).max(axis=0)], axis=0) half = max(float(np.max(span)), 1.8)*.55 fig = plt.figure(figsize=(6,5)) ax = fig.add_subplot(111, projection="3d") frames = range(0,len(pts),2) def animate(k): ax.cla() p = pts[k] for j in range(1,len(parents)): par = parents[j] if par < 0: continue v = p[[j,par]] ax.plot(v[:,0],v[:,2],v[:,1],color="black",lw=1.5) ax.scatter(p[:,0],p[:,2],p[:,1],color="tab:blue",s=6) ax.set_xlim(mid[0]-half,mid[0]+half) ax.set_ylim(mid[2]-half,mid[2]+half) ax.set_zlim(max(-.2,mid[1]-half),mid[1]+half) ax.set_xlabel("X (m)"); ax.set_ylabel("Z (m)"); ax.set_zlabel("Y-up (m)") ax.set_title("MotionBricks SOMA - Mac ONNX CPU") ax.view_init(elev=16,azim=40+(120*k/len(pts) if orbit else 0)) anim=FuncAnimation(fig,animate,frames=list(frames),interval=1000/15,repeat=True) anim.save(output,writer=PillowWriter(fps=15)) plt.close(fig) def main(): pa=argparse.ArgumentParser() pa.add_argument("--skip-gif",action="store_true",help="Only test inference and write output NPZ") pa.add_argument("--orbit",action="store_true",help="Rotate virtual camera when creating GIF") pa.add_argument("--model",default=str(SOMA_DIR/"mmm_v6_soma_fp32.onnx")) pa.add_argument("--bvh",default=str(SAMPLE_BVH)) args=pa.parse_args() model=Path(args.model); bvh=Path(args.bvh) if not bvh.exists() or bvh.stat().st_size < 200: raise SystemExit(f"Missing real example BVH file: {bvh} (check git lfs pull)") manifest=json.loads((SOMA_DIR/"soma_n1.json").read_text()) joint_names=manifest["joint_names"] print("Reading NVIDIA's sample walking BVH ...",flush=True) nodes, clip, step=parse_bvh(bvh) inputs=encode_sample(nodes,clip,step,joint_names) print(f"Conditioning: 4 context + 4 target poses; source rate {1/step:.2f}Hz",flush=True) print("Loading official FP32 ONNX ...",flush=True) t0=time.perf_counter() session=ort.InferenceSession(str(model),providers=["CPUExecutionProvider"]) print(f"Loaded in {time.perf_counter()-t0:.2f}s. Running REAL inference ...",flush=True) t0=time.perf_counter() outputs=dict(zip([x.name for x in session.get_outputs()],session.run(None,inputs))) print(f"Inference completed in {time.perf_counter()-t0:.2f}s",flush=True) tokens=int(outputs["pred_num_tokens"][0]); raw=outputs["pred_global_motions"][0,:4*tokens] if tokens not in range(6,17) or not np.isfinite(raw).all(): raise RuntimeError(f"Bad output: num_tokens={tokens}, finite={np.isfinite(raw).all()}") # Official output has 3 start/end boundary frames. No endpoint correction here. raw=raw[3:-3] roots=raw[:,:3] pts=np.zeros((len(raw),len(joint_names),3),dtype=np.float32) pts[:,0,:]=roots pts[:,1:,:]=raw[:,5:5+29*3].reshape(-1,29,3)+np.stack([roots[:,0],np.zeros(len(roots)),roots[:,2]],axis=1)[:,None,:] out_dir=Path("mac_test_output");out_dir.mkdir(exist_ok=True) np.savez_compressed(out_dir/"soma_generated.npz",features=raw,world_joints=pts,root_xyz=roots, joint_names=np.array(joint_names),model_inputs=inputs["local_poses"]) print(f"Generated {len(raw)} valid frames ({len(raw)/30:.2f}s at 30Hz)") print(f"Root: start={roots[0].round(3)}, end={roots[-1].round(3)}") print(f"Saved: {out_dir/'soma_generated.npz'}") if not args.skip_gif: index={n['name']:i for i,n in enumerate(nodes)} parents=[] for name in joint_names: src=nodes[index[name]] p=src['parent'] while p>=0 and nodes[p]['name'] not in joint_names: p=nodes[p]['parent'] parents.append(joint_names.index(nodes[p]['name']) if p>=0 else -1) gif=out_dir/("soma_orbit.gif" if args.orbit else "soma_fixed_camera.gif") print("Rendering 3D stick-figure GIF...",flush=True) draw_gif(pts,parents,gif,orbit=args.orbit) print(f"Saved: {gif}") print("SUCCESS: MotionBricks SOMA produced skeletal motion on macOS via ONNX CPU") if __name__=="__main__": main() 4. 実行結果 まず、推論のみ実行してNumPyファイルを保存しました。 .venv/bin/python motionbricks_macos_first_motion.py --skip-gif 実際のログです。 Reading NVIDIA's sample walking BVH ... Conditioning: 4 context + 4 target poses; source rate 120.00Hz Loading official FP32 ONNX ... Loaded in 1.07s. Running REAL inference ... Inference completed in 0.02s Generated 26 valid frames (0.87s at 30Hz) Root: start=[ 0.002 0.933 -0.002], end=[0.207 0.969 1.164] Saved: mac_test_output/soma_generated.npz SUCCESS: MotionBricks SOMA produced skeletal motion on macOS via ONNX CPU 続いて、生成した骨格をカメラが回り込むGIFとして出力しました。 .venv/bin/python motionbricks_macos_first_motion.py --orbit open mac_test_output/soma_orbit.gif こちらも正常に完了しました。 Reading NVIDIA's sample walking BVH ... Conditioning: 4 context + 4 target poses; source rate 120.00Hz Loading official FP32 ONNX ... Loaded in 0.91s. Running REAL inference ... Inference completed in 0.02s Generated 26 valid frames (0.87s at 30Hz) Root: start=[ 0.002 0.933 -0.002], end=[0.207 0.969 1.164] Saved: mac_test_output/soma_generated.npz Rendering 3D stick-figure GIF... Saved: mac_test_output/soma_orbit.gif SUCCESS: MotionBricks SOMA produced skeletal motion on macOS via ONNX CPU 生成GIF !soma_orbit.gif このGIFは、生成した骨格位置をMatplotlibで描画した簡易的なスティックフィギュアです。公式の3Dキャラクターを再現したものではなく、推論結果の座標を確認するための可視化になります。 結果のまとめ | 項目 | 結果 | | --- | --- | | ONNXモデル読み込み | 成功(約0.9〜1.1秒) | | ONNX推論 | 成功(ログ上は約0.02秒) | | 生成したモーション | 26フレーム/約0.87秒 | | 出力データ | soma_generated.npz | | 骨格GIF | soma_orbit.gif | | CUDA / TensorRT | 不使用 | 約20msという数字はこの入力に対する1回のONNX推論の測定値であり、前後の処理やGIF生成まで含めた時間ではありません。複数回の平均やApple GPUとの比較もまだ実施していません。 また、公式ランタイムは生成結果の前後の境界フレーム除去に加え、始点・終点の補正も行っています。今回のスクリプトは境界の3フレームずつを除去していますが、始点・終点の補正は未実装です。したがって、公式デモとモーション品質が完全に一致するという意味ではありません。 5. 感想・今後試したいこと 個人的に面白かったのは、NVIDIA GPUが必要な公式ランタイムとは別に、公開されているONNXモデルを使ってMacでも人体動作を生成できたことです。 まだ短い歩行モーションを1回生成しただけですが、次は停止位置や移動方向を変更したり、動作を連続生成したりしてみたいと思います。余裕があれば、3Dエンジン上でキャラクターを動かすところまで試してみたいです。 今回はひとまず「Macでモデルを読み込み、実際に推論し、生成した骨格をGIFで確認できた」という記録でした。 久しぶりの記事になりましたが、これからも気になったモデルは実際に触ってみて、面白い使い方を探していこうと思います。 最後まで読んでいただき、ありがとうございました! 参考リンク - MotionBricks 公式プロジェクトページ - MotionBricks 公式GitHub - MotionBricks 論文(arXiv) - 公式 ONNX inference and batching - SOMAモデルの説明 ※ 公式のサンプルモーションおよびモデルの利用には、それぞれのライセンス条件が適用されます。この記事ではモデル重みやBVHデータ自体は再配布していません。

    1 like
  3. 自分の3DキャラをMotionBricksで動かす。ColabのT4とキーボードで試してみた 私は今、研究室独自のキャラ(といっても、私の写真やプロンプトを元にChatGPTに作ってもらったのですが)を展開していて、現在、TakaBounce Campusというゲームを3D化しています。 主人公は、私をキャラクタにしたTakaです。 せっかく3Dモデルができたので、歩いたり、走ったり、ジャンプしたりしてほしい。 さらに、椅子に座ったり、立ち上がったりまで自然にできたら、ゲーム以外にも使えそうです。 そこで気になったのが、NVIDIAのMotionBricksでした。 公開されているデモを見ると、人間がかなり自然に動いています。 これを、自分のキャラでやりたい。 今回は、Google ColabのT4 GPUで動きを生成して、ブラウザに表示したTAKAをキーボードで操作してみました。 実際に、キーを押すと歩き、走り、ジャンプし、椅子に座って立つところまで動かせました。 ただ、ここまで来るのに一番苦労したのは、GPUの性能よりも、私のキャラクタに人間の動きをどう対応させるかという部分でした。 頭が大きく、手足が短いキャラですからね。 MotionBricksは何を生成するのか MotionBricksの公式リポジトリと、Wangらの論文を参照しています。 論文名は MotionBricks: Scalable Real-Time Motions with Modular Latent Generative Model and Smart Primitives です。 SIGGRAPH 2026の研究で、ACM Transactions on Graphicsに掲載されています。DOIもあります。 MotionBricksは、直前の姿勢と、これから到達したい姿勢を条件に、その間の動きを生成する仕組みです。 人間用のSOMAモデルに加え、ヒューマノイドロボット用のモデルも公開されています。 今回は、人間用の学習済みモデルを使いました。 公式の説明では、直近4姿勢を履歴とし、1〜4個の目標姿勢に向かう動きを30Hzで生成します。 経路と時間を扱うモジュール、姿勢を扱うモジュール、連続した動きへ戻すデコーダーが役割を分担します。 移動や物とのやり取りの目標姿勢を組み立てる仕組みが、Smart Primitivesです。 この構成は公式READMEの解説にもまとまっています。 つまり、キーボードの「前へ進む」をそのままニューラルネットワークへ渡せば終わり、という接続ではありません。 アプリ側で「この方向へ、この速さで進む」という意図を目標姿勢へ変換し、それをMotionBricksに渡します。 椅子に座るなら、椅子の位置と向きに合わせた目標が必要です。 今回も、移動や着座の目標を作るときには、公式の設定や参照姿勢を利用しています。 その目標に向かう途中の動きは、実行中に生成します。 既存の歩行クリップをキーに合わせて再生するだけの実装とは、この部分が違います。 TAKA用にモデルを再学習したわけでもありません。 自分のキャラを用意するところが、やっぱり難しい 私の制作では、まずキャラクタの正面、背面、左右の絵を用意し、MeshyやSloydを使って3D化を進めました。 これらは制作中に使ったサービスで、両方を通さないといけないわけではありません。 今回の人間型TAKAでは、Meshyで生成したモデルをもとに調整しています。 前後左右の絵は、同じキャラクタを同じ大きさで描いておくと、後から形を確認しやすくなります。 ただし、複数方向の画像をどう入力できるかは、サービスや利用する機能によって違います。 絵を4枚作れば、そのまま動くモデルが完成するという話ではありません。 できあがった3Dモデルには、顎の形、メガネ、髪の生え際、袖など、直したい箇所がありました。 それをCodexとBlenderで調整しながら、身体を動かすための骨格を定義しました。 骨を入れる作業をリギングと呼びます。 さらに、どの骨がメッシュのどこを動かすかという重み付け、いわゆるスキニングも必要です。 ここが結構厄介でした。 止まっているとかわいいのに、腕を曲げると袖が切れたように見える。 右足だけ引きずる。 手がお腹に入る。 こういうことが、本当に次々と出てきました。 MotionBricksから届く骨格の動きと、TAKAの骨格の動きは、そのまま同じにはなりません。 生成元の人間とTAKAでは、肩幅、腕の長さ、脚の長さ、頭の大きさが違います。 この対応を作る処理が、リターゲティングです。 何が準備できていれば試せるのか 今回の仕組みで別のキャラを動かすためには、少なくとも次のものが必要です。 準備するもの 今回、必要だった内容 人間型の3Dモデル GLBで読み込めるメッシュとマテリアル 身体の骨格 腰、背骨、胸、首、頭、肩、上腕、前腕、手、太もも、すね、足などの親子関係 スキニング 骨を動かしたときに、身体や服が連続して変形する重み 基準姿勢 TポーズやAポーズなど、各骨の向きを校正できる姿勢 骨の対応表 生成元の関節と、自分のモデルの骨を対応付ける情報 体格の校正値 身体の向き、長さ、足裏、手の向き、接触回避に使う身体の範囲 表情や口パクも重ねるなら、顔を変形するモーフターゲット、または顔用の骨も用意します。 身体を動かすだけなら、表情の仕組みは後から追加できます。 今回の変換コードは、私が定義したTAKAの骨格を前提にしています。 したがって、別のGLBにファイル名だけ差し替えて、すべて動くとは言えません。 GLBという形式が同じでも、骨の名前、向き、親子関係、メッシュの重みは違うからです。 別のキャラで最初にやるなら、直立、左右の腕上げ、膝曲げ、足首の曲げを、生成処理と切り離して確認するのがよかったと思います。 その状態で服や関節が崩れるなら、動作生成を調整する前にモデルを直した方が早いです。 その場しのぎの補正から、体格の校正へ 制作の途中では、見えている違和感を追いかけて、かなり場当たり的に直していました。 ただ、それを続けると、歩行がよくなったら別の動作がおかしくなる、ということが起こります。 そこで、途中から次のように分けました。 共通の変換処理:座標変換、基準姿勢からの回転差、腕と脚の解き方、接地の扱い。 キャラ固有の校正:骨の名前、実際の長さ、手のひらの向き、頭や身体の大きさ。 モデル自体の修正:関節位置、靴の向き、袖の形、スキニングの重み。 たとえば、足首の位置だけを床へ固定すると、つま先で蹴り出す動きまで止めてしまうことがあります。 今回は靴のメッシュも参照して、かかととつま先の支持点を扱うようにしました。 肩も、生成元の回転をそのまま広い肩幅のキャラへ写すと、落ちすぎたり、腕が不自然に開いたりします。 基準姿勢と骨の軸から、どう対応させるかを見直しました。 この分離で、別のキャラに応用するときに変更すべき場所がわかりやすくなります。 ただし、現在のコードにもTAKA向けの設計や補助骨の前提は残っています。 汎用のリターゲット製品が完成した、という段階ではありません。 Colabとブラウザをどうつないだか 今回の構成は、生成する場所と、キャラを表示する場所を分けています。 GPUを使うのは、Colab側のMotionBricksです。 一方、3Dモデルの表示とTAKA向けの姿勢変換は、手元のブラウザで行います。 ColabのT4を使っていても、Mac側のブラウザの負荷は残ります。 身体の生成結果として送るのは、各関節の位置とクォータニオンによる回転、接地情報などです。 動画を毎フレーム転送しているわけではありません。 ブラウザが受け取った情報から、自分で3Dモデルを描画しています。 Notebookで実行していること Notebookの役割は、環境を準備し、モデルを復元し、生成サーバーを起動して、その操作画面をColabの出力へ出すことです。 TAKAの骨格をその場でBlenderから作り直すNotebookではありません。 調整済みのモデルと変換コードを読み込んで使います。 GPUと実行ファイルを用意する 最初に、GPUが割り当てられているか確認します。 Notebookでは、nvidia-smi の結果を表示し、GPUがなければ止めています。 import subprocess r = subprocess.run( ["nvidia-smi", "--query-gpu=name,memory.total", "--format=csv,noheader"], capture_output=True, text=True, ) print(r.stdout or r.stderr) if r.returncode: raise RuntimeError("GPUランタイムを選択してください。") 実行用のZIPはGoogle Driveへ置きました。 毎回アップロードするのは面倒なので、Driveを接続して、そこからColab内へコピーして展開します。 ZIPに含めたハッシュ一覧で、展開後のファイルも確認します。 以下は、保存先を読者の環境用に置き換えた例です。 from pathlib import Path from google.colab import drive drive.mount("/content/drive") DRIVE_FOLDER = Path("/content/drive/MyDrive/MotionBricksExperiment") ZIP_PATH = DRIVE_FOLDER / "Professor_MotionBricks_latency20_runtime.zip" MODEL_CACHE_DIR = str(DRIVE_FOLDER / "MotionBricks") MotionBricksExperiment は自分で用意する保存先です。 ここに示したパスやファイル名だけを作っても、実行一式が自動で手に入るわけではありません。 自分のモデルに対応したコードとGLBを用意して、ZIPにまとめる必要があります。 公式環境とモデルを準備する 依存環境はuvで管理し、Git LFSを使って公式モデルと必要な動作参照を取得します。 実際の準備セルでは、固定コミットへのチェックアウト、必要なLFSデータの検証、環境構築を順番に行っています。 中心となるコマンドは、次のようなものです。 git clone NVlabs/motionbricks git checkout 54fc563aeaaf819a753d72cc9fdc6713989cdd43 uv sync --python 3.12 --frozen この3行は準備処理の抜粋です。 私のNotebookでは、大きなLFSファイルを最初のclone時に自動取得しない設定にし、キャッシュ確認後、必要なものだけ取得します。 公式の導入手順はリポジトリのSetupを参照してください。 モデルなどはDriveへキャッシュし、次のランタイムでも再利用できるようにしました。 ファイルの内容をSHA-256で確認してから、速いローカル領域の/contentへコピーします。 不足や破損があった場合だけ取得する方式です。 今回使う32ファイルについて、既存キャッシュのファイル名とサイズの一致も確認しました。 キャッシュがあっても、Python環境の導入やGPUの初期化は必要です。 TensorRTの初回準備もあり、「Driveに置いたので起動待ちがゼロ」とはなりません。 私がDriveで共用しているのは主にモデルと参照データで、GPUごとのTensorRTプランまで一律に共用する仕組みではありません。 Pythonの生成サーバーを起動する 公式ランタイムを呼ぶPythonプログラムを、Colab内のポート8780で起動します。 サーバーは身体の生成状態を保持し、前回までの履歴を使って次の動きを生成します。 キー入力のたびに別のモデルをロードする方式ではありません。 Notebookでは専用のプロセスとして起動し、状態取得APIが準備完了を返すまで待ちます。 最初の推論で必要な準備も起動時に済ませ、操作開始直後の大きな待ちを減らしました。 ウォームアップには別のプレイヤーを使い、実際の操作用の姿勢履歴を進めないようにしています。 Colabの出力へHTML画面を出す 操作画面を表示するセルは、この部分です。 from google.colab import output output.no_vertical_scroll() output.serve_kernel_port_as_iframe(8780, height=760) output.no_vertical_scroll()は、出力欄の縦スクロールを抑えるために入れています。 表示領域の高さは、heightでも調整します。 ブラウザや画面サイズによっては、Colab全体のスクロールは残ります。 表示されたHTML画面で「生成を開始」を押し、3D画面をクリックしてからキーボード操作します。 画面へフォーカスが当たっていないと、WASDなどが操作に使われません。 これは使ってみると結構大事でした。 キーボード入力を動作の指示へ変える 今回割り当てた主な操作は、次のとおりです。 キー 操作 WASD、矢印 移動 Shift、B 走る キーを離す 止まる Space ジャンプ P、Ctrl 押している間しゃがむ O 横移動や後退のモード切り替え V 乗り越え F くぐる I 座る、座っているときは立つ [ 移動スタイルの切り替え マウス 視点の変更 C 視点を戻す 移動方向は、カメラの向きから計算して、生成側の座標へ変換しています。 そして、ブラウザからPythonへ、移動方向や状態を送ります。 たとえば、次はジャンプを要求するデータの例です。 { "x": 0.0, "z": -1.0, "run": false, "crouch": false, "jump": 1, "strafe": false, "action": "jump", "style": "neutral", "frames": 4 } この実装のjumpという項目名は少し紛らわしいのですが、単に「飛んでいるか」というフラグではありません。 単発のアクション要求を区別するための連番です。 ジャンプだけでなく、乗り越えや着座でもこの連番を増やし、actionで種類を指定します。 キーを押しっぱなしにしても、同じアクションが無制限に再発火しないようにしています。 ブラウザ側の送信処理は、概略では次のようになります。 const response = await fetch("./api/step", { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/vnd.motionbricks.frames" }, body: JSON.stringify(command) }); // decodeMotionは、この実験で用意したfloat32形式のデコーダー。 // JavaScriptやMotionBricksに標準で備わる関数ではない。 const result = decodeMotion(await response.arrayBuffer()); queue.push(...result.frames); 同じ生成状態へ複数の要求を同時に送ると、姿勢の履歴や入力順序がわかりづらくなります。 そこで、生成要求は一つずつ処理し、画面表示と次の要求の準備を並行させています。 動きの生成と、TAKAへの変換 Python側では、指示に合わせて目標姿勢を配置し、生成プレイヤーへ渡します。 生成した動きを30Hzでサンプリングし、使った姿勢を履歴へ戻します。 実装の中心は、次の流れです。 変数は初期化済みのものを使う、backend.pyの処理の抜粋。 targetには移動やアクションの目標姿勢が入る。 self.player.generate(self.target, settings) 生成済みの動きから1/30秒後の姿勢を取り出す。 self.player.sample(1 / 30, self.current, self.contacts) self.player.record_pose(1 / 30, self.current) generateは、新しい遷移が必要なときに呼びます。 すべての表示フレームで新たな推論を実行しているわけではありません。 ブラウザへ数フレームずつ送る単位と、モデルが一度に生成する動きの長さも別です。 ブラウザへ戻した生成骨格は、TAKAの体格に合わせて変換します。 ここでは、軸の向き、基準姿勢からの回転差、手足の長さ、足裏の接地、身体への手のめり込みなどを扱います。 今回の生成側はZ軸が上、表示側のThree.jsはY軸が上という違いもあります。 骨格の対応の一部は、次のようになります。 生成元SOMAの関節 TAKA側の役割 Hips 腰 Spine1、Chest 背骨、胸 LeftArm、RightArm 左右の上腕 LeftForeArm、RightForeArm 左右の前腕 LeftLeg、RightLeg 左右の太もも LeftShin、RightShin 左右のすね LeftFoot、RightFoot 左右の足 名前をそろえるだけでは不十分で、骨の軸がどちらを向いているかも確認します。 今回、右足を引きずって見える問題や腕の違和感を調べるうえで、この対応の見直しにかなり時間を使いました。 生成骨格を表示して、元の動きにも問題があるのか、TAKAへ変換した後に問題が出るのかを比較できるようにもしました。 表情や瞬き、音声に合わせた口パクは、身体とは別の層で重ねています。 そのため、歩きながら話すような組み合わせもできます。 今回のMotionBricksが、音声から顔や口の動きまで一緒に生成しているという意味ではありません。 T4で動く。でも、操作には遅れがある 今回、ColabのT4 GPUで動作生成を実行できました。 A100でないと試せない、という構成ではありません。 ただ、触ってみると、キーを押してから反応が見えるまでの遅れはあります。 最初は、T4だから遅いのかな、とも思いました。 しかし、生成側だけを見ていても操作感は説明できません。 今回の構成では、次の処理を経由します。 キー入力 → 通信とサーバーへの要求 → 目標の更新と必要な生成 → 姿勢データの転送 → 受信済みの動きの待ち行列 → TAKAの体格への変換 → ブラウザの描画 このうち、GPUを速くすれば短くなる時間もあります。 一方で、ネットワークの往復や受信待ち、手元の姿勢補正と描画は、それだけでは短くなりません。 動きの生成速度と、操作から見た応答時間を分けて測る必要がありました。 今回の操作記録には、3,754フレーム、408回のAPI呼び出しが残っています。 サーバー内部のstep処理時間は、次のようになっていました。 サーバー内部の処理時間 今回の記録 中央値 約9.95ms 95パーセンタイル 約30.87ms 最大 約960ms これは、受け渡し用の姿勢を作る処理、必要に応じた生成、サンプリング、GPUとの同期などを含む値です。 通信、HTTP応答のエンコード、ログの保存、ブラウザの描画は含みません。 また、各呼び出しで返すフレーム数が違い、新しい生成が必要でない呼び出しもあるため、「MotionBricksの推論1回が9.95ms」と読む数値ではありません。 最大値もあり、常に一定時間で応答するわけではありませんでした。 出力側で変えたこと 通信と表示の調整では、姿勢の精度を落とさず、待ち時間や重複作業を減らしました。 固定8フレームの受信から、通常4〜6フレーム程度で始める適応的な受信へ変更。 関節情報の転送をJSONからfloat32バイナリへ変更。 HTTP接続の再利用と、小さなパケットの待ちを抑える設定。 GPUのウォームアップを操作開始前へ移動。 ブラウザ側の重複した形状更新や頻繁すぎる表示更新を削減。 回線が遅いときは、受信フレーム数を最大16まで増やします。 細かく要求しすぎると通信が追いつかないため、そのバランスも必要でした。 返ってきた姿勢を捨てたり、動きを倍速にして追いつかせたりする処理は入れていません。 同じ4フレームを使った比較では、gzip後のデータ量がJSONの19,475 bytesから、float32形式の7,620 bytesになりました。 この例では約61%減っています。 別途、同じT4とブラウザで同じキー列を使って比較したところ、対応する入力9点の「入力から、その指示を使った姿勢が最初に描画されるまで」の中央値は、335.8msから300.4msへ短くなりました。 約11%の改善です。 この比較はColab CLI経由の接続で行い、Notebookのiframe経由で測った値ではありません。 今回の操作ログの数値とも測定条件が異なります。 少数の実測なので、どの環境でも300msで動くとは言えません。 動作が切り替わり終わるまでの時間とも違います。 それでも、T4の生成性能だけで操作感を判断せず、通信から表示までを直す意味は確認できました。 変更前後で生成結果も比較しました。 同じ入力履歴864フレームでは、生成された関節値の最大差は0でした。 この検査は、通信の改善で動きを変えていないことの確認で、どの姿勢も完全に自然だという保証ではありません。 無料版Colabでも試せるのか 計算性能という意味では、今回T4で動かせたことはうれしい結果です。 手元にNVIDIA GPUがないMacでも、Colab側で生成して、ブラウザ側でキャラを動かせます。 ただし、今回確認したのはT4上での実行で、無料枠のアカウントで同じ条件の通し実行を確認したわけではありません。 無料版でGPUが割り当てられれば試す余地はありますが、GPUの種類や利用可能時間は保証されません。 GoogleのColab FAQにも、その点が説明されています。 同じFAQには、無料枠でのSSHなどのリモート操作や、Notebook UIを迂回して主にWeb UIから操作する使い方への制限もあります。 そのため、今回のCLI検証環境を、そのまま無料枠向けの実行手順として勧めることはしません。 Notebook内の対話実験としての使い方と利用条件を確認し、必要に応じて有料枠や手元のGPU環境を選ぶ、という整理です。 最後にGPUまで止める Notebookでは、結果を保存した後、サーバーを止めるセルと、GPUランタイムを解放するセルを分けました。 サーバーを止めても、GPUランタイムは確保されたままだからです。 このNotebookが起動した専用プロセス群を止める、自作の関数。 stop_motion_server() 必要なファイルの保存を終え、実験を終了するときに実行する。 from google.colab import runtime runtime.unassign() /contentにしかない記録は消えるので、先に保存します。 ブラウザのタブを閉じるだけで終わりにしないよう、ここはNotebookに手順を入れました。 ゲーム制作のどこが変わりそうか 私は、これはゲーム制作の転換点になる技術だと思っています。 自分のキャラができたとき、「次はこの動きをさせたい」という要求に対して、目標を組み立てて、その途中の動きを生成する方法が使えるからです。 座る動作そのものだけでなく、そこへ向かう途中や立ち上がりまで、自分のキャラで試せるのは面白いです。 一方で、今回の苦労を見ると、キャラを動かす準備まで全部なくなったとは言えません。 モデルの骨格、重み、体格への対応は、かなり大きな仕事として残りました。 ゲームなら、当たり判定、踏みつけ、得点、失敗、入力の気持ちよさも別に設計します。 生成された人間らしい動きが、そのゲームに必要な動きと一致するかも判断が必要です。 私のTakaBounce Campusでも、まずMotionBricksで自然な動きを確かめ、そのうえで、ゲーム固有のジャンプや被弾など、必要な部分を組み合わせたいと考えています。 生成モデルと、こちらで意図して作るアクションの両方を使えると、試せることが増えそうです。 実際に操作した結果 次の画像は、今回使ったHTML画面です。 Colabで生成して保存した記録を、同じ表示コードでMac上に読み込み、着座したところで止めています。 画像の「GPU推論なし」は、スクリーンショットを撮った時点では記録を再生している、という意味です。 実際のHTML表示。視点変更、区間選択、表情などの操作を付けています。 HTMLは、Three.jsの表示領域と、キー入力や生成状態を扱うJavaScriptを組み合わせています。 そのHTMLをColabの出力欄へ表示し、Pythonの生成サーバーとつなぎました。 HTMLファイルだけで動作生成ができるわけではなく、表示用JavaScript、GLB、変換処理、生成サーバーが必要です。 最後に、実際にキーボード操作した結果の動画です。 フレーム0から、歩いて、走って、ジャンプし、椅子に座って立ち上がるところまでを切り出しています。 操作記録はColabのT4で生成したもので、掲載用の動画は保存した姿勢列をブラウザで再生してMP4へ書き出しました。 生成や操作の待ち時間は省いた連続再生なので、この動画だけからライブ操作時の遅延は評価できません。 まだ気になる姿勢はあります。 それでも、自分のキャラがキー入力に応じて動いて、椅子に座って、また立ち上がる。 これをColabのT4とブラウザで試せるところまで来たのは、やっぱりうれしいです。 使用するコードやデータには、公式に定められたライセンスの区分があります。1 参考文献 Tingwu Wang et al., MotionBricks: Scalable Real-Time Motions with Modular Latent Generative Model and Smart Primitives, ACM Transactions on Graphics, 45(4), 2026. arXiv:2604.24833, DOI:10.1145/3811334. NVlabs/motionbricks(公式実装) Google Colab FAQ 脚注 公式リポジトリでは、コード、モデル、同梱のサンプル動作でライセンスが分かれています。特にサンプル動作の説明は別途確認が必要です。自作ゲームへ組み込む際は、評価用の実験と分けて、実際に使うデータの条件を確認してください。 ↩︎

  4. Reddit · · r/comfyui · u/imlo2 · NVlabs/Sana

    Open-H3-Regenerate-2K for ComfyUI: refinement nodes, noise controls and comparison examples Hi, I put together a small experimental ComfyUI wrapper for NVIDIA’s Open-H3-Regenerate-2K. IMHO it's a bit like SoL-Refiner when it comes to output, but I decided I'll still set up a node for own tests after initial disappointment. There are already other ComfyUI options for this like Kijai's LoRA (which I think contains the refiner only?), but this one wraps NVIDIA’s published merged adapters, Sharp curve branches and learned latent upscaler into a few nodes, mainly to make experimentation easier. Main features: - Refine existing 24 fps video or native MiniMax-H3 latents. - Adjustable noise, an upscale-only mode and memory controls. - Longer clips through independent windows, which can show visible boundaries. - Example workflows, a test clip and detailed comparison images included. The attached example is 1344x768 to 2560x1440, using two steps from noise 0.5. It adds texture and definition, though faces, and small details like jewelry, lettering and small patterns can also change. The README in my repo compares upscale-only and noise 0.5 / 0.6 / 0.7. Tested on Windows with an RTX 5090 (32 GB VRAM) and 128 GB RAM. Smaller cards haven’t been validated; it does consume quite a lot RAM and VRAM, but probably runs at least on an RTX 4090, and you can dial down a few settings to try to make it fit. I'm Interested to hear how it behaves with other source material. Repo: o-l-l-i/ComfyUI-Olm-Open-H3-Regenerate-2K NVIDIA's official pages for this: nvlabs.github.io github.com/NVlabs/Sana/tree/sol-engine/models/Ope… huggingface.co

    24 points · 18 comments
  5. ボルト超えの時代、走るロボットをどう止める? GPUで9,600回の強化学習 ボルト超えの時代、走るロボットをどう止める? GPUで9,600回の強化学習 2026年8月、中国・北京の人型ロボット競技大会では、100mを8秒台で走るロボットが話題になりました。[1] 一方、ゴール後にうまく止まれずマットに激突する場面も報じられています。[3] 2026年の人型ロボット競技大会。ゴール後、防護マットへ衝突する場面。(出典:Reuters) 速く走るだけでなく、走り終えた後にどう減速するか。 これも人型ロボットにとって重要な課題です。 前回の記事では、MacBook Airで人型ロボットの歩行学習に挑戦しました。今回は学習済みの走行AIを使い、100mのゴール通過後、5m以内に安定して止まることを目指します。 今回はまず、こちらで2種類の停止ルールを定義して試します。続いて、ロボットの速度や姿勢に応じて停止方法を選べるよう、強化学習に挑戦します。 ただし、AIに止まり方を学ばせるには、シミュレータ上で何度も走行と停止を試す必要があります。そこで今回はNVIDIA A100を使い、試行錯誤を高速化します。 AIはどんな止まり方を学ぶのか。そして、GPUでその学習をどこまで速くできるのか? 実験して確認していきましょう。 ※本記事はMuJoCoによるシミュレーション実験です。北京大会の機体や事故原因を再現するものではなく、実機の安全性を検証するものでもありません。 今回試すこと 項目 内容 ロボット Unitree G1(手指付きモデル) 物理シミュレータ MuJoCo 走る・歩く・立つ動作 NVIDIAの学習済みAI「GEAR-SONIC」[2] 新たに学習するAI ゴール後の指令を選ぶPPO 計算環境 HIGHRESOのNVIDIA A100 80GBとCPU 成功条件 ゴール後5m以内で、転倒・逸脱せず2秒間ほぼ静止 本記事では、走り方は学習し直さず、停止の判断だけを学習させます。 なお、G1やMuJoCoなどの基本用語については、前回の記事をご参照ください。 1. 🤖 学習済みAIでG1を走らせる G1はロボット本体、GEAR-SONICはその動かし方を学んだAIモデルのことを指します。NVIDIAが公開したこの制御モデルに「走る(run)」「歩く(walk)」「立つ(idle)」などの動作と目標速度を渡すと、全身の関節の動かし方を計算します。 今回は、NVIDIAの公式GitHubで公開しているプログラムと、Hugging Faceで公開されている学習済みモデルを利用しました。モデルの推論はPythonから実行し、MuJoCo上のG1を動かしています。 動作計画器に渡す入力の一部は、次のとおりです。 feeds = { 直前のロボットの姿勢・関節角度 "context_mujoco_qpos": context_qpos[None].astype(np.float32), 目標速度(例:4.0m/s) "target_vel": np.array([cmd.speed], np.float32), 動作モード(run / walk / idleなど) "mode": np.array([int(cmd.mode)], np.int64), 腰の高さ指定(-1.0で無効)。ほかの入力は省略 "height": np.array([-1.0], np.float32), } 「4.0m/sで走れ」と指示すると、GEAR-SONICが各関節の動かし方を計算し、MuJoCoが実際の身体の動きを再現します。動作指令は0.1秒ごと、関節の動かし方は0.02秒ごとに更新しています。 指令速度と実際の速度は違う ただし、車の目標速度と同様、「4.0m/sで走れ」と指示しても、姿勢やモーターの制約でその速度が出るとは限りません。 指令速度 100mライン通過時の平均実速度 2.5m/s 2.02m/s 4.0m/s 3.49m/s 高速条件では最大4.19m/sを記録しましたが、大会の100m記録(8.64秒、平均約11.6m/s)には及びません。今回使用したGEAR-SONICの公式操作UIでは走行指令の上限が3.0m/sであり、実験ではこれを超える4.0m/sまで試しました。 今回は上記大会の最高速度再現ではなく、既存の走行AIでどのように停止できるかを検証していきます。 参考までに、下のGIFは停止指令を出す前の走行だけを切り出したものになります。 2.5m/sの方が幾分ジョギング気味なのがわかります。 同じseedでの走行比較。上段が2.5m/s指令、下段が4.0m/s指令。 2. 🏁 100m通過後、どう止める? ゴールは座標で判定する 今回はカメラで白線を認識させたりしません。MuJoCoから得られるG1の骨盤の前進方向の位置を使い、スタートを0m、ゴールを100mと設定しました。 if obs.along < self.goal_line: # 骨盤の前進位置が100m未満 self.phase = "cruise" # 走行を継続 ... 100m以上で停止制御に切り替え self.phase, self.t_switch, self.x_switch = "stop", obs.t, obs.along self.next_decision_t = obs.t 判定は0.1秒ごとなので、停止指令への切替は実際のライン通過から最大約0.1秒後です。実機なら、ここに画像認識や位置推定の仕組みが別途必要になります。 強化学習を使わず、まず2方式を試す まずは強化学習を使わず、こちらで停止手順を2つ定義し、比較していきましょう。 方法 ゴール後の指令 A:即座に立位指令 直後にidleへ切り替える B:段階的に減速 run → walk → slow_walk → idle idleは立位を保つための動作モードで、切り替えた瞬間に止まるわけではありません。また、走行速度をゼロに指定するだけでは足踏みが続く場合があったため、最後はidleに切り替えます。どちらの方法も、ゴール前には減速しません。 左がA(ゴール通過後ただちにidleへ切替)、右がB(run→walk→slow_walk→idle)。どちらもゴール前には減速せず、ゴール通過後の停止指令だけを変えています(2.5m/s指令・seed 1234)。 実験してみると、ゴール通過速度が平均2.02m/sの条件では、両方式とも10/10回成功。平均停止距離はAが1.15m、Bが3.59mでした。 ところが、高速条件では次の差が出ました。 4.0m/s指令・各10回 A:即座に立位 B:段階減速 5m以内で停止 9/10 8/10 転倒 1回 0回 平均停止距離 2.78m 4.57m Aでは4.19m/sで通過した試行が、停止指令の約2.15秒後に前方へ転倒しました。Bでは転倒しない一方、2回は5mを超過。短い距離で止まることと、穏やかに止まることは両立しない場合があります。 4.0m/s指令・seed 4。転倒判定時はゴール後約6.84m、滑った後の最終位置は約7.44m。 では、速度や姿勢に応じていつidleへ切り替えるか、AIに選ばせたらどうなるでしょうか? 3. 🧠 「止まり方」を強化学習する 走行AIはそのまま、判断役だけを学習 ここで使うのが、PPO(Proximal Policy Optimization) という強化学習の手法です。行動の選び方を一度に大きく変えすぎず、安定した学習を目指すのが特徴です。 走行や関節制御はGEAR-SONICに任せ、新たなAIがロボットの速度や姿勢をもとに、0.2秒ごとに次の3つの指令から選びます。 選択肢 内容 維持 現在の指令を続ける 一段階減速 runからwalkなど、次の低速モードへ進む 立位へ切替 idleに切り替える 停止制御はrun 1.5m/sから始まり、ゴール手前でPPOは操作できません。新しく学習するのは停止判断AIだけです。 PPOが動作指令を選び、GEAR-SONICが関節の動かし方を計算する。MuJoCoがその動きをシミュレーションし、停止結果に応じた報酬をもとにPPOを学習させる。 何を見て、何を褒める? PPOには、ロボットの位置・速度・姿勢などを入力し、停止結果に応じて報酬を与えます。 区分 項目 内容 入力 位置・速度 ゴール後の距離、横位置、前後・左右の速度 入力 姿勢 胴体の前後・左右の傾き、回転速度 入力 動作状態 現在の減速段階、経過時間 報酬 安定停止 5m以内で2秒間ほぼ静止:+10点 報酬 転倒 −15点 報酬 その他の失敗 コース逸脱・5m超過・時間切れ:各−10点 減点 急減速 最大減速度が2.0m/s²を超える 減点 急な速度変化 ジャークが5.0m/s³を超える 減点 姿勢の崩れ 胴体の傾きが15°を超える 減点 停止時間・距離 3秒・4mを超えると、それぞれ減点 ※各減点の上限は−2点です。安定停止は平均速度0.05m/s未満が2秒続くことを指します。 まず5m以内で安定して止まることを優先し、そのうえで急減速や姿勢の崩れ、停止に時間・距離がかかりすぎることを抑える設計です。 毎回100mを走り直さない 停止だけを練習したいのに、毎回100mの助走から始めるのは非効率です。そこで、先に走らせたゴール直後の状態を保存し、その地点から停止部分だけを繰り返しました。 保存するのは位置や速度だけでなく、GEAR-SONICの動作計画や履歴も含む状態です。これにより、100mの助走を毎回繰り返さず、ゴール通過直後の118種類の状態から停止だけを学習できます。 一方、最終評価では未使用の20種類の条件で、スタートから100mを走らせて停止性能を確認します。 助走を一度記録すれば、その後は停止部分だけを反復できる。 4. ⚡ A100で9,600回学習させたら? 強化学習の試行回数と実験条件 今回は、学習の進み方と計算時間を確認するため、96試行を1セットとして100セット、計9,600回の停止試行を行いました。 9,600回は最適な回数として導いたものではなく、まず学習の傾向を調べるために設定した回数です。 GPUが担当する処理 CPU上で24個のMuJoCoシミュレーションを並列実行し、ロボットの動きを物理計算します。一方、各関節の動かし方を求めるGEAR-SONICのAI推論はA100が担当します。 24個のプロセスが1枚のGPUを効率よく共有するため、CUDA MPSを使用。停止試行を繰り返してデータを集め、PPOの学習更新もGPUで行います。 CPUで物理シミュレーション、GPUでAI推論を分担。A100による高速化の主な要因は、GEAR-SONICの推論を効率よく並列処理できること。 17.5分で、仮想の停止動作12.1時間分 A100+MPSでは、9,600試行の学習が17.5分で終了しました。試行中にシミュレータ内で進んだ時間は合計43,409秒(約12.1時間)。これは実際の待ち時間ではなく、各ロボットの停止動作を足した仮想時間で、100mの助走は含んでいません。 左上:報酬、右上:停止成功率、左下:停止距離、右下:転倒率。報酬は学習序盤に改善しましたが、成功率は当初から高く、停止距離はむしろ長くなりました。 GPUで停止AIの学習は約3倍速くなる CPUだけで実行する場合と、GPU(A100)を使う場合で、96回の停止試行とPPOの更新にかかる時間を比較しました。 使用したサーバーは、CPUがIntel Xeon Silver 4310(12コア/24スレッド、2.10GHz)、GPUがNVIDIA A100 80GB、メモリ約251GiBです。いずれも24プロセスで計測しました。 計算方法 96試行+更新の1セット 100セット CPUのみ 25.9秒 約54分(推定) A100・MPSなし 45.3秒 約93分(推定) A100+MPS 8.5秒 17.5分(実測) A100+MPSでは、CPUのみと比べて約3倍高速化しました。一方、MPSなしではGPUを使っても遅くなりました。 これは、24個のプロセスからGPUへ頻繁に推論を依頼する際、処理待ちや切り替えの負荷が生じるためと考えられます。CUDA MPSは複数プロセスのGPU処理を効率よく実行する仕組みで、今回の高速化にはこれが重要でした。 左から①シミュレーション処理速度、②PPOの更新時間、③1セットの処理時間、④100セットの総時間。GPUの効果は主にGEAR-SONICの推論にあり、PPOの更新自体はCPUの方が速い結果でした。なお、100セットのCPU時間は短時間計測からの推定値です。 5. 🏃 学習した止まり方はどう変わった? ここでは、ゴール後の止まり方を決める3つの方法を比べます。 2つは人手で決めたルール、もう1つは強化学習で学んだ方法です。 A:即 idle … ゴール通過後、すぐ立位モードに切り替える B:段階減速 … run → walk → slow_walk → idle と段階的に切り替える PPO … 学習した停止判断AIが、0.2秒ごとに次の指令を選ぶ 未使用の20 seedを使い、スタートから100m走らせて、この3方式を比較しました。 左から、A:即 idle、B:段階減速、PPO。ゴール通過時は約4.10m/sであり、3つの止まり方の違いを比較した。 指標 即idle 段階減速 PPO 5m以内停止まで成功 18/20 18/20 18/20 平均停止距離 2.34m 4.28m 3.07m 平均停止時間 3.04秒 3.89秒 2.59秒 ピーク減速度 3.19m/s² 2.23m/s² 2.56m/s² ピークジャーク 8.26m/s³ 5.86m/s³ 5.85m/s³ 最大胴体傾斜 17.0° 13.9° 11.8° 成功数は3方式とも18/20。 残る2件はゴール前のコース逸脱と転倒です。停止距離などの平均は、逸脱後も走り切った1件を含む19試行で集計しています。 PPOは成功率を上げませんでしたが、即idleより減速が穏やかで、段階減速より短時間で止まりました。 なお、学習前後を比較すると、PPOは停止時の急減速や姿勢の崩れを抑える方向に変化しました。ただし、停止距離は長くなっており、学習によってすべての指標が改善したわけではありません。 AIが学んだのは「約1秒後に立位へ切り替える」 PPOは、ゴール通過後に目標速度1.5m/sの低速走行を指示し、19試行中14回は1.0秒後、残る5回は0.8秒後にidleへ切り替えました。実際の速度はその間も低下し、平均3.07mで停止しました。 左上:切替時刻とゴール通過速度。右下:切替時刻と骨盤の傾き。速度との明確な関係はなく、一部の試行では姿勢に応じて早めに切り替えています。 固定で1秒後にidleへ切り替えるルールと比べても、19試行中14回は同じ動作となり、平均停止距離の差は約0.06mでした。今回の条件では、PPOが単純な固定ルールを大きく上回ったとは言えません。 一方、PPOはロボットの姿勢に応じて停止タイミングを変える動作も学習しました。こうした状況に応じた判断を、人手で細かなルールを定義せずに獲得できることは、強化学習の利点です。 6. 🔍 まとめ 今回、学習済みのGEAR-SONICを利用し、走行動作を学習し直さず、停止判断だけを強化学習できました。 学習したPPOは、ルールベースでの即idleより急減速を抑え、段階減速より短時間で停止しました。ただし、停止成功率はどの方法も18/20で、固定1秒ルールと比べた優位性も限定的でした。 一方、A100+CUDA MPSでは9,600回の停止試行を17.5分で学習し、CPUのみと比べて1セット当たり約3倍高速化しました。GPUの価値は、停止性能を直接高めることではなく、試行条件や報酬を変えながら改善を繰り返す時間を短縮できることにあります。 今回はシミュレータ上でゴール位置を把握できましたが、実際のロボットでは、カメラ映像などから周囲の状況を認識し、判断する必要があります。 今後は、視覚情報をもとに周囲の状況を理解し、行動につなげるVLA(Vision-Language-Action)モデルなど、より高度なロボットAIの実験にも取り組んでいく予定です。 この記事を書いた人 おむ 画像認識・LLMを中心に、AIシステムの開発や技術検証に取り組むAIエンジニア。 参考資料 [1] IT之家「天工Ultraの100m決勝8.64秒」 ithome.com (大会の機体は本実験と異なる) [2] Luo et al., SONIC: Supersizing Motion Tracking for Natural Humanoid Whole-Body Control, arxiv.org 。公開モデル:huggingface.co 、公式実装:NVlabs/GR00T-WholeBodyControl [3] Reuters, After outrunning Bolt, China's robot champion races towards real-world work, reuters.com

  6. C-RADIOv4: A Distilled Vision Foundation Model for FiftyOne !image.mux.com Introduction The field of computer vision has seen remarkable progress with vision foundation models that excel at specific tasks—CLIP for vision-language alignment, DINOv3 for dense perception, SAM3 for segmentation. But what if you could distill the best of these foundation models into a single, unified architecture? That's exactly what C-RADIOv4 achieves. C-RADIOv4 is the latest release in NVIDIA Labs' agglomerative vision foundation model family. Through innovative multi-teacher distillation, it creates a unified student model that retains and improves upon the distinct capabilities of multiple state-of-the-art teachers: SigLIP2, DINOv3, and SAM3. In this blog post, we'll explore what makes C-RADIOv4 special, dive into its technical innovations, and show you how to leverage its powerful capabilities in FiftyOne for computer vision workflows. What are foundation models? Foundation models are large, pretrained models that learn broad, reusable representations from massive datasets and can be adapted to many downstream tasks with little or no task-specific training. What is C-RADIOv4? C-RADIOv4 is an agglomerative foundation model that learns from multiple teacher models simultaneously. Instead of training on labeled data, it distills foundation model knowledge from three cutting-edge vision models: - SigLIP2: The frontier text-image foundation encoder, providing enhanced zero-shot classification capabilities - DINOv3: A self-supervised learning powerhouse that delivers strong dense perception and semantic segmentation - SAM3: The latest iteration of Segment Anything Model, enabling powerful segmentation capabilities The result? A single vision language model that combines text-image alignment, dense perception, and segmentation—all while maintaining competitive performance at a fraction of the parameters of its teachers. Get started with C-RADIOv4 → C-RADIOv4: Vision foundation model variants C-RADIOv4 comes in two variants: !cdn.sanity.io Both foundation models achieve impressive results: - Zero-shot accuracy: 83.09% (H) and 82.01% (SO400M) on ImageNet-1K - kNN accuracy: 86.59% (H) and 85.76% (SO400M) on ImageNet-1K - Semantic segmentation: 55.20 mIoU (H) and 55.14 mIoU (SO400M) on ADE20k Remarkably, C-RADIOv4-H achieves performance competitive with DINOv3-7B (which has 6.7B parameters) on dense tasks, despite having an order of magnitude fewer parameters. C-RADIOv4: Key technical innovations for vision foundation models 1. Stochastic resolution training Previous RADIO vision foundation models trained at just two resolutions, which could lead to inconsistent behavior at inference time—a phenomenon called "mode switching." C-RADIOv4 solves this by training across a wide range of resolutions: - Low-resolution partition: {128, 192, 224, 256, 384, 432} pixels - High-resolution partition: {512, 768, 1024, 1152} pixels This enables smooth resolution scaling and substantial quality improvements at low resolutions. The model demonstrates strong robustness even at resolutions higher than those it was trained on, achieving 57.72 mIoU at 1536px on ADE20k. 2. Shift equivariance One challenge in foundation model distillation is that students can learn not just useful features, but also fixed-pattern noise from teachers. C-RADIOv4 addresses this with two forms of shift equivariance: - Shift Equivariant Loss: Randomly shifts crops for both student and teachers independently, preventing the model from learning position-dependent artifacts - Shift Equivariant MESA: Applies exponential moving average matching with different crops, further reducing fixed-pattern noise These techniques ensure the model learns robust, semantically meaningful features rather than spurious patterns. 3. ViTDet mode for high-resolution efficiency For high-resolution inference, C-RADIOv4 supports "ViTDet mode," which uses windowed attention instead of full global attention. This dramatically reduces inference time: - The SO400M variant with ViTDet window size ≤ 12 is faster than SAM3's encoder - ViT-H with window size 8 is nearly as fast as SAM3 - Latency scales much more favorably with resolution compared to full attention This makes C-RADIOv4 practical for real-world applications requiring high-resolution processing. 4. Balanced summary loss Different teachers produce summary features with different angular dispersions. Without normalization, teachers with larger dispersion would dominate the loss. C-RADIOv4 uses an angular loss formulation that normalizes for each teacher's cone radius, ensuring balanced learning from all teachers. Getting started with C-RADIOv4 in FiftyOne FiftyOne provides seamless integration with C-RADIOv4, making it easy to leverage these powerful capabilities in your computer vision workflows. Installation First, install FiftyOne and register the C-RADIOv4 model source: # Install FiftyOne pip install fiftyone # Register the RADIO model source import fiftyone.zoo as foz foz.register_zoo_model_source( "https://github.com/harpreetsahota204/CRADIOv4", ) Quick start: Computing embeddings The most common use case is extracting image embeddings for similarity search, clustering, and visualization: import fiftyone as fo import fiftyone.zoo as foz # Load your dataset dataset = foz.load_zoo_dataset("quickstart", shuffle=True) # Load the C-RADIOv4 model model = foz.load_zoo_model("nv_labs/c-radio_v4-h") # Compute embeddings with efficient batching dataset.compute_embeddings( model=model, embeddings_field="radio_embeddings", batch_size=16, # Adjust based on GPU memory num_workers=4 # Parallel data loading ) # Launch the FiftyOne App to explore session = fo.launch_app(dataset) Model configuration options C-RADIOv4 offers flexible configuration for different use cases: # Global image embeddings (default) model = foz.load_zoo_model( "nv_labs/c-radio_v4-h", output_type="summary", # Global semantic features feature_format="NCHW" # or "NLC" ) # Spatial attention features spatial_model = foz.load_zoo_model( "nv_labs/c-radio_v4-h", output_type="spatial", # Patch-level spatial features feature_format="NCHW", # Required for spatial apply_smoothing=True, # Gaussian smoothing for cleaner heatmaps smoothing_sigma=1.51 # Smoothing strength ) C-RADIOv4: Practical use cases for vision foundation models 1. Embedding visualization with UMAP Create beautiful 2D visualizations of your image embeddings to understand dataset structure: import fiftyone.brain as fob # Compute embeddings first dataset.compute_embeddings( model=model, embeddings_field="radio_embeddings" ) # Create UMAP visualization results = fob.compute_visualization( dataset, method="umap", # Also supports "tsne", "pca" brain_key="radio_viz", embeddings="radio_embeddings" ) # Explore in the App session = fo.launch_app(dataset) The visualization reveals clusters of similar images, making it easy to identify patterns and outliers in your dataset. 2. Similarity search Build powerful similarity search capabilities: import fiftyone.brain as fob # Build similarity index results = fob.compute_similarity( dataset, backend="sklearn", brain_key="radio_sim", embeddings="radio_embeddings" ) # Find similar images sample_id = dataset.first().id similar_samples = dataset.sort_by_similarity( sample_id, brain_key="radio_sim", k=10 # Top 10 most similar ) # View results session = fo.launch_app(similar_samples) This is incredibly useful for: - Finding duplicate or near-duplicate images - Discovering similar content for data augmentation - Building recommendation systems - Quality control and anomaly detection 3. Spatial attention heatmaps Visualize what regions of an image the model focuses on using spatial attention features: # Load spatial model with smoothing spatial_model = foz.load_zoo_model( "nv_labs/c-radio_v4-h", output_type="spatial", apply_smoothing=True, smoothing_sigma=1.51, feature_format="NCHW" ) # Generate attention heatmaps dataset.apply_model( spatial_model, "radio_heatmap", batch_size=16, num_workers=4 ) # View heatmaps in FiftyOne App session = fo.launch_app(dataset) The heatmaps use PCA visualization (as described in the C-RADIOv4 paper) to show object boundaries and regions of interest. This is particularly useful for: - Understanding model behavior - Debugging and interpretability - Identifying important image regions - Quality assessment 4. Dataset curation: Uniqueness and representativeness Use embeddings to score how unique or representative each sample is: import fiftyone.brain as fob # Compute uniqueness scores fob.compute_uniqueness( dataset, embeddings="radio_embeddings" ) # Compute representativeness scores fob.compute_representativeness( dataset, representativeness_field="radio_represent", method="cluster-center", embeddings="radio_embeddings" ) # Find most representative samples representative_view = dataset.sort_by("radio_represent", reverse=True) These scores help with: - Active learning: Select diverse samples for labeling - Dataset balancing: Identify underrepresented regions - Data cleaning: Find outliers and edge cases - Efficient annotation: Prioritize representative samples 5. Duplicate detection Automatically find and remove near-duplicate images: import fiftyone.brain as fob # Detect duplicates using embeddings results = fob.compute_uniqueness( dataset, embeddings="radio_embeddings" ) # Filter to most unique samples unique_view = dataset.sort_by("uniqueness", reverse=True) This is essential for: - Cleaning datasets before training - Reducing storage costs - Improving dataset quality - Preventing data leakage in train/test splits Advanced workflows for vision foundation models Comprehensive analysis pipeline Combine multiple C-RADIOv4 outputs for thorough dataset analysis: # Step 1: Global embeddings for similarity embedding_model = foz.load_zoo_model("nv_labs/c-radio_v4-h") dataset.compute_embeddings(embedding_model, "radio_embeddings") # Step 2: Spatial heatmaps for attention analysis spatial_model = foz.load_zoo_model( "nv_labs/c-radio_v4-h", output_type="spatial", apply_smoothing=True, smoothing_sigma=0.8 ) dataset.apply_model(spatial_model, "radio_heatmap") # Step 3: Build similarity index import fiftyone.brain as fob fob.compute_similarity(dataset, embeddings="radio_embeddings", brain_key="radio_sim") # Step 4: Compute additional metrics fob.compute_uniqueness(dataset, embeddings="radio_embeddings") fob.compute_representativeness(dataset, embeddings="radio_embeddings") # Step 5: Comprehensive exploration session = fo.launch_app(dataset) This pipeline gives you: - Similarity search for finding related images - Attention visualization for understanding model focus - Uniqueness scores for identifying outliers - Representativeness scores for dataset balancing - Interactive exploration in the FiftyOne App Performance optimization for vision foundation models Batch processing For optimal performance on large datasets, use batching with parallel data loading: dataset.compute_embeddings( model=model, embeddings_field="radio_embeddings", batch_size=16, # Adjust based on GPU memory num_workers=4 # Parallel data loading workers ) Recommended batch sizes by GPU: - RTX 3090/4090 (24GB): batch_size=16-32 - A100 (40GB/80GB): batch_size=32-64 - Smaller GPUs: batch_size=4-8 GPU acceleration C-RADIOv4 automatically uses GPU acceleration with mixed precision (bfloat16) on compatible hardware (Ampere+). The vision foundation model automatically handles: - Device placement (GPU/CPU) - Mixed precision inference - Efficient memory management High-resolution processing For high-resolution images, consider using the SO400M variant with ViTDet mode enabled (when available through the API) for faster inference: # Use smaller model for faster inference model = foz.load_zoo_model("nv_labs/c-radio_v4-so400m") Real-world applications for vision foundation models C-RADIOv4 has been successfully deployed in various domains: - Autonomous Vehicles: Dense perception for scene understanding - Robotics: Visual navigation and manipulation - Document Processing: OCR and document parsing (Nemotron Parse) - Open Vocabulary Segmentation: RADSeg uses RADIO for state-of-the-art segmentation - Vision-Language Models: Used as vision encoder in Nemotron Nano V2 VL The vision foundation model's permissive license (NVIDIA Open Model License Agreement) makes it suitable for both research and commercial applications. Why C-RADIOv4? Unified capabilities Instead of maintaining separate models for different tasks, C-RADIOv4 provides: - Zero-shot classification (from SigLIP2) - Dense perception (from DINOv3) - Segmentation capabilities (from SAM3) All in a single, efficient model. Efficiency With 631M parameters (H variant) or 412M parameters (SO400M variant), C-RADIOv4 achieves performance competitive with models having 10x more parameters, making it practical for deployment. Flexibility - Works across a wide range of resolutions (128px to 1152px+) - Supports both global embeddings and spatial features - Can replace SAM3's vision encoder for segmentation tasks - ViTDet mode enables efficient high-resolution processing Quality The vision foundation model demonstrates: - Cleaner object boundaries (as shown in PCA visualizations) - Strong resolution scaling properties - Robust performance across diverse benchmarks - Reduced fixed-pattern noise compared to individual teachers Foundation model distillation and the road ahead for vision models C-RADIOv4 represents a significant advancement in agglomerative vision foundation models. By combining the strengths of SigLIP2, DINOv3, and SAM3 through innovative foundation model distillation techniques, it delivers a unified model that's both powerful and efficient. The integration with FiftyOne makes it easy to leverage these capabilities for: - Dataset exploration and visualization - Similarity search and duplicate detection - Attention visualization and interpretability - Dataset curation and active learning - Quality control and anomaly detection Whether you're working on autonomous vehicles, robotics, document processing, or any computer vision application, C-RADIOv4 provides a solid foundation for your workflows. Resources - GitHub Repository: CRADIOv4 FiftyOne Integration - NVIDIA RADIO GitHub: Original Implementation - Hugging Face Models: C-RADIOv4 Models - Technical Report: C-RADIOv4 Tech Report - FiftyOne Documentation: docs.voxel51.com Citation If you use C-RADIOv4 in your research, please cite: @misc{ranzinger2026cradiov4, title={C-RADIOv4 (Tech Report)}, author={Mike Ranzinger and Greg Heinrich and Collin McCarthy and Jan Kautz and Andrew Tao and Bryan Catanzaro and Pavlo Molchanov}, year={2026}, eprint={2601.17237}, archivePrefix={arXiv}, primaryClass={cs.CV}, url={https://arxiv.org/abs/2601.17237}, } Ready to get started? Install FiftyOne, register the C-RADIOv4 model source, and begin exploring your datasets with this powerful unified vision foundation model! Get started →

  7. Regenerate Minimax H3 videos in 2K in just 3 steps. It does tend to change details and faces though. github.com/NVlabs/Sana/tree/sol-engine/models/Ope… t.co

    67 likes · 8 reposts · 2,635 views
  8. 🚀 Open-H3-Regenerate-2K: 3-Step Video Regeneration, Native Output up to 4K 📝 Blog: nvlabs.github.io 💻 Code: github.com/NVlabs/Sana/tree/sol-engine/models/Ope… 🤗 HF Weights: huggingface.co t.co

    97 likes · 8 reposts · 3,690 views
  9. MotionBricks by Nvidia, a new AI that generates realistic human and robot movements in real time NVlabs/motionbricks t.co

    133 likes · 3 reposts · 4,034 views
  10. LongLive Long video generation and world-action modeling research from NVIDIA. Each project has its own directory, code, documentation and model weights. NVlabs/LongLive

Trending awards, every completed day and week
Gold
11st place finishes
Silver
32nd place finishes
Bronze
43rd place finishes
Awarded repositories
5Owned by NVlabs now

Repositories

Ordered by gold, then silver, then bronze.

  1. stylegan3Best: 1st by stars, 394 stars110
  2. SPADEBest: 2nd by stars, 721 stars011
  3. stylegan2Best: 2nd by stars, 274 stars011
  4. instant-ngpBest: 3rd by stars, 427 stars001
  5. moderngpuBest: 3rd by stars, 146 stars001

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.