本日はBlender枠です。
Blenderでは3DCGのモデリング以外にも多用途な使い方ができます。今回はColmapを用いた実写合成VFXを行うためのカメラワーク推定を行います。
〇環境
・Blender4.5
・Colmap
・ FFmpeg 7.1.1
〇Colmapとは?
Colmapは画像解析のオープンソースソフトウェアです。
RealityCaptureやNeRFなどのフォトグラメトリやスキャンなどのカメラ画像解析に用いられていたりもします。
具体的には3D Reconstruction(3次元再構築)を行います。これによって写真から実世界の物体の3次元情報を取得しています。
今回はColmapを用いて有料アドオンを使用せずに動画からカメラワーク(撮影時のカメラの動き)を三次元で取得します。
〇準備 作業ディレクトリの作成
任意のディレクトリにフォルダを作成、次の5つのフォルダを作成してください。01 COLMAP,02 VIDEOS.03 FFMPEG,04 SCENES,05 SCRIPT

注意点として日本語パスを含めたディレクトリ内には作成しないでください。
心配な場合Cドライブ直下に適当なフォルダを作成しその中に配置するとよいでしょう。なお、ルートのファイル名はautomated trackerとしました。
〇準備1 Colmapの取得
①GitHubのリンクからColmapを取得します。
NVIDIA製のGPUを使用したPCの場合は colmap-x64-windows-cuda.zip、NVIDIA以外のGPUを使用している場合はcolmap-x64-windows-nocuda.zipをDLします。
②DLした.zipを回答し、内部を先に作成しているautomated tracker/01 COLMAP内に配置します。
配置後の01 COLMAP内は次のようになります。

〇準備2 FFmpegの取得
次にFFmpegを取得します。これは
FFmpegは、動画や音声の処理を行うためのオープンソースのツールです。
例えば、動画ファイルのフォーマット変換や音声の抽出、解像度変更などが可能です。また、多くのメディアプレイヤーや編集ソフトが内部でFFmpegを利用しています。
筆者は以前BlenerでGIFメーカーアドオンを作成する際などに用いています。
①以下のリンクからversion 7.1.1のffmpeg-7.1.1-essentials_build.zipをDLします。

②FFmpegもColmap同様に展開したファイルを03 FFMPEGフォルダ内に配置します。
配置後は以下のようになります。

〇準備3
次にColmapとFFmpegというそれぞれ独立したソフトウェアをつなぎ合わせるためにスクリプト(プログラム)を配置します。 これは既に作成している方がいるので以下のコードを使用します。
Batch script for automated photogrammetry tracking workflow · GitHub
①Rowボタンを押します。

②余白部を右クリックし名前を付けて保存を選択します。

③ファイル名のbatch_reconstruct.bat.txtから.txtを削除しbatch_reconstruct.batファイルとして保存します。

![]()
④③の.batファイルを05 SCRIPTフォルダ内に配置します。

参考欄のYoutubeチュートリアルではScriptは上記で動くとありますが、筆者環境ではおそらく文字コード由来のエラーにより調整が必要でした。
⑤新規でテキストファイルを作成します。

⑥ファイル名をrun_fixed.batに変更します。重要なことは.txtではなくWindowsバッチファイルとして認識させてください。

⑦run_fixed.batを右クリックしてメモ帳で開きます。

