Добавлены пропсы конвейера и стереодвижки, задействованные в прогоне
assets/conveyors (274 МБ) - ленты и угловая секция NVIDIA, на которые ссылается сцена относительным путём. Раньше исключались как перекачиваемые, но без них сцена не композится из коробки. cv/ - код стереодвижков, которые вызывает control_test, без весов: * defom-stereo - рабочий бейзлайн (DEFOM vitl, вход 480, iters 24) * crestereo - второй движок, точнее по габаритам (MAE 23.5 против 32.8 мм) * fast-foundationstereo - проверялся, в бейзлайн не вошёл * circular_section.py - показатель кругового сечения, перенесён в measure_plane.py: выравнивает облако по СОБСТВЕННЫМ главным осям и режет на пяти высотах вдоль каждой. Три самодельные версии (мировые оси, одно сечение) давали хуже; результаты проверки на эталонной геометрии - в circular_section_results.json Веса по-прежнему не в репозитории - источники в MODELS.md. Наборы кадров прежних прогонов (cv/flow_*, 1.26 ГБ) исключены: это выход, а не исходники. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
# Fast-FoundationStereo C++ Inference
|
||||
|
||||
C++ runtime for Fast-FoundationStereo stereo depth inference on TensorRT.
|
||||
|
||||
## Run from inside the C++ Docker container
|
||||
|
||||
**All commands in this README are intended to be run from inside the container built from [`docker/dockerfile_cpp`](../docker/dockerfile_cpp).** That image carries the CUDA toolkit, TensorRT 10 runtime + ONNX parser + C++ headers, OpenCV development package, `trtexec`, and a Python environment with PyTorch / ONNX export tooling. The plain `docker/dockerfile` image does **not** ship the C++ TRT headers and will fail to build the C++ targets.
|
||||
|
||||
Environment setup:
|
||||
|
||||
```bash
|
||||
docker build --network host -t ffs -f docker/dockerfile_cpp .
|
||||
bash docker/run_container.sh
|
||||
```
|
||||
|
||||
|
||||
`run_container.sh` mounts the parent of `docker/` (the repo root) into `/workspace`, so `cd /workspace/<repo-name>/cpp` lands you in this folder. Every `cd cpp`, `cpp/build/...`, `python3 scripts/...`, and `trtexec ...` example below assumes that working directory.
|
||||
|
||||
```text
|
||||
cpp/
|
||||
+-- CMakeLists.txt
|
||||
+-- README.md
|
||||
+-- app/
|
||||
| +-- main.cpp -- ffs_depth_main: single image inference + visualization
|
||||
| +-- build_single_engine.cpp -- ffs_build_single_engine: ONNX (with FFSGWCVolume plugin) -> .engine
|
||||
| +-- profile_speed.cpp -- ffs_profile_speed: latency profiler for either route
|
||||
+-- include/
|
||||
| +-- ffs_depth_tensorrt.hpp
|
||||
| +-- ffs_depth_single_tensorrt.hpp
|
||||
| +-- ffs_gwc_plugin.hpp
|
||||
+-- src/
|
||||
+-- ffs_depth_tensorrt.cpp
|
||||
+-- ffs_depth_single_tensorrt.cpp
|
||||
+-- gwc_volume_plugin.cpp
|
||||
+-- depth_kernels.cu
|
||||
```
|
||||
|
||||
Two interchangeable inference routes are supported:
|
||||
|
||||
- `FFSSingleEngineInference` loads **one** TensorRT engine that contains the `FFSGWCVolume` plugin node.
|
||||
- `FFSDepthInference` loads **two** TensorRT engines (feature_runner + post_runner) and computes the GWC cost volume between them with a hand-written CUDA kernel.
|
||||
|
||||
`ffs_depth_main` auto-detects the route based on the engine directory contents:
|
||||
|
||||
- If the directory contains `fast_foundationstereo.engine`, it uses the single-engine plugin path.
|
||||
- Otherwise it uses the two-engine reference path.
|
||||
|
||||
Inputs and outputs are the same in both cases:
|
||||
|
||||
- Input: a stereo image pair plus an intrinsic file (`demo_data/K.txt` format: 9 floats on line 1 for the 3x3 camera matrix, one float on line 2 for the stereo baseline in meters).
|
||||
- Output: float32 disparity (input-pixel units), float32 depth in meters, and PNG visualizations.
|
||||
|
||||
## Dependencies
|
||||
|
||||
All C++ build dependencies are provided by the [`docker/dockerfile_cpp`](../docker/dockerfile_cpp) image (see [Run from inside the C++ Docker container](#run-from-inside-the-c-docker-container) for how to build and enter it):
|
||||
|
||||
- CUDA Toolkit (for `nvcc` and the CUDA runtime).
|
||||
- TensorRT 10 runtime, ONNX parser, and C++ headers.
|
||||
- OpenCV development package (image I/O and depth visualization in `app/main.cpp`).
|
||||
- `trtexec`, used by Route B to build the two-engine TensorRT engines from ONNX.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cd cpp
|
||||
cmake -B build
|
||||
cmake --build build -j
|
||||
```
|
||||
|
||||
This produces:
|
||||
|
||||
- `build/libffs_gwc_plugin.so` -- the FFSGWCVolume plugin as a shared library (loadable by `trtexec --staticPlugins=...`).
|
||||
- `build/libffs_depth_inference.a` -- the inference static library.
|
||||
- `build/ffs_build_single_engine` -- single-engine builder.
|
||||
- `build/ffs_depth_main` -- demo / inference CLI.
|
||||
- `build/ffs_profile_speed` -- latency profiler.
|
||||
|
||||
## Route A: Single Engine with FFSGWCVolume Plugin
|
||||
|
||||
### A.1 Export ONNX with the plugin node
|
||||
|
||||
`scripts/make_plugin_onnx.py` exports one ONNX graph in which the GWC cost volume is represented by an `FFSGWCVolume` custom plugin node (resolved at engine-build time by `libffs_gwc_plugin.so`):
|
||||
|
||||
```bash
|
||||
python3 scripts/make_plugin_onnx.py \
|
||||
--model_dir weights/23-36-37/model_best_bp2_serialize.pth \
|
||||
--save_path output_plugin_onnx \
|
||||
--height 480 \
|
||||
--width 640 \
|
||||
--valid_iters 8 \
|
||||
--max_disp 192
|
||||
```
|
||||
|
||||
This writes:
|
||||
|
||||
```text
|
||||
output_plugin_onnx/
|
||||
+-- fast_foundationstereo_plugin.onnx
|
||||
+-- onnx.yaml
|
||||
```
|
||||
|
||||
### A.2 Build the single TensorRT engine
|
||||
|
||||
```bash
|
||||
cpp/build/ffs_build_single_engine \
|
||||
output_plugin_onnx/fast_foundationstereo_plugin.onnx \
|
||||
output_plugin_onnx/fast_foundationstereo.engine
|
||||
```
|
||||
|
||||
By default the engine is built with FP16 enabled. Pass `--fp32` to disable FP16. Pass `--workspace-mb N` to override the workspace (default 4096 MB).
|
||||
|
||||
After this step `output_plugin_onnx/` contains everything the runtime needs:
|
||||
|
||||
```text
|
||||
output_plugin_onnx/
|
||||
+-- fast_foundationstereo.engine
|
||||
+-- onnx.yaml
|
||||
```
|
||||
|
||||
### A.3 Run inference
|
||||
|
||||
Run from the repository root:
|
||||
|
||||
```bash
|
||||
cpp/build/ffs_depth_main \
|
||||
output_plugin_onnx \
|
||||
demo_data/left.png \
|
||||
demo_data/right.png \
|
||||
demo_data/K.txt \
|
||||
output_plugin_onnx
|
||||
```
|
||||
|
||||
The last argument is the output directory (default `ffs_output`). `ffs_depth_main` sees `fast_foundationstereo.engine` inside `output_plugin_onnx/` and uses `FFSSingleEngineInference`, which deserializes the engine and registers the `FFSGWCVolume` plugin before inference.
|
||||
|
||||
### A.4 Python alternative (build engine and run inference without the C++ apps)
|
||||
|
||||
The same plugin ONNX can be turned into an engine and executed end-to-end from Python. Only the C++ plugin shared library (`libffs_gwc_plugin.so`) is required from the C++ build; the C++ apps (`ffs_build_single_engine`, `ffs_depth_main`) are not.
|
||||
|
||||
```bash
|
||||
# 1. Export plugin ONNX
|
||||
python3 scripts/make_plugin_onnx.py \
|
||||
--model_dir weights/23-36-37/model_best_bp2_serialize.pth \
|
||||
--save_path output_plugin_onnx \
|
||||
--height 480 \
|
||||
--width 640
|
||||
|
||||
# 2. Build the C++ plugin shared library
|
||||
cmake -S cpp -B cpp/build
|
||||
cmake --build cpp/build -j
|
||||
|
||||
# 3. Build the TensorRT engine from Python
|
||||
python3 scripts/build_plugin_trt.py \
|
||||
output_plugin_onnx/fast_foundationstereo_plugin.onnx \
|
||||
output_plugin_onnx/fast_foundationstereo.engine
|
||||
|
||||
# 4. Run inference from Python
|
||||
python3 scripts/run_demo_plugin_trt.py \
|
||||
--model_dir output_plugin_onnx \
|
||||
--left_file demo_data/left.png \
|
||||
--right_file demo_data/right.png \
|
||||
--intrinsic_file demo_data/K.txt \
|
||||
--out_dir output_plugin_onnx
|
||||
```
|
||||
|
||||
Both `build_plugin_trt.py` and `run_demo_plugin_trt.py` auto-discover `libffs_gwc_plugin.so` in `cpp/build/`. Pass `--plugin_lib /path/to/libffs_gwc_plugin.so` to override the location. `build_plugin_trt.py` accepts `--fp32` and `--workspace-mb N` with the same meaning as `ffs_build_single_engine`. `run_demo_plugin_trt.py` writes the same five output files as the C++ demo (see [Outputs](#outputs)).
|
||||
|
||||
## Route B: Two TensorRT Engines (feature_runner + post_runner)
|
||||
|
||||
### B.1 Build the two engines
|
||||
|
||||
See the [Two-stage ONNX section in the top-level README](../readme.md#two-stage-onnx) for how to export `feature_runner.onnx` / `post_runner.onnx` with `scripts/make_onnx.py` and then build `feature_runner.engine` / `post_runner.engine` with `trtexec`. After running those steps your engine directory should contain:
|
||||
|
||||
```text
|
||||
output_two_onnx/
|
||||
+-- feature_runner.engine
|
||||
+-- post_runner.engine
|
||||
+-- onnx.yaml
|
||||
```
|
||||
|
||||
The two engines do **not** use the FFSGWCVolume plugin: the GWC cost volume is computed externally on GPU by `cpp/src/depth_kernels.cu` between the two engine calls, so a plain `trtexec --fp16` build with no custom plugin library is enough.
|
||||
|
||||
### B.2 Run inference
|
||||
|
||||
```bash
|
||||
cpp/build/ffs_depth_main \
|
||||
output_two_onnx \
|
||||
demo_data/left.png \
|
||||
demo_data/right.png \
|
||||
demo_data/K.txt \
|
||||
output_two_onnx
|
||||
```
|
||||
|
||||
`ffs_depth_main` sees no `fast_foundationstereo.engine` in the directory and falls back to `FFSDepthInference`, which executes the feature engine, builds the GWC volume with the CUDA kernel, then executes the post engine.
|
||||
|
||||
## Outputs
|
||||
|
||||
Both routes write the same files into the output directory:
|
||||
|
||||
- `disparity.bin` -- raw float32 disparity (input-pixel units), prefixed by int32 `[height, width]`.
|
||||
- `depth_meter.bin` -- raw float32 depth in meters, prefixed by int32 `[height, width]`.
|
||||
- `depth_meter.npy` -- NumPy float32 depth in meters, shape `[height, width]`.
|
||||
- `disp_vis.png` -- left/right/colorized-disparity side-by-side visualization.
|
||||
- `depth_vis.png` -- colorized depth visualization.
|
||||
|
||||
## Profile Speed
|
||||
|
||||
`ffs_profile_speed` benchmarks either route end-to-end on a single image pair using CUDA events for GPU-side timing and `steady_clock` for host wall time. It auto-detects the route the same way `ffs_depth_main` does (presence of `fast_foundationstereo.engine` in the engine directory selects single-engine), and `--mode` can be set explicitly:
|
||||
|
||||
```bash
|
||||
cpp/build/ffs_profile_speed <engine_dir> <left_image> <right_image> <intrinsic_file> \
|
||||
[--mode auto|two|single] [--warmup N] [--runs N] [--include-depth]
|
||||
```
|
||||
|
||||
Defaults: `--mode auto`, `--warmup 10`, `--runs 30`. With `--include-depth`, the disparity-to-depth conversion is included in the timed region (otherwise only the `infer()` call is timed).
|
||||
|
||||
### Profile the single engine
|
||||
|
||||
```bash
|
||||
cpp/build/ffs_profile_speed \
|
||||
output_plugin_onnx \
|
||||
demo_data/left.png demo_data/right.png demo_data/K.txt \
|
||||
--mode single --warmup 20 --runs 100
|
||||
```
|
||||
|
||||
### Profile the two engines
|
||||
|
||||
```bash
|
||||
cpp/build/ffs_profile_speed \
|
||||
output_two_onnx \
|
||||
demo_data/left.png demo_data/right.png demo_data/K.txt \
|
||||
--mode two --warmup 20 --runs 100
|
||||
```
|
||||
|
||||
The output looks like:
|
||||
|
||||
```text
|
||||
mode=single
|
||||
image=960x540
|
||||
model=640x480
|
||||
warmup=20 runs=100
|
||||
timed_region=infer
|
||||
gpu mean_ms=... p50_ms=... p90_ms=... min_ms=... max_ms=... std_ms=...
|
||||
host mean_ms=... p50_ms=... p90_ms=... min_ms=... max_ms=... std_ms=...
|
||||
```
|
||||
|
||||
- `gpu` is `cudaEventElapsedTime` between start/stop events on the inference stream (pure GPU work).
|
||||
- `host` is `std::chrono::steady_clock` around the same region, including the cost of `cudaEventSynchronize`. `host >= gpu` always.
|
||||
|
||||
For a side-by-side comparison, run the profiler twice with different engine directories and `--mode`, then compare the `gpu mean_ms` columns.
|
||||
Reference in New Issue
Block a user