Skip to content

Instantly share code, notes, and snippets.

@aidv
Forked from polyfjord/AutoTracker_v1.4.bat
Last active September 4, 2025 10:14
Show Gist options
  • Save aidv/05779c76401ae55ee6b227ee0c1e47f9 to your computer and use it in GitHub Desktop.
Save aidv/05779c76401ae55ee6b227ee0c1e47f9 to your computer and use it in GitHub Desktop.
AutoTracker workflow using GLOMAP
:: ================================================================
:: BATCH SCRIPT FOR AUTOMATED PHOTOGRAMMETRY TRACKING WORKFLOW
:: By polyfjord - https://youtube.com/polyfjord
:: GLOMAP mapping (faster), COLMAP for features/matching + TXT export
:: ================================================================
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set COLMAP_USE_GPU=1
:: Detect AMD GPU
set "gpuInfo="
for /f "tokens=*" %%i in ('wmic path win32_VideoController get name /value ^| find "="') do (
set "gpuInfo=%%i"
)
echo Detected GPU: !gpuInfo!
echo !gpuInfo! | find /I "AMD" >nul
if %errorlevel%==0 (
echo ============================================================
echo WARNING: AMD GPU detected.
echo COLMAP and GLOMAP will probably fail or crash on AMD GPUs.
echo ============================================================
set /p useCPU="Do you want to force CPU mode instead? [y/n]: "
if /I "!useCPU!"=="y" (
echo Using CPU mode...
set COLMAP_USE_GPU=0
) else (
echo Exiting...
exit /b 1
)
)
:: ---------- Resolve top-level folder (one up from this .bat) -----
pushd "%~dp0\.." >nul
set "TOP=%cd%"
:: Point Qt to the correct plugin folder
set "QT_QPA_PLATFORM_PLUGIN_PATH=%TOP%\01 GLOMAP\plugins\platforms"
:: ---------- Key paths -------------------------------------------
set "SFM_DIR=%TOP%\01 GLOMAP"
set "VIDEOS_DIR=%TOP%\02 VIDEOS"
set "FFMPEG_DIR=%TOP%\03 FFMPEG"
set "SCENES_DIR=%TOP%\04 SCENES"
:: ---------- Locate ffmpeg.exe -----------------------------------
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"
) else (
echo [ERROR] ffmpeg.exe not found inside "%FFMPEG_DIR%".
popd & pause & goto :eof
)
:: ---------- Locate glomap.exe -----------------------------------
if exist "%SFM_DIR%\glomap.exe" (
set "GLOMAP=%SFM_DIR%\glomap.exe"
) else if exist "%SFM_DIR%\bin\glomap.exe" (
set "GLOMAP=%SFM_DIR%\bin\glomap.exe"
) else (
echo [ERROR] glomap.exe not found inside "%SFM_DIR%".
popd & pause & goto :eof
)
:: ---------- Locate colmap.exe (DB + TXT export) ------------------
if exist "%SFM_DIR%\colmap.exe" (
set "COLMAP=%SFM_DIR%\colmap.exe"
) else if exist "%SFM_DIR%\bin\colmap.exe" (
set "COLMAP=%SFM_DIR%\bin\colmap.exe"
) else (
echo [ERROR] colmap.exe not found inside "%SFM_DIR%".
popd & pause & goto :eof
)
:: ---------- Put binaries on PATH --------------------------------
set "PATH=%SFM_DIR%;%SFM_DIR%\bin;%PATH%"
:: ---------- Ensure required folders exist ------------------------
if not exist "%VIDEOS_DIR%" (
echo [ERROR] Input folder "%VIDEOS_DIR%" missing.
popd & pause & goto :eof
)
if not exist "%SCENES_DIR%" mkdir "%SCENES_DIR%"
:: ---------- Count videos for progress bar ------------------------
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 in "%VIDEOS_DIR%".
popd & pause & goto :eof
)
echo ==============================================================
echo Starting GLOMAP pipeline on %TOTAL% video(s) …
echo ==============================================================
set /a IDX=0
for %%V in ("%VIDEOS_DIR%\*.*") do (
set /a IDX+=1
call :PROCESS_VIDEO "%%~fV" "%%IDX%%" "%TOTAL%"
)
echo --------------------------------------------------------------
echo All jobs finished – results are in "%SCENES_DIR%".
echo --------------------------------------------------------------
popd
pause
goto :eof
:PROCESS_VIDEO
:: ----------------------------------------------------------------
:: %1 = full path to video %2 = current index %3 = total
:: ----------------------------------------------------------------
setlocal EnableDelayedExpansion
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!" ===
:: -------- Directory layout for this scene -----------------------
set "SCENE=%SCENES_DIR%\!BASE!"
set "IMG_DIR=!SCENE!\images"
set "SPARSE_DIR=!SCENE!\sparse"
:: -------- Skip if already reconstructed -------------------------
if exist "!SCENE!" (
echo • Skipping "!BASE!" – already reconstructed.
goto :END
)
:: Clean slate ----------------------------------------------------
mkdir "!IMG_DIR!" >nul
mkdir "!SPARSE_DIR!" >nul
:: -------- 1) Extract every frame --------------------------------
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!".
goto :END
)
dir /b "!IMG_DIR!\*.jpg" >nul 2>&1 || (
echo × No frames extracted – skipping "!BASE!".
goto :END
)
:: -------- 2) Feature extraction (COLMAP) -------------------------
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 %COLMAP_USE_GPU% ^
--SiftExtraction.max_image_size 4096 ^
--SiftExtraction.max_num_features 2000 ^
1> "!SCENE!\feature_extractor.log" 2>&1
:: Check for warnings
findstr /C:"WARNING" "!SCENE!\feature_extractor.log" >nul
if %errorlevel%==0 (
echo.
echo --------------------------------------------------------
echo ⚠ WARNINGS during feature extraction:
echo --------------------------------------------------------
findstr /C:"WARNING" "!SCENE!\feature_extractor.log"
echo --------------------------------------------------------
)
:: Check for errors based on log content
findstr /C:"ERROR" "!SCENE!\feature_extractor.log" >nul
if %errorlevel%==0 (
echo.
echo × feature_extractor failed – skipping "!BASE!".
echo --------------------------------------------------------
findstr /C:"ERROR" "!SCENE!\feature_extractor.log"
echo --------------------------------------------------------
goto :END
)
:: Check if features were actually extracted
findstr /C:"Processed file" "!SCENE!\feature_extractor.log" >nul
if %errorlevel%==0 (
echo √ feature_extractor completed successfully.
) else (
echo × feature_extractor produced no features – skipping "!BASE!".
goto :END
)
:: -------- 3) Sequential matching (COLMAP) ------------------------
echo [3/4] COLMAP sequential_matcher …
"%COLMAP%" sequential_matcher ^
--database_path "!SCENE!\database.db" ^
--SiftMatching.use_gpu %COLMAP_USE_GPU% ^
--SequentialMatching.overlap 15 ^
--SiftMatching.max_num_matches 1000
if errorlevel 1 (
echo × sequential_matcher failed – skipping "!BASE!".
goto :END
)
:: -------- 4) Sparse reconstruction (GLOMAP) ----------------------
echo [4/4] GLOMAP mapper …
"%GLOMAP%" mapper ^
--database_path "!SCENE!\database.db" ^
--image_path "!IMG_DIR!" ^
--output_path "!SPARSE_DIR!"
if errorlevel 1 (
echo × glomap mapper failed – skipping "!BASE!".
goto :END
)
:: -------- Export TXT **inside the model folder** -----------------
:: Keep TXT next to BIN so Blender can import from sparse\0 directly.
if exist "!SPARSE_DIR!\0" (
"%COLMAP%" model_converter ^
--input_path "!SPARSE_DIR!\0" ^
--output_path "!SPARSE_DIR!\0" ^
--output_type TXT >nul
)
:: -------- Export TXT to parent sparse\ (for Blender auto-detect) --
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
@aidv
Copy link
Author

aidv commented Sep 4, 2025

Changelog;

  • FIxed QT issue
  • Added check for AMD GPU's
  • Added false failure during message during feature_extractor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment