FlowEngine 7.517
Photogrammetry Software Development Kit
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
  2. Licensing and Activation
    1. Activation
    2. Free Version Limitations
    3. Licensing
  3. API
    1. Objects
    2. Conventions
    3. Error Handling
    4. Data Structures
    5. Utilities
  4. Quick Start
  5. Examples
    1. Building
  6. Computation Settings
    1. Settings
    2. Settings Manager
    3. Computation Presets
    4. Bundle Adjustment Settings
  7. Tips
    1. Initial Camera Calibration Parameters
    2. Computation Presets




Follow the instructions to build the examples.

Run Visual Studio as Adminstrator and build the project INSTALL in configuration Release.

The default installation directory is

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



See the instructions to build the Examples.

Alternatively, you can type the following from the SDK root directory:

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

Debian package

You can install FlowEngine with the supplied deb package.

Via command line:

sudo dpkg -i FlowEngine_@version@.deb

replace @version@ with the version you have.

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 2103

To cleanup previous information:

FlowEngineLicenser flserver clear


  • You might need Administrator priviledges 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


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 distribuited with the SDK (see section Utilities)


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.


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 applicabile, 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 applicabile, 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 succesfully 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.

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 succesfull 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.

See also

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 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


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

See also

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
UniqueWorkspaceSaverPtr workspaceSaver( CreateWorkspaceSaver() );
CheckResult( stereoTexturedMesh->saveToObj( "test.obj" ), logListener );


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

The included samples can be easily compiled with CMake.

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.

Only 64 bits builds are supported.


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, then specify the generator (e.g. Visual Studio 15 2017 Win64) and then Finish.
  4. After the configuring process, click the Generate button and then Open Project.


We suggest to use cmake via command line.

A convenient script is included in the package:


will build the examples and install the library in the default user path.


  • remember to set execution permission to the file.
  • you may need sudo priviledges to successfully run the script.

Examples are built in the "redist" folder.

Alternatively you can follow the usual cmake generation procedure to just build the examples:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..

and then

sudo make install

to install the library.


  • FlowEngine library should be available in the linker path in order for the examples to work. Either follow the installation instructions or run sudo make install from the build folder.
  • FlowEngine depends on ImageMagick version >= 7.0.0 and it should be installed on your system.

    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 -j8
      sudo make install
      sudo ldconfig /usr/local/lib

Computation Settings


You can set all the computation settings through the FlowCore::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 specilized for low polygon meshes


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


  • 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.


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

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.


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