はじめに:ASAPフレームワークとnuScenesデータセット
ASAP(Autonomous-driving StreAming Perception)は、自動運転シナリオ向けに設計された効率的な時系列知覚自動アノテーションパイプラインです。このフレームワークの主要な目的は、自動運転データセットにおけるセンサーのサンプリング周波数と手動アノテーションの周波数との間に存在する大きな隔たりを解消することにあります。
nuScenesのような主要なデータセットでは、LiDARセンサーは20Hzという高頻度でデータを収集しますが、アノテーションコストを抑えるため、公式には2Hz(毎秒2フレーム)のキーフレームのみに手動アノテーションが提供されています。これは、センサーデータの90%(中間フレーム、またはSweeps)が教師なし状態であり、データの時系列的な価値が大きく失われていることを意味します。
ASAPは、高頻度アノテーションを生成するために二つの主要な戦略を提供します。
- 基本補間戦略 (Interp): これは最もシンプルかつ迅速な手法であり、前後のキーフレームのアノテーション情報を直接利用し、線形補間によって中間フレームの物体位置と姿勢を推定します。計算量が非常に少なく、精度要件が低い場合やベンチマークとしての利用に適しています。
- 高度時系列知覚戦略 (Advanced): ASAPの中核をなす貢献です。以下の3つの主要な段階で構成されます。
- 初期補間(Initial Interpolation): キーフレームのアノテーション情報を基に、線形補間を通じて中間フレームの粗い擬似ラベルを生成します。
- 時系列検出と関連付け(Temporal Detection & Association): キーフレームで事前学習された3D検出器(ASAPではCenterPointを使用)を用いて全フレームを推論し、IDベースの時系列データベースを構築することで、補間によって生じる剛体運動の誤差を修正します。
- 高頻度アノテーション生成(High-Frequency Generation): 補間された軌跡と検出結果を組み合わせ、カルマンフィルタリングや最適化アルゴリズムを通じて、最終的にフルフレームレート(例:12Hzまたは20Hz)の高品質な3Dアノテーションボックスを生成します。
ASAPを利用することで、nuScenesデータセットのアノテーション密度を最大6倍向上させ、モデルの動的物体に対する知覚能力を大幅に強化することが可能です。
nuScenesデータセットの構造
ASAPプロジェクトをデプロイする前に、nuScenesデータセットのファイル構成、特にsamplesとsweepsの違いを理解することが重要です。
データセットバージョン
- v1.0-mini: データセットのミニサブセットで、10のシーンのみが含まれます。主にコードのデバッグやプロセスの検証に使用されます。本記事ではminiセットを例に全体フローを説明します。
- v1.0-trainval: 完全なデータセットで、700のトレーニングシーンと150の検証シーンを含み、正式なモデル学習に使用されます。
ディレクトリ構造
ASAPは、データ読み込みにおいて公式のディレクトリ構造に厳密に依存します。データが以下の規範(例:UniScene_Storage)に従って配置されていることを確認してください。
/root/autodl-tmp/UniScene_Storage/data/nuscenes/
├── maps/ # 高精度地図データ
├── samples/ # [重要] キーフレームデータ (Keyframes)、公式アノテーションあり (2Hz)
│ ├── CAM_FRONT/
│ ├── LIDAR_TOP/
│ └── ...
├── sweeps/ # [重要] 中間フレームデータ (Intermediate Frames)、公式アノテーションなし (20Hz)
│ ├── CAM_FRONT/
│ ├── LIDAR_TOP/
│ └── ...
├── v1.0-mini/ # 各種メタデータJSONファイルを含む (instance.json, sample.json など)
└── v1.0-trainval/ # 完全なデータセットを使用する場合
主要概念の区別:
- Keyframe (Sample): 公式の真値アノテーションを持つフレーム。0.5秒ごとに1フレームです。
- Sweep: 2つのKeyframe間に位置する中間フレーム。ASAPの目的は、これらのSweepにアノテーションを付与し、Sampleとして扱えるようにすることです。
環境構築と依存関係の管理
ASAPプロジェクトのコードベースは比較的新しくないため、新しいMMDetection3D(v1.x/MMEngine)に無理に適合させると、多数のAPI非互換性の問題が発生します。実用的な経験に基づくと、**ダウングレード戦略**を適用し、独立した環境を構築するのが最も堅実な方法です。
基本環境構築
Condaを用いた環境管理を推奨します。Pythonバージョンは3.7または3.8に固定し、CUDAバージョンは11.1または11.3が推奨されます。
# 現在 /root ディレクトリにいると仮定
git clone https://github.com/JeffWang987/ASAP.git
cd ASAP
# conda仮想環境を作成
# 注意:python=3.7 を指定することが必須です。そうしないと、後続のnumbaおよびnuscenes-devkitのインストールで互換性の問題が発生する可能性があります。
conda create -n ASAP python=3.7 -y
conda activate ASAP
# nuScenesデータセットを処理するための中核開発パッケージであるnuscenes-devkitをインストールします。
pip install nuscenes-devkit
# PyTorchをインストールします (CUDA 11.1 の例)
# 実測によると、PyTorch 1.9.0 と CUDA 11.1 の組み合わせが最も安定しています。
# 物理マシンのCUDAドライバーバージョンが高い場合でも、condaは自動的に互換性を保ちます。
conda install pytorch==1.9.0 torchvision==0.10.0 cudatoolkit=11.1 -c pytorch -c conda-forge
MMDetection3Dエコシステムのインストール
これは環境設定で最も間違いやすい部分です。OpenMMLab系列のライブラリは厳密なバージョン対応関係があり、バージョンが合致しないとRuntimeErrorや演算子の欠落が発生します。mmcv-full、mmdet、mmseg、およびmmdet3dが互換性を持つように、以下の順序とバージョンに厳密に従ってインストールする必要があります。
# 1. openmimツールをインストール
# MIMはOpenMMLabのパッケージ管理ツールで、プリコンパイル済みパッケージのダウンロードを支援します。
pip install openmim
# 2. mmcv-fullをインストール (mmdet3d 0.17.x に対応する最適なバージョン、1.4.0必須)
# 警告:mmcv-fullをインストールしてください。mmcv(軽量版)はインストールしないでください。そうしないとCUDA演算子が実行できません。
# バージョンは1.4.0に固定します。これはmmdet3d 0.17.x に対応する最適なバージョンです。
pip install mmcv-full==1.4.0 -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.9.0/index.html
# 3. mmsegmentationをインストール (バージョン >=0.20.0 かつ <1.0.0 が必要、依存関係の衝突を避けるため0.20.2を推奨)
pip install mmsegmentation==0.20.2
# 4. mmdetectionをインストール (バージョン >=2.24.0 かつ <3.0.0 が必要、2.28.2を推奨)
pip install mmdet==2.28.2
# 5. MMDetection3D 0.17.3をソースからインストールし、互換性を確保します。
git clone https://github.com/open-mmlab/mmdetection3d.git -b v0.17.3
cd mmdetection3d
pip install -v -e . # -e はeditableモードで、デバッグに便利です。
cd ..
# 6. spconvをインストール (CenterPointが必須とする依存関係で、CUDAバージョンに応じて選択)
pip install spconv-cu111 # CUDA 11.3 の場合は spconv-cu113 をインストール
# numbaバージョン問題の修正 (Python 3.7環境)
# 以前の環境と新しいnumbaにはAPIの衝突があるため、バージョンをロックする必要があります。
pip install numba==0.56.4
環境検証と留意事項
上記の手順を完了した後、各コンポーネントのバージョンが正しく、Pythonインタープリタによって認識されていることを確認するために、環境検証を行うことを強く推奨します。
1. バージョン確認コマンド
ターミナルで以下のPythonコードを実行し、出力されるバージョン番号が期待通りか確認します。
python -c "
import torch
print(f'PyTorch: {torch.__version__}, CUDA: {torch.version.cuda}')
import mmcv
print(f'MMCV: {mmcv.__version__}')
import mmdet
print(f'MMDetection: {mmdet.__version__}')
import mmdet3d
print(f'MMDetection3D: {mmdet3d.__version__}')
import mmseg
print(f'MMSegmentation: {mmseg.__version__}')
"
期待される出力:
- PyTorch: 1.9.0, CUDA: 11.1
- MMCV: 1.4.0
- MMDetection: 2.28.2
- MMDetection3D: 0.17.3
- MMSegmentation: 0.20.2
2. 重要な留意事項
- MMCVの選択: システムに
mmcv(fullサフィックスなしのパッケージ)がインストールされていないことを必ず確認してください。pip list | grep mmcvでmmcvとmmcv-fullが両方表示される場合は、pip uninstall mmcvを実行してアンインストールし、mmcv-fullのみを残してください。 - MMEngineについて:
mmengineライブラリのインストールは厳禁です。これはOpenMMLab 2.0アーキテクチャの中核であり、本記事で使用する1.0アーキテクチャとは互換性がありません。誤ってインストールした場合は、必ずアンインストールしてください。 - Numpyについて: 実行中に
ImportError: numpy.core.multiarray failed to importというエラーが発生した場合、通常はnumbaのバージョンによってnumpyのバージョンが変更されたことが原因です。numpyを1.21.6にダウングレードしてみてください (pip install numpy==1.21.6)。
データセットの準備とパスの指定
nuScenesデータセットは、公式のディレクトリ構造に従う必要があります。
ディレクトリ構造の例:
/root/autodl-tmp/UniScene_Storage/data/nuscenes/
├── maps/
├── samples/
├── sweeps/
├── v1.0-mini/
└── ...
ASAP実行フローとスクリプト詳細
ASAPのワークフローは主に4つの段階に分けられます:20Hz入力情報の生成 -> オブジェクト検出推論 -> 時系列データベースの構築 -> 最終アノテーションの生成。
ステップ1:20Hz LiDAR入力情報の生成 (Input Generation)
スクリプトパス:scripts/nusc_20Hz_lidar_input_pkl.sh
機能:元の低周波数(2Hz)のキーフレームを補間し、20Hzの高周波数フレームメタデータ(.pklファイル)を生成します。
変更ガイド
スクリプトを開き、data_pathとdata_versionを修正します。
PYTHONPATH="$(dirname $0)/..":$PYTHONPATH
# 1. data_path を変更
# 注意:「nuscenes」の層まで記述してください。「v1.0-mini」以下は含めないでください。
# ファイルが見つからない問題を避けるため、絶対パス(/ で始まるパス)を使用してください。
data_path="/root/autodl-tmp/UniScene_Storage/data/nuscenes"
# data_path="./data/nuscenes"
# 2. data_version を変更
# デフォルトのtrainvalをminiに変更
data_version="v1.0-mini"
# data_version="v1.0-trainval"
PY_ARGS=${@:1}
OUT_DIR="./out/"
LOG_DIR=$OUT_DIR/'lidar_20Hz'
if [ ! -d $LOG_DIR ]; then
mkdir -p $LOG_DIR
fi
python -m sAP3D.nusc_20Hz_lidar_input_pkl \
--data_path $data_path \
--data_version $data_version \
$PY_ARGS | tee -a $LOG_DIR/log.txt
実行コマンド
bash scripts/nusc_20Hz_lidar_input_pkl.sh
出力:ASAP/out/lidar_20Hz/20Hz_lidar_infos_val.pkl
ステップ2:CenterPoint推論 (Inference)
機能:事前学習済みのCenterPointモデルを利用し、上記で生成された20Hzフレームに対して推論を行い、初期の検出ボックスを取得します。
1. 重みのダウンロード
CenterPoint Voxel 0.075 + DCNバージョン(mAP 56.92 / NDS 65.27)の事前学習済み重みをダウンロードします。これは公式提供されている中で最も強力なモデルの一つです。ASAPディレクトリ内で直接ダウンロードするコマンドを以下に示します(CenterPointリポジトリから手動でダウンロードすることも可能です)。
# 1. 重みファイルを保存するディレクトリを作成
mkdir -p assets/ckpts
# 2. 重みをダウンロードし、full_centerpoint.pth にリネーム
wget https://download.openmmlab.com/mmdetection3d/v1.0.0_models/centerpoint/centerpoint_0075voxel_second_secfpn_dcn_circlenms_4x8_cyclic_20e_nus/centerpoint_0075voxel_second_secfpn_dcn_circlenms_4x8_cyclic_20e_nus_20220810_025930-657f67e0.pth -O assets/ckpts/full_centerpoint.pth
2. 設定ファイルの修正
ファイルパス:assets/centerpoint_20Hz_lidar_input.py
このファイルはmmdet3dの設定に基づいており、ローカル環境に合わせてパスを修正する必要があります。
# data_root を修正 (文字列先頭のスペースを削除することに注意)
data_root = '/root/autodl-tmp/UniScene_Storage/data/nuscenes/'
# ann_file を修正 (train, val, test の3箇所すべてを絶対パスに修正)
# ステップ1で生成したpklファイルを指すようにします。
ann_file = '/root/ASAP/out/lidar_20Hz/20Hz_lidar_infos_val.pkl'
3. 推論コマンドの実行
mmdetection3d/tools/test.pyを呼び出して推論を実行します。mmdet3d v0.17.3の標準パラメータを使用します。
# ASAPルートディレクトリで実行してください
python mmdetection3d/tools/test.py \
assets/centerpoint_20Hz_lidar_input.py \
assets/ckpts/full_centerpoint.pth \
--format-only \
--eval-options jsonfile_prefix=work_dirs/centerpoint_20hz_mini/
出力:work_dirs/centerpoint_20hz_mini/pts_bbox/results_nusc.json
ステップ3:時系列データベースの構築 (Temporal Database)
スクリプトパス:scripts/nusc_20Hzlidar_instance-token_generator.sh
機能:推論によって得られた検出ボックスにグローバルに一意なinstance_tokenを割り当て、フレームを跨ぐ時系列関連付けを確立します。
変更と実行
スクリプトを開き、data_pathとdata_versionを修正します。
PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \
# 1. data_path を変更
# 注意:「nuscenes」の層まで記述してください。「v1.0-mini」以下は含めないでください。
# ファイルが見つからない問題を避けるため、絶対パス(/ で始まるパス)を使用してください。
data_path="/root/autodl-tmp/UniScene_Storage/data/nuscenes"
# data_path="./data/nuscenes"
# 2. data_version を変更
# デフォルトのtrainvalをminiに変更
data_version="v1.0-mini"
# data_version="v1.0-trainval"
PY_ARGS=${@:1}
OUT_DIR="./out/"
LOG_DIR=$OUT_DIR/'lidar_20Hz'
if [ ! -d $LOG_DIR ]; then
mkdir -p $LOG_DIR
fi
python -m sAP3D.nusc_lidar20Hz_instance-token_generator \
--data_path $data_path \
--data_version $data_version \
$PY_ARGS | tee -a $LOG_DIR/instance_token_generator.txt
スクリプトの内容を修正した後、前のステップで生成されたJSONパスを直接コマンドラインに渡して実行します。
bash scripts/nusc_20Hzlidar_instance-token_generator.sh \
--lidar_inf_rst_path work_dirs/centerpoint_20hz_mini/pts_bbox/results_nusc.json
出力:通常、.work_dirs/centerpoint_20hz_mini/pts_bbox/results_nusc_with_instance_token.jsonに生成されます(スクリプトの出力ログによって異なる場合があります)。
ステップ4:最終アノテーションの生成 (Annotation Generation)
スクリプトパス:scripts/ann_generator.sh
機能:元の真値(GT)アノテーションと検出結果を組み合わせ、"Advanced"戦略(補間+時系列データベース修正)を使用して最終的な12Hzアノテーションファイルを生成します。
変更ガイド
スクリプト内のデータセットバージョン設定が正しいことを確認する必要があります。
PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \
# 1. data_path を変更
# 注意:「nuscenes」の層まで記述してください。「v1.0-mini」以下は含めないでください。
# ファイルが見つからない問題を避けるため、絶対パス(/ で始まるパス)を使用してください。
data_path="/root/autodl-tmp/UniScene_Storage/data/nuscenes"
# data_path="./data/nuscenes"
# 2. data_version を変更
# デフォルトのtrainvalをminiに変更
data_version="v1.0-mini"
# data_version="v1.0-trainval"
ann_frequency=$1
PY_ARGS=${@:2}
OUT_DIR="./out/"
LOG_DIR=$OUT_DIR/$input_frequency/'2'_$ann_frequency
if [ ! -d $LOG_DIR ]; then
mkdir -p $LOG_DIR
fi
python -m sAP3D.nusc_annotation_generator \
--data_path $data_path \
--data_version $data_version \
--ann_frequency $ann_frequency \
$PY_ARGS | tee -a $LOG_DIR/log_generate_ann.txt
実行コマンド(戦略に応じて選択)
- オプションA:高度戦略 (Advanced Strategy) — 推奨
補間と検出結果を組み合わせて高品質のアノテーションを生成します。--lidar_inf_rst_pathがステップ3の出力ファイルを指すように修正してください。scripts/ann_generator.sh 12 \ --ann_strategy 'advanced' \ --lidar_inf_rst_path ./out/lidar_20Hz/results_nusc_with_instance_token.json - オプションB:基本補間戦略 (Interp Strategy) — 高速
元のキーフレームのみを利用した単純な補間を行います。ステップ1〜3の結果には依存しません。scripts/ann_generator.sh 12 --ann_strategy 'interp'
最終出力:
nuScenesデータセットのルートディレクトリに新しいフォルダ(例:advanced_12Hz_miniまたはinterp_12Hz_mini)が生成され、完全なJSONアノテーションセット(sample.json, sample_annotation.jsonなど)が含まれます。このフォルダはnuScenes形式のデータセットとして直接読み込むことが可能です。
可視化検証 (Render)
スクリプトパス:scripts/render_ann.sh および render/nusc_annotation_render.py
機能:生成された3Dボックスを画像に投影し、動画として合成することで、アノテーション品質を検証します。
主要なコード修正
nuScenes-miniデータセットは一部のシーンが不足しているため、元のコードではインデックス範囲外エラーが発生する可能性があります。render/nusc_annotation_render.pyを修正する必要があります。
- シーンインデックスロジックの修正:
create_splits_scenesを使用せず、現在ロードされているシーンを動的に読み込むように変更します。 - Shellスクリプトの修正:
scripts/render_ann.sh内のdata_versionをv1.0-miniに必ず変更します。
実行コマンド
# パラメータ1:生成されたフォルダ名
bash scripts/render_ann.sh advanced_12Hz_mini --render_anns
よくある問題のトラブルシューティング (FAQ)
-
エラー
AssertionError: Database version not found: v1.0-mini- 原因:nuScenes初期化時のパスが間違っているか、または
dataディレクトリにv1.0-miniフォルダが実際に存在しないためです。 - 解決策:
data_pathがv1.0-miniの1つ上のディレクトリを含んでいるか確認してください。
- 原因:nuScenes初期化時のパスが間違っているか、または
-
エラー
ModuleNotFoundError: No module named 'mmdet3d'- 原因:Pythonのパスにmmdetection3dが含まれていません。
- 解決策:ASAPルートディレクトリで実行していること、および
pip installでmmdet3dライブラリがインストールされていること、またはPYTHONPATHにmmdetection3dのパスが追加されていることを確認してください。
-
推論時にプログレスバーが非常に速く進み、出力がない
- 原因:
NuScenesDatasetが公式SDKに従って20Hzの補間フレームをフィルタリングし、ロードされたサンプル数が0になったためです。 - 解決策:非公式バージョンのデータに
NuScenesDatasetを使用していることが原因です。mmdet3d v0.17.3では通常この問題は発生しませんが、発生した場合は.pklファイル生成時にtrainvalとminiの設定が誤って混用されていないか確認する必要があります。
- 原因:
-
レンダリング中にエラー
KeyError: 'scene-0035'- 原因:レンダリングスクリプトがminiデータセットでtrainvalのシーンを検索しようとしたためです。
- 解決策:Pythonレンダリングスクリプトを修正し、事前に定義された分割リストを使用するのではなく、
nusc.sceneリストを動的に取得するように変更してください。