FlowEngine 9.000
Photogrammetry Software Development Kit
Loading...
Searching...
No Matches

Structure from Motion and Multiview Stereo libraries by 3Dflow

FlowEngine is the perfect Photogrammetry Software Development Kit: a powerful, fully customizable photogrammetry reconstruction engine written in C++ available for Windows and Linux.


Table of contents:

  1. Installation
    1. Windows
    2. Linux
    3. CMake Integration
  2. Compiler Requirements
  3. System Requirements
  4. Licensing and Activation
    1. Activation
    2. Free Version Limitations
    3. Licensing
  5. API
    1. Objects
    2. Conventions
    3. Thread Safety
    4. Error Handling
    5. Data Structures
    6. Utilities
  6. Quick Start
  7. Examples
    1. Building
  8. Computation Settings
    1. Settings
    2. Settings Manager
    3. Computation Presets
    4. Bundle Adjustment Settings
    5. Point Classification Settings
  9. Tips
    1. Initial Camera Calibration Parameters
  10. Extra
    1. Classification Models
    2. Masking Models
  11. Support

Installation

Windows

CMake

First, generate and build the project using cmake-gui and Visual Studio.

To install the SDK, the INSTALL target must be run with Administrator privileges (writing to C:\Program Files\ requires elevation). There are two ways to do this:

Option A — Visual Studio: Close Visual Studio if it is open, relaunch it as Administrator, reopen the solution from your build folder, and build the INSTALL target in Release configuration.

Option B — Elevated command prompt: Open a Command Prompt as Administrator and run:

cmake --install <your-build-folder> --config Release

The default installation directory is

C:\Program Files\FlowEngine or C:\Program Files\FlowEngineFree depending on your version.

The installed package includes the CMake config files needed for find_package integration (see CMake Integration).

Linux

Simply use the debian package installation included in the SDK. In the terminal run:

sudo apt install ./FlowEngine_@version@.deb

replace @version@ with the version you have.

Use apt install, not dpkg -i: FlowEngine and FlowEngineFree conflict with each other, and only apt will automatically remove the other edition first if it's already installed. dpkg -i will simply fail in that case.

Alternatively, you can build the Examples and run make install.

Don't mix the two install methods. The .deb installs to /usr, while make install defaults to /usr/local. If you use both at different times (e.g. testing a source build, then switching to the .deb, or vice versa), CMake's find_package searches /usr/local before /usr and will silently pick up whichever copy it finds first – even a stale one left behind by an install you've since replaced or removed. If find_package succeeds but the build fails to link, remove the stale copy (check /usr/local/cmake/ and /usr/local/lib/) before installing fresh.

CMake Integration

After installing FlowEngine, the SDK provides a CMake package config file. In your project:

# Full version
find_package( FlowEngine REQUIRED )
target_link_libraries( MyApp PRIVATE FlowEngine::FlowEngine )
# Free version
find_package( FlowEngineFree REQUIRED )
target_link_libraries( MyApp PRIVATE FlowEngineFree::FlowEngineFree )

Compile flags and link dependencies (SSE4.2, OpenMP, etc.) are propagated automatically through the imported target and do not need to be set manually.

If the SDK is not installed to a standard system path, provide a hint:

# Full version
find_package( FlowEngine REQUIRED HINTS /path/to/FlowEngine )
# Free version
find_package( FlowEngineFree REQUIRED HINTS /path/to/FlowEngineFree )

Alternatively, set the FlowEngine_ROOT (or FlowEngineFree_ROOT) environment variable or CMake variable before calling find_package.

Windows: FlowEngine.dll / FlowEngineFree.dll and their redistributable dependencies (onnxruntime.dll) must be in the same directory as your executable at runtime. Add a post-build step to copy them all automatically:

add_custom_command(TARGET MyApp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_RUNTIME_DLLS:MyApp>
$<TARGET_FILE_DIR:MyApp>
COMMAND_EXPAND_LISTS
)