⑧run_fixed.batの内部を次のコードを貼り付けます。
なお本コードはCドライブ直下のC:\automated trackerにフォルダを作成している前提でコードを記述しています。
違うディレクトリに作成した場合は該当パス部分を適時自分の環境に書き直してください。
@echo off
chcp 65001 > nul
echo.
echo === Starting Automated Photogrammetry Workflow ===
echo.
:: --- SET YOUR PROJECT FOLDER PATH HERE ---
:: --- Replace the path below with the exact path to your 'automated tracker' folder ---
set "TOP=C:\automated tracker"
:: --- Key paths are now set from the TOP variable ---
set "COLMAP_DIR=%TOP%\01 COLMAP"
set "VIDEOS_DIR=%TOP%\02 VIDEOS"
set "FFMPEG_DIR=%TOP%\03 FFMPEG"
set "SCENES_DIR=%TOP%\04 SCENES"
:: --- FOLDER EXISTENCE CHECKS WITH CLEAR LOGS ---
echo [1/4] Checking required folders...
if not exist "%COLMAP_DIR%" ( echo ✖ ERROR: '01 COLMAP' folder not found. & pause & exit /b )
echo ✔ Found '01 COLMAP' folder.
if not exist "%VIDEOS_DIR%" ( echo ✖ ERROR: '02 VIDEOS' folder not found. & pause & exit /b )
echo ✔ Found '02 VIDEOS' folder.
if not exist "%FFMPEG_DIR%" ( echo ✖ ERROR: '03 FFMPEG' folder not found. & pause & exit /b )
echo ✔ Found '03 FFMPEG' folder.
if not exist "%SCENES_DIR%" ( mkdir "%SCENES_DIR%" >nul & echo ✔ '04 SCENES' folder created. ) else ( echo ✔ Found '04 SCENES' folder. )
:: --- EXECUTABLE LOCATION CHECKS ---
echo.
echo [2/4] Verifying FFMPEG.exe location...
if exist "%FFMPEG_DIR%\ffmpeg.exe" ( set "FFMPEG=%FFMPEG_DIR%\ffmpeg.exe" ) else if exist "%FFMPEG_DIR%\bin\ffmpeg.exe" ( set "FFMPEG=%FFMPEG_DIR%\bin\ffmpeg.exe" )
if not defined FFMPEG ( echo ✖ ERROR: 'ffmpeg.exe' not found. & pause & exit /b )
echo ✔ Found ffmpeg.exe at "%FFMPEG%".
echo.
echo [3/4] Verifying COLMAP.exe location...
if exist "%COLMAP_DIR%\colmap.exe" ( set "COLMAP=%COLMAP_DIR%\colmap.exe" ) else if exist "%COLMAP_DIR%\bin\colmap.exe" ( set "COLMAP=%COLMAP_DIR%\bin\colmap.exe" )
if not defined COLMAP ( echo ✖ ERROR: 'colmap.exe' not found. & pause & exit /b )
echo ✔ Found colmap.exe at "%COLMAP%".
:: --- Final check before main process ---
echo.
echo [4/4] All pre-checks passed. Starting the main workflow.
pause
:: ================================================================
:: MAIN WORKFLOW
:: ================================================================
set "PATH=%COLMAP_DIR%;%COLMAP_DIR%\bin;%PATH%"
for /f %%C in ('dir /b /a-d "%VIDEOS_DIR%\*" ^| find /c /v ""') do set "TOTAL=%%C"
if "%TOTAL%"=="0" ( echo [INFO] No video files found. & pause & exit /b )
echo ==============================================================
echo Starting COLMAP on %TOTAL% video(s) ...
echo ==============================================================
setlocal EnableDelayedExpansion
set /a IDX=0
for %%V in ("%VIDEOS_DIR%\*.*") do (
if exist "%%~fV" (
set /a IDX+=1
call :PROCESS_VIDEO "%%~fV" "!IDX!" "%TOTAL%"
)
)
echo --------------------------------------------------------------
echo All jobs finished – results are in "%SCENES_DIR%".
echo --------------------------------------------------------------
pause
exit /b
:PROCESS_VIDEO
setlocal
set "VIDEO=%~1"
set "NUM=%~2"
set "TOT=%~3"
for %%I in ("%VIDEO%") do (
set "BASE=%%~nI"
set "EXT=%%~xI"
)
echo.
echo [!NUM!/!TOT!] === Processing "!BASE!!EXT!" ===
set "SCENE=%SCENES_DIR%\!BASE!"
set "IMG_DIR=!SCENE!\images"
set "SPARSE_DIR=!SCENE!\sparse"
if exist "!SCENE!" ( echo ↻ Skipping "!BASE!" – already reconstructed. & goto :END )
mkdir "!IMG_DIR!" >nul
mkdir "!SPARSE_DIR!" >nul
echo [1/4] Extracting frames...
"%FFMPEG%" -loglevel error -stats -i "!VIDEO!" -qscale:v 2 "!IMG_DIR!\frame_%%06d.jpg"
if errorlevel 1 ( echo ✖ FFmpeg failed – skipping "!BASE!". & pause & goto :END )
dir /b "!IMG_DIR!\*.jpg" >nul 2>&1 || ( echo ✖ No frames extracted – skipping "!BASE!". & pause & goto :END )
echo [2/4] COLMAP feature_extractor...
"%COLMAP%" feature_extractor --database_path "!SCENE!\database.db" --image_path "!IMG_DIR!" --ImageReader.single_camera 1 --SiftExtraction.use_gpu 1 --SiftExtraction.max_image_size 4096
if errorlevel 1 ( echo ✖ feature_extractor failed – skipping "!BASE!". & pause & goto :END )
echo [3/4] COLMAP sequential_matcher...
"%COLMAP%" sequential_matcher --database_path "!SCENE!\database.db" --SequentialMatching.overlap 15
if errorlevel 1 ( echo ✖ sequential_matcher failed – skipping "!BASE!". & pause & goto :END )
echo [4/4] COLMAP mapper...
"%COLMAP%" mapper --database_path "!SCENE!\database.db" --image_path "!IMG_DIR!" --output_path "!SPARSE_DIR!" --Mapper.num_threads %NUMBER_OF_PROCESSORS%
if errorlevel 1 ( echo ✖ mapper failed – skipping "!BASE!". & pause & goto :END )
if exist "!SPARSE_DIR!\0" (
"%COLMAP%" model_converter --input_path "!SPARSE_DIR!\0" --output_path "!SPARSE_DIR!" --output_type TXT >nul
)
echo ✔ Finished "!BASE!" (!NUM!/!TOT!)
:END
endlocal & goto :eof
このコードは問題をチェックしてくれる機能を持たせています。 初期設定とフォルダ確認などを一つ一つ確認しエラーが発生しない場合は問題がありません。
〇処理の開始
①処理を開始する前に02 VIDEOS内に任意の.mp4を配置します。

処理には膨大な時間がかかるため必要ないフレームなどはこの時点でトリミングしておくことを強く推奨します。
②処理を開始するにはSCRIPTフォルダ内のrun_fixed.batを実行します。

このスクリプトでは先に説明した通り、チェックが行われエラーが発生していない場合すべての項目に✔がつき、Press any key to continue...が表示されますので 何かしらのキーを押すことで実際の処理が開始されます。
なお51フレーム程度の動画で1時間程度かかりました。
4k 1分半のiPhoneで撮影した動画で丸々5日半かかりました。この辺りはPCのスペックにも依存します。
〇処理の完了
処理が完了すると04 SCENESフォルダ内に動画名のフォルダが作成され、database.dbを含めたデータが作成されます。

以上で動画解析フェーズになります。次回これをBlenderで読み込んでいきます。