TARGET_RUNTIME_DLLS requires CMake 3.21 or newer, which matches the minimum required version of this SDK.

Linux: ImageMagick 7.0.0 or newer must be present on the target machine at runtime.


Compiler Requirements

FlowEngine requires C++17 or newer.

The following compilers are officially supported:

Platform Compiler Minimum Version
Windows MSVC (Visual Studio) Visual Studio 2019
Linux GCC 13.3.0

Only 64-bit builds are supported. Other compilers or platforms are not officially tested.


System Requirements

Minimum requirements depend heavily on the dataset size and computation settings and cannot be stated precisely. The following are general recommendations:

  • RAM: 16 GB or more recommended.
  • CPU: SSE4.2 instruction set support required.
  • GPU: A CUDA-enabled GPU is strongly recommended for best performance.
    • Minimum CUDA compute capability: 7.5 (Turing).
    • OpenCL devices are also supported as an alternative to CUDA.
    • CPU-only computation is supported but will be significantly slower.
Compute Capability Architecture Representative GPUs
7.5 Turing (2018) GTX 1650 / 1660, RTX 2060 – RTX 2080 Ti, Titan RTX
8.0 Ampere (2020) A100, A30
8.6 Ampere (2020) RTX 3050 – RTX 3090, RTX A4000 / A5000 / A6000
8.9 Ada Lovelace (2022) RTX 4050 – RTX 4090, L4
9.0 Hopper (2022) H100, H200

Licensing and Activation

Activation (Full version only)

To use the full version of the SDK, you need to activate it on a specific machine.

To activate the product you can either:

For a standard activation, all you need to do is to invoke:

FlowEngineLicenser activate XXXX-XXXX-XXXX-XXXX-XXXX-XXXX

When using TurboFloatServer, the Licenser can help to setup the server information.

For example:

FlowEngineLicenser flserver set 127.0.0.1 2103

To cleanup previous information:

FlowEngineLicenser flserver clear

Notes:

  • You might need Administrator privileges for certain license functionalities.
  • Some functions of the Licenser may not be available in the Floating license version.

See the README.txt in the third_party/TurboFloat-Server-Linux for more information on how to setup the server.

Free Version Limitations

  • Most of the processing functions are available but limited to 50 pictures.
  • Some of the exporting functions are not available.
See also
FlowEngine::Result::FeatureNotAvailable.

Licensing

The FlowEngine license is included in the main SDK directory in the file license.txt.

Unless you have already discussed and agreed a specific licensing model with 3Dflow srl, the same licensing terms of FlowEngine Free applies.


Application Program Interface

FlowEngine is a thin layer on top of our technologies. As such, the interface is very simple. Abstractions are left to the users to be built on top.

Some very basic utilities are distributed with the SDK (see section Utilities)

Objects

FlowEngine exposes a set of Objects that are used throughout various computations.

Some example of these Objects are:

Objects must be created and destroyed with their respective function (e.g. FlowEngine::CreateCamera, FlowEngine::DestroyCamera)

Objects are created and destroyed by the user. FlowEngine never creates instances.

FlowEngine::UniqueCameraPtr and its siblings can be used to facilitate automatic storage for Object classes.

Conventions

The documentation specifies what kind of parameters are expected in a function call.

  • In parameters: the parameter is expected to in a valid state and, when applicable, in a valid value range as described in the documentation. The passed-in parameter will not be modified (at least in its observable state) by the function.
  • Out parameters: the parameter must point to a valid memory location that will be filled with data by the function.
  • In,Out parameters: the parameter is expected to be in a valid state and, when applicable, in a valid value range as described in the documentation. The parameter will also be modified by the function.

When passing references to Objects, the object must be in a valid state (i.e. at least successfully created). Functions specify if the object must satisfy a precondition in the documentation.

When passing Buffers, the buffer must point to a valid memory region. FlowEngine never stores buffers directly. Instead memory is copied if needed. When appropriate, the documentation specifies how big the buffer must be before calling the function.

  • Passing a reference to NULL is undefined behavior.
  • Passing parameters in an invalid range is considered a broken precondition and therefore undefined behavior. Note that some functions will still check for violated preconditions when possible and will try to fail in an orderly manner by reporting a generic error, but this should not be relied on.

Thread Safety

FlowEngine methods are not thread-safe: calling them concurrently from multiple threads simultaneously is undefined behavior.

However, it is safe to call FlowEngine methods from a thread other than the main thread. This is a common pattern in UI applications, where computation runs on a dedicated background thread to keep the interface responsive. The requirement is that only one FlowEngine call is in progress at any given time.

Error Handling

Functions in FlowEngine are exception free. Instead, error codes are returned.

Functions that do not return error codes, can never fail or the result is consistent even in the case of failed preconditions (e.g. returning 0 elements in a collection). The result codes indicates if the operations was successful or what error caused the operation to fail.

If a function in the documentation contains preconditions and the preconditions are not met before calling it, the behavior is undefined.

The utility function FlowEngine::CheckResult can be used to print an error message in string form to the standard error stream and terminate the application.

Object creation functions return nullptr if the object creation has failed.

Exception Safety

FlowEngine does not throw exceptions under any circumstances. If an exception propagates out of a FlowEngine call, it should be treated as a defect in the SDK — please report it.

See also
FlowEngine::Result

Data Structures

FlowEngine::Point2, Point3 hold respectively a couple and a triplet of doubles that represents a 2-dimensional and 3-dimensional position in space

FlowEngine::Normal is a triplet of floats that represents a normal (unit-sized)

FlowEngine::Color specifies a packed (32 bits) RGB color

FlowEngine::Triangle is a triplet of point indices that represents the vertices of a triangle specified in counter-clockwise order.

FlowEngine::TexCoords is a pair of floating point values holding texture coordinates.

FlowEngine::Quaternion is used to represent an axis and a rotation around that axis

Buffers

Buffers are very simple structs that aid in the passing of parameters that are generally coupled together as pointer and size.

They hold a typed pointer to an array of values and the number of elements they point to.

They never own the data they point to. This also implies trivial copying.

Various implicit constructors help the user code to call functions without having to manually convert their data first, so generally they are almost invisible to the user.

See also
FlowEngine::Buffer
FlowEngine::ConstBuffer

Utilities

The SDK is shipped with a small set of basic utilities built on top of the API:

See also
Utilities.h

Quick start

Here's a superquick example to compute everything:

using namespace FlowEngine;
// Setup settings
UniqueSettingsPtr settings( CreateSettings() );
if ( argc > 1 ) // Try to load the xml from file
settings->load( argv[ 1 ] );
// Prepare the progress bar
FlowEngine::ProgressBarEmpty progressBar;
// Prepare the log listener to let the application write the log to file
FlowEngine::LogListenerOStream logListener;
std::ofstream myfile( "log.txt" );
if ( myfile.good() )
logListener.mFileStream = &myfile;
// Prepare data to be filled
std::vector< UniqueCameraPtr > cameras;
UniqueSparsePointCloudPtr sparsePointCloud( CreateSparsePointCloud() );
UniqueStereoPointCloudPtr stereoPointCloud( CreateStereoPointCloud() );
UniqueStereoMeshPtr stereoMesh( CreateStereoMesh() );
UniqueStereoTexturedMeshPtr stereoTexturedMesh( CreateStereoTexturedMesh() );
// Load all the cameras in the folder
std::string imagesPath;
imagesPath.resize( settings->getValueLength( "Workspace", "ImagesPath" ) );
settings->getValue( "Workspace", "ImagesPath", imagesPath );
UniqueCamerasLoaderPtr camerasLoader( CreateCamerasLoader() );
for ( Size i = 0; i < camerasLoader->getImageCount( imagesPath ); ++i )
cameras.emplace_back( CreateCamera() );
CheckResult( camerasLoader->loadImages( imagesPath, true, cameras ), logListener );
// Main flowengine object
FlowEnginePtr flowengine( CreateFlowEngineObject() );
// Compute Structure from motion
CheckResult( flowengine->computeStructureAndMotion( *settings, progressBar, logListener, cameras, *sparsePointCloud ), logListener );
// Compute the bounding box
UniqueBoundingBoxPtr boundingBox( CreateBoundingBox() );
CheckResult( boundingBox->computeFromPoints( *sparsePointCloud, true ), logListener );
// Compute Dense point cloud with Multiview Stereo procedure
CheckResult( flowengine->computeDensePointCloud( *settings, progressBar, logListener, *boundingBox, cameras, *sparsePointCloud, *stereoPointCloud ), logListener );
// Compute Mesh
CheckResult( flowengine->computeMesh( *settings, progressBar, logListener, *boundingBox, cameras, *stereoPointCloud, *stereoMesh ), logListener );
// Finally compute the textured mesh
CheckResult( flowengine->computeTexturedMesh( *settings, progressBar, logListener, cameras, *stereoMesh, *stereoTexturedMesh ), logListener );
// Export output as .obj
CheckResult( stereoTexturedMesh->saveToObj( "test.obj" ), logListener );

Examples

The SDK comes with many examples. For example:

  • Basic (ExampleBasic.cpp) Shows how to setup a minimal computation, including settings and the log, up to a textured mesh.
  • Advanced (ExampleAdvanced.cpp) Shows how to configure a computation in a more advanced manner, load settings from an external file and resume previous computations. Optionally (must be enabled in the build settings) the examples shows how to export the computed textured mesh to the FBX format.
  • Stream (ExampleStream.cpp) In this particular use case, a series of frames are processed through the pipeline one after another, each time using the result from the previous computation.
  • Ortho (ExampleOrtho.cpp) Resumes from the basic example and first runs a Bundle adjustment with control points and then computes an orthophoto with the stereo mesh, finally saves the orthophoto using a particular georeferencing system.

Some simple datasets are also included with the SDK for experimentation with the examples.

For more free datasets, please visit: http://datasets.shared.3dflow.net

Building the examples

Examples are easily compiled with CMake (version 3.21 and newer) and GCC version >= 13.3.0 or Visual Studio 2019

Optional dependencies:

  • FBX SDK: to export meshes and textured meshes to the FBX format.
  • Eigen: to use the included FbxHelper utility class to ease the FBX export.

Note that only 64 bits builds are supported.

Linux

Required dependencies:

  • ImageMagick version >= 7.0.0

    We suggest that you follow one of the many tutorials available. However, these basic steps should be sufficient for most cases:

    1. Install pkg-config (very recommended so that ImageMagick configure step will easily find any additional image delegates):
      sudo apt-get install pkg-config

    2. Install additional ImageMagick delegates:
      sudo apt-get install libpng-dev
      sudo apt-get install libjpeg-dev
      sudo apt-get install libtiff-dev

    3. Download and compile ImageMagick:
      wget http://www.imagemagick.org/download/ImageMagick.tar.gz
      tar -xvf ImageMagick.tar.gz
      cd ImageMagick-7.*
      ./configure --with-quantum-depth=16 --enable-hdri=yes
      make -j20
      sudo make install
      sudo ldconfig /usr/local/lib

    4. Download Onnxruntime
      wget https://github.com/microsoft/onnxruntime/releases/download/v1.20.1/onnxruntime-linux-x64-gpu-1.20.1.tgz
      tar -xf onnxruntime-linux-x64-gpu-1.20.1.tgz
      cd onnxruntime-linux-x64-gpu-1.20.1
      sudo cp -rf lib/* /usr/local/lib/
      sudo ldconfig /usr/local/lib/
    5. Install OpenCL Installable Client Driver (ICD) Loader:
      sudo apt install ocl-icd-libopencl1

From the main FlowEngine package directory run:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j20

Examples are built in the redist directory by default.

To install the SDK run:

sudo make install

This installs the library, headers, and the CMake config files required for find_package integration.

Alternatively, you can run the included setup.sh script to both build the examples and install the SDK. From the terminal:

chmod +x setup.sh
./setup.sh

The script requires administrator privileges for the installation part.

Building examples standalone (after installation)

If you have already installed the SDK, you can build the examples on their own without the root project:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DFlowEngine_DIR=/usr/local/cmake ../examples
make -j20

Replace /usr/local with your actual installation prefix if different.

Windows

We suggest to use the graphical interface for CMake (cmake-gui) available here: https://cmake.org/download/

After the installation:

  1. Specify the source code folder, e.g.: C:/SDK/FlowEngine
  2. Specify the build folder, e.g.: C:/SDK/FlowEngine/Build
  3. Hit the Configure button, select the generator (e.g. Visual Studio 17 2022), set the platform to x64, then click Finish.
  4. After the configuring process, click the Generate button and then Open Project.

Building examples standalone (after installation)

If you have already installed the SDK, you can configure cmake-gui to build only the examples:

  1. Set the source folder to C:/SDK/FlowEngine/examples
  2. Set FlowEngine_DIR to the cmake subdirectory of your installation, e.g. C:/Program Files/FlowEngine/cmake
  3. Configure, generate, and open the project as above.

Computation Settings

Settings

You can set all the computation settings through the FlowEngine::SettingsInterface object. Settings can be loaded from a file (.xml) or programmatically.

Additionally, you can set the following general processing settings:

  • Cuda/DeviceList: List of the devices to be used. If set to "0", the first Cuda device will be used. If set to "0 1" the first and the second Cuda device will be used together. If the list is empty, computation will run on CPU.
  • Workspace/TempPath: Path to the cache folder. Please note that the cache folder is not created or deleted. automatically after the processing. Be sure that this directory exists before starting computations.
  • (Examples only) Workspace/ImagesPath: Path to the image folder.
  • (Examples only) Workspace/ExportPath: Path to the export folder.

A couple of examples configuration settings are included in the SDK redist/ExampleSettings folder.

For a full list of pipeline processing parameters, please refer to this page: Tutorial: Parameters Tuning

Settings Manager

FlowEngine::SettingsManager is a collection of utility methods to:

Computation Presets

For each phase in the pipeline, it's possible to specify a set of computation settings that will contain all the parameters for that phase. We have compiled common usage settings over the years that should be enough for most users or at least a good starting point.

For example, here are some examples of the available presets:

Phase Preset Category Preset Name Description
Samantha General Fast Very fast and general purpose structure and motion
Stereo Aerial High Details Detailed stereo reconstruction for aerial datasets
Surface Human Body Default Close range standard surface reconstruction
Texture General Low Poly Texture generation specialized for low polygon meshes

Notes

Bundle Adjustment Settings

The following settings can be customized when performing a bundle adjustment:

Category Name Default Min Max
"BundleAdjustment" "AdjustInternals" 1 0 1
"BundleAdjustment" "TwoStepsFocalAdjustment" 0 0 1
"BundleAdjustment" "AdjustRadialDistortion" 1 0 1
"BundleAdjustment" "AdjustTangentialDistortion" 0 0 1
"BundleAdjustment" "MaxCamerasPerChunk" 50 2 DBL_MAX
"BundleAdjustment" "MaximumTracksPerCamera" 10 10 DBL_MAX
"BundleAdjustment" "MaxIterations" 20 1 DBL_MAX
"BundleAdjustment" "MaxOuterIterations" 5 1 DBL_MAX
"BundleAdjustment" "MaxReprojectionError" 10 1e-05 DBL_MAX
"BundleAdjustment" "MinIterations" 10 1 DBL_MAX
"BundleAdjustment" "RemoveInvalidCameras" 0 0 1

Notes

  • Values might change during major FlowEngine updates.
  • Use the FlowEngine::SettingsManager class or the ExampleSettingsManager utility program (built with the examples) to discover updated values.

Point Classification Settings

The following settings can be customized when performing a point classification:

Category Name Default Min Max
"PointClassification" "UseGroundFilter" 0 0 1
"PointClassification" "MinCamerasPerCategory" 3 1 INT_MAX
"PointClassification" "MinPointsPerCategory" 300 1 INT_MAX

The ground filter extraction algorithm can be customized with the following parameters:

Category Name Default Min Max
"PointClassification" "CSFClothResolution" 1.0 0.0 DBL_MAX
"PointClassification" "CSFRigidness" 2 1 3
"PointClassification" "CSFClassThreshold" 0.5 0.0 1.0
"PointClassification" "CSFIterations" 500 1 1000
"PointClassification" "CSFSmoothing" 1 0 1
"PointClassification" "CSFTimeStep" 0.65 0.0 1.0

Notes

  • Values might change during major FlowEngine updates.
  • Use the FlowEngine::SettingsManager class or the ExampleSettingsManager utility program (built with the examples) to discover updated values.

Tips

Initial Camera Calibration Parameters

Exif Grouping

Grouping cameras calibration means that the cameras with the same EXIF information about camera lenses and model or without EXIF information but with the same resolution will share the same calibration parameters during the reconstruction. Grouping should be always used when taking photos with the same camera device as it makes the reconstruction more stable. In the case of a rig of cameras, it's usually better to keep it disabled, unless the results are unstable (like in the autocalibration case).

See also
FlowEngine::CamerasLoaderInterface

Autocalibration, Adjusted, and Fixed internal parameters

In the camera calibration object, you can control how the internal parameters will be handled by the reconstruction pipeline. The FlowEngine::CamerasLoaderInterface utility class will automatically use the EXIF information (when available) to set up the cameras calibration object in the most appropriate way. When using .png files or images that don't contain any EXIF information, the pipeline will try to perform the autocalibration routine.

If the EXIF information is present, an initial parameters guess will be set and the parameters will be only adjusted by the pipeline, the type of adjustment is defined by the FlowEngine::CameraCalibrationInterface::setAdjustmentType function.

Autocalibration

No initial focal length or radial distortion parameters are given. By default, a newly created camera calibration object will be treated as autocalibrated. The pipeline will try to find the internal parameters from images matches. The procedure can be unstable if the same camera calibration is used in very few cameras (less than 5-10). You can additionally set if you want to adjust the radial and tangential distortion or keep it fixed.

Adjusted Internal Parameters

The pipeline will use the parameters defined by the user as initial guesses, but it will adjust them during the reconstruction. You can set to adjust the focal length, optical center, tangential and radial distortion.

While the optical center and the radial distortion can be set to the default values (respectively zero and half the image size), it's important to set a sensible guess for the focal length.

The optional precalibration step performs a quick reconstruction with adjustment followed by a Euclidean reconstruction step and should be used especially when the initial focal length value is not very accurate.

Fixed Internal Parameters

Should be used in calibrated environments only. Even if you know all the calibration parameters and set them in the camera calibrations object, it's usually better to let the pipeline slightly adjust them to the specific dataset.

See also
FlowEngine::CameraCalibrationInterface::setAdjustmentType
FlowEngine::CameraCalibrationInterface::AdjustmentType

Extra

Classification Models

Pre-trained Models

We offer the following pre-trained classification models:

Model Description Link
Buildings Pre-trained model for buildings classification Download
Trees Pre-trained model for trees classification Download
Roads Pre-trained model for roads classification Download

Please contact us if you need other models for specific workflows.

Point Classification APIs

FlowEngine offers 2 APIs to classify dense point clouds and 2 APIs to classify meshes vertexes. The two are identical except for the input object. One overload is higher-level while the second one more granular:

Masking Models

We offer the following pre-trained masking models:

Model Description Link
General Pre-trained model for general masking Download

Please contact us if you need other models for specific workflows.

Image Masking APIs

FlowEngine::computeAutomaticMasking


Support

For general enquiries, reach us at **support@3dflow.net**.

Registered users can open and track support tickets through their account on the 3Dflow website.