Skip to content

fuse_object_model_3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3dT_fuse_object_model_3d🔗

Short description🔗

fuse_object_model_3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3dT_fuse_object_model_3d — Fuse 3D object models into a surface.

Signature🔗

fuse_object_model_3d( object_model_3d ObjectModel3D, number BoundingBox, number Resolution, number SurfaceTolerance, number MinThickness, number Smoothing, string NormalDirection, attribute.name GenParamName, attribute.value GenParamValue, out object_model_3d ObjectModel3DFusion )void FuseObjectModel3d( const HTuple& ObjectModel3D, const HTuple& BoundingBox, const HTuple& Resolution, const HTuple& SurfaceTolerance, const HTuple& MinThickness, const HTuple& Smoothing, const HTuple& NormalDirection, const HTuple& GenParamName, const HTuple& GenParamValue, HTuple* ObjectModel3DFusion )static void HOperatorSet.FuseObjectModel3d( HTuple objectModel3D, HTuple boundingBox, HTuple resolution, HTuple surfaceTolerance, HTuple minThickness, HTuple smoothing, HTuple normalDirection, HTuple genParamName, HTuple genParamValue, out HTuple objectModel3DFusion )def fuse_object_model_3d( object_model_3d: MaybeSequence[HHandle], bounding_box: Sequence[Union[int, float]], resolution: Union[int, float], surface_tolerance: Union[int, float], min_thickness: Union[int, float], smoothing: Union[int, float], normal_direction: MaybeSequence[str], gen_param_name: Sequence[str], gen_param_value: Sequence[Union[str, float, int]] ) -> HHandle

Herror T_fuse_object_model_3d( const Htuple ObjectModel3D, const Htuple BoundingBox, const Htuple Resolution, const Htuple SurfaceTolerance, const Htuple MinThickness, const Htuple Smoothing, const Htuple NormalDirection, const Htuple GenParamName, const Htuple GenParamValue, Htuple* ObjectModel3DFusion )

static HObjectModel3D HObjectModel3D::FuseObjectModel3d( const HObjectModel3DArray& ObjectModel3D, const HTuple& BoundingBox, const HTuple& Resolution, const HTuple& SurfaceTolerance, const HTuple& MinThickness, const HTuple& Smoothing, const HTuple& NormalDirection, const HTuple& GenParamName, const HTuple& GenParamValue )

HObjectModel3D HObjectModel3D::FuseObjectModel3d( const HTuple& BoundingBox, double Resolution, double SurfaceTolerance, double MinThickness, double Smoothing, const HString& NormalDirection, const HTuple& GenParamName, const HTuple& GenParamValue ) const

HObjectModel3D HObjectModel3D::FuseObjectModel3d( const HTuple& BoundingBox, double Resolution, double SurfaceTolerance, double MinThickness, double Smoothing, const char* NormalDirection, const HTuple& GenParamName, const HTuple& GenParamValue ) const

HObjectModel3D HObjectModel3D::FuseObjectModel3d( const HTuple& BoundingBox, double Resolution, double SurfaceTolerance, double MinThickness, double Smoothing, const wchar_t* NormalDirection, const HTuple& GenParamName, const HTuple& GenParamValue ) const (Windows only)

static HObjectModel3D HObjectModel3D.FuseObjectModel3d( HObjectModel3D[] objectModel3D, HTuple boundingBox, HTuple resolution, HTuple surfaceTolerance, HTuple minThickness, HTuple smoothing, HTuple normalDirection, HTuple genParamName, HTuple genParamValue )

HObjectModel3D HObjectModel3D.FuseObjectModel3d( HTuple boundingBox, double resolution, double surfaceTolerance, double minThickness, double smoothing, string normalDirection, HTuple genParamName, HTuple genParamValue )

Description🔗

fuse_object_model_3dFuseObjectModel3d fuses multiple point clouds representing an object surface into a watertight surface ObjectModel3DFusionobjectModel3DFusionobject_model_3dfusion. The operator can be used to simplify the postprocessing step of point clouds that are already registered in the same coordinate system. In particular, unification, suppression of outliers, trade-off between smoothing and preservation of edges, equidistant sub-sampling, hole filling, and meshing of the output surface can often be handled nicely and in high quality. On the other hand, these advantages come at the price of a high runtime.

If you want to fuse 3D point clouds acquired by stereo reconstruction, you should use reconstruct_surface_stereoReconstructSurfaceStereo instead of fuse_object_model_3dFuseObjectModel3d.

Workflow🔗

  1. Acquire point clouds and transform them into a common coordinate system, for example using register_object_model_3d_pairRegisterObjectModel3dPair and register_object_model_3d_globalRegisterObjectModel3dGlobal.

  2. If not already available, compute triangles or point normals for the point clouds using triangulate_object_model_3dTriangulateObjectModel3d or surface_normals_object_model_3dSurfaceNormalsObjectModel3d. A triangulation is more suitable if you have surfaces with many outliers or holes that should be closed. Otherwise, for clean surfaces, you can work with normals.

  3. Inspect the normals of the input models using visualize_object_model_3d with GenParamNamegenParamNamegen_param_name 'disp_normals'"disp_normals" or dev_inspect_ctrl. The point or triangle normals have to be oriented consistently towards the inside or outside of the object. Set NormalDirectionnormalDirectionnormal_direction accordingly to 'inwards'"inwards" or 'outwards'"outwards".

  4. Specify the volume of interest in BoundingBoxboundingBoxbounding_box. To obtain a first guess for BoundingBoxboundingBoxbounding_box, use get_object_model_3d_paramsGetObjectModel3dParams with GenParamNamegenParamNamegen_param_name set to 'bounding_box1'"bounding_box1".

  5. Specify an initial set of parameters: a rough Resolutionresolutionresolution (e.g., 1/100 of the diameter of the BoundingBoxboundingBoxbounding_box), SurfaceTolerancesurfaceTolerancesurface_tolerance at least a bit larger (e.g., 5*Resolutionresolutionresolution), MinThicknessminThicknessmin_thickness as the minimum thickness of the object (if the input point clouds represent the object only from one side, set it very high, so that the object is cut off at the BoundingBoxboundingBoxbounding_box), Smoothingsmoothingsmoothing set to 1.01.0.

  6. Apply fuse_object_model_3dFuseObjectModel3d and readjust the parameters to improve the results with respect to quality and runtime, see below. Use a Resolutionresolutionresolution just fine enough to make out the details of your object while tuning the other parameters, in order to avoid long runtimes. Also consider using the additional parameters in GenParamNamegenParamNamegen_param_name.

Parameter Description🔗

See the HDevelop example fuse_object_model_3d_workflow for an explanation how to fine-tune the parameters for your application.

The input point clouds ObjectModel3DobjectModel3Dobject_model_3d have to lie in a common coordinate system and add up to the initial surface. Furthermore, they must contain triangles or point normals. If both attributes are present, normals are used as a default due to speed advantages. If triangles should be used, use copy_object_model_3dCopyObjectModel3d to obtain only point and triangle information. Surfaces with many outliers or holes to be closed should be used with a triangulation, clean surfaces with normals. The point or triangle normals have to be oriented consistently towards the inside or outside of the object.

NormalDirectionnormalDirectionnormal_direction is used to specify whether the point or triangle normals point 'inwards'"inwards" or 'outwards'"outwards". If only one value is specified, it is applied to all input models. Otherwise, the number of values has to equal the number of input models.

BoundingBoxboundingBoxbounding_box specifies the volume of interest to be taken into account for input and output. Note that points outside the bounding box are discarded. Triangles of the input point cloud with a point outside the BoundingBoxboundingBoxbounding_box are discarded, not clipped. The BoundingBoxboundingBoxbounding_box is specified as a tuple [x1,y1,z1,x2,y2,z2] assigning two opposite corner points P1=[x1,y1,z1] and P2=[x2,y2,z2] of the rectangular cuboid (with edges parallel to the coordinate axes). For a valid bounding box, P1 must be the point on the front lower left corner and P2 on the back upper right corner of the bounding box, i.e., x1<x2, y1<y2 and z1<z2. Note that the operator will try to produce a closed surface. If the input point clouds represent the object from only one point of view, one wants the bounding box usually to cut off the unknown part, wherefore MinThicknessminThicknessmin_thickness should be set e.g., to a value larger than or equal to the length of the diagonal of the bounding box (which can be obtained by using get_object_model_3d_paramsGetObjectModel3dParams with the parameter 'diameter_axis_aligned_bounding_box'"diameter_axis_aligned_bounding_box"). An object cut off by a surface of the bounding box has no points at this specific surface, thus has a hole. Note also that you may have to rotate the input point clouds in order make the bounding box cut off the unknown part in the right place, since the edges of the bounding box are always parallel to the coordinate axes. This can be achieved e.g., using affine_trans_object_model_3dAffineTransObjectModel3d or rigid_trans_object_model_3dRigidTransObjectModel3d.

Resolutionresolutionresolution specifies the distance of neighboring grid points in each coordinate direction in the discretization of the BoundingBoxboundingBoxbounding_box. Resolutionresolutionresolution is set in the same unit as used in ObjectModel3DobjectModel3Dobject_model_3d. Too small values will unnecessarily increase the runtime, so it is recommended to begin with a coarse resolution. Too large values will lead to a reconstruction with high loss of details. Smoothingsmoothingsmoothing may need to be adapted when Resolutionresolutionresolution is changed. Resolutionresolutionresolution should always be a bit smaller than SurfaceTolerancesurfaceTolerancesurface_tolerance in order to avoid discretization artifacts.

SurfaceTolerancesurfaceTolerancesurface_tolerance specifies how much noise in the input point cloud should be combined to the surface from its inside and outside. Sole exemption when SurfaceTolerancesurfaceTolerancesurface_tolerance is larger than 'distance_in_front'"distance_in_front", in that case 'distance_in_front'"distance_in_front" determines the surface thickness to the front of the object. SurfaceTolerancesurfaceTolerancesurface_tolerance is set in the same unit as used in ObjectModel3DobjectModel3Dobject_model_3d. Points in the interior of the object as specified by NormalDirectionnormalDirectionnormal_direction (and also GenParamNamegenParamNamegen_param_name='angle_threshold'"angle_threshold") are considered surely inside the object if their distance to the initial surface exceeds SurfaceTolerancesurfaceTolerancesurface_tolerance but is smaller than MinThicknessminThicknessmin_thickness. SurfaceTolerancesurfaceTolerancesurface_tolerance always has to be smaller than MinThicknessminThicknessmin_thickness. SurfaceTolerancesurfaceTolerancesurface_tolerance should always be a bit larger than Resolutionresolutionresolution in order to avoid discretization artifacts.

MinThicknessminThicknessmin_thickness specifies the thickness of the object in normal direction of the initial surfaces. MinThicknessminThicknessmin_thickness is set in the same unit as used in ObjectModel3DobjectModel3Dobject_model_3d. Points which are specified by NormalDirectionnormalDirectionnormal_direction (and also GenParamNamegenParamNamegen_param_name='angle_threshold'"angle_threshold") to be in the interior of the object are only considered as being inside if their distance to the initial surface does not exceed MinThicknessminThicknessmin_thickness. Note that this can lead to a hollow part of the object. MinThicknessminThicknessmin_thickness always has to be larger than SurfaceTolerancesurfaceTolerancesurface_tolerance. For point clouds representing the object from different sides, MinThicknessminThicknessmin_thickness is best set as the thickness of the objects narrowest part. Note that the operator will try to produce a closed surface. If the input point clouds represent the object only from one side, this parameter should be set very large, so that the object is cut off at the bounding box. The backside of the objects is not observed and thus its reconstruction will probably be incorrect. If you observe several distinct objects from only one side, you may want to reduce the parameter MinThicknessminThicknessmin_thickness to restrict the depth of reconstructed objects and thus keep them from being smudged into one surface. Too small values can result in holes or double walls in the fused point cloud. Too large values can result in a distorted point cloud or blow up the surface towards the outside of the object (if the surface is blown up beyond the bounding box, no points will be returned).

 
(1) (2)

Schematic view of the parameters SurfaceTolerancesurfaceTolerancesurface_tolerance, MinThicknessminThicknessmin_thickness and the value 'distance_in_front'"distance_in_front" with the aid of an example surface (_.): o are points taken as outside, s are points of the surface, i are points surely inside the object, c are points also considered for the evaluation of the surface. (1): 'distance_in_front'"distance_in_front" smaller than SurfaceTolerancesurfaceTolerancesurface_tolerance (2): 'distance_in_front'"distance_in_front" larger than SurfaceTolerancesurfaceTolerancesurface_tolerance.

Smoothingsmoothingsmoothing determines how important a small total variation of the distance function is compared to data fidelity. Thus, Smoothingsmoothingsmoothing regulates the ‘jumpiness’ of the resulting surface. Note that the actual value of Smoothingsmoothingsmoothing for a given data to result in an appropriate and visually pleasing surface has to be found by trial and error. Too small values lead to integrating many outliers into the surface even if the surface then exhibits many jumps. Too large values lead to lost fidelity towards the input point clouds (how the algorithm views distances to the input point clouds depends heavily on SurfaceTolerancesurfaceTolerancesurface_tolerance and MinThicknessminThicknessmin_thickness). Smoothingsmoothingsmoothing may need to be adapted when Resolutionresolutionresolution is changed.

By setting GenParamNamegenParamNamegen_param_name to the following values, the additional parameters can be set with GenParamValuegenParamValuegen_param_value:

  • 'distance_in_front'"distance_in_front" Points in the exterior of the object as specified by NormalDirectionnormalDirectionnormal_direction (and also GenParamNamegenParamNamegen_param_name='angle_threshold'"angle_threshold") are only considered as part of the object if their distance to the initial surface does not exceed 'distance_in_front'"distance_in_front". This is the outside analogous to MinThicknessminThicknessmin_thickness of the interior, except that 'distance_in_front'"distance_in_front" does not have to be larger than SurfaceTolerancesurfaceTolerancesurface_tolerance. In case 'distance_in_front'"distance_in_front" is smaller than SurfaceTolerancesurfaceTolerancesurface_tolerance it determines the surface thickness to the front. This parameter is useful if holes in the surface should be closed along a jump in the surface (for example along the viewing direction of the sensor). In this case, 'distance_in_front'"distance_in_front" can be set to a small value in order to avoid a wrong initialization of the distance field. 'distance_in_front'"distance_in_front" is set in the same unit as used in ObjectModel3DobjectModel3Dobject_model_3d. 'distance_in_front'"distance_in_front" should always be a bit larger than Resolutionresolutionresolution in order to avoid discretization artifacts. Per default, 'distance_in_front'"distance_in_front" is set to a value larger than the bounding box diameter, therewith all points outside of the object in the bounding box are considered.

    Suggested values: 0.0010.001, 0.10.1, 11, 1010.

    Default: Larger than the bounding box diameter.

    Restriction: 'distance_in_front'"distance_in_front" > 0

  • 'angle_threshold'"angle_threshold" specifies the angle of a cone around a surface normal. 'angle_threshold'"angle_threshold" is set in [rad]. When determining the distance information for data fidelity, only points are considered lying in such a cone starting at their closest surface point. For example, if distances to triangles are considered, 'angle_threshold'"angle_threshold" can be set to 0.00.0, so that only the volume directly above the triangle is considered (thus a right prism). If point normals are used and thus distances to normals are considered, 'angle_threshold'"angle_threshold" has to be set to a higher value. When outliers disrupt the result, decreasing 'angle_threshold'"angle_threshold" may help. If holes in the surface should be closed along a jump in the surface (for example along the viewing direction of the sensor), enlarging 'angle_threshold'"angle_threshold" may help.

    Suggested values: 'rad(0.0)'"rad(0.0)", 'rad(10.0)'"rad(10.0)", 'rad(30.0)'"rad(30.0)".

    Default: 'rad(10.0)'"rad(10.0)".

    Restriction: 'angle_threshold'"angle_threshold" >= 0

  • 'point_meshing'"point_meshing" determines whether the output points should be triangulated with the algorithm ‘marching tetrahedra’, which can be activated by setting 'point_meshing'"point_meshing" to 'isosurface'"isosurface". Note that there are more points in ObjectModel3DFusionobjectModel3DFusionobject_model_3dfusion if meshing of the isosurface is enabled even if the used Resolutionresolutionresolution is the same.

    List of values: 'none'"none", 'isosurface'"isosurface".

    Default: 'isosurface'"isosurface".

Fusion algorithm🔗

The algorithm will produce a watertight, closed surface (which is maybe cut off at the BoundingBoxboundingBoxbounding_box). The goal is to obtain a preferably smooth surface while keeping form fidelity. To this end, the bounding box is sampled and each sample point is assigned an initial distance to a so-called isosurface (consisting of points with distance 0). The final distance values (and thus the isosurface) are obtained by minimizing an error function based on fidelity to the initial point clouds on the one hand and total variation (‘jumpiness’) of the distance function on the other hand. This leads to a fusion of the input point clouds (see paper in References below).

The calculation of the isosurface can be influenced with the parameters of the operator. The distance between sample points in the bounding box (in each coordinate direction) can be set with the parameter Resolutionresolutionresolution.

Fidelity to the initial point clouds is grasped as the signed distances of sample points, lying on the grid, in the bounding box to their nearest neighbors (points or triangles) on the input point clouds. Whether a sample point in the bounding box is considered to lie outside or inside the object (the sign of the distance) is determined by the normal of its nearest neighbor on the initial surface and the set NormalDirectionnormalDirectionnormal_direction. To determine if a sample point is surely inside or outside the object with respect to an input point cloud, the distance to its nearest neighbor on the initial surface is determined. A point on the inside is considered surely inside if the distance exceeds SurfaceTolerancesurfaceTolerancesurface_tolerance but not MinThicknessminThicknessmin_thickness, while a point on the outside counts as exteriorly if the distance exceeds 'distance_in_front'"distance_in_front".

Fidelity to the initial point clouds is only considered for those sample points lying within MinThicknessminThicknessmin_thickness inside or within GenParamNamegenParamNamegen_param_name 'distance_in_front'"distance_in_front" outside the initial surface.

Furthermore, fidelity is not maintained for a given sample point lying outside a cone around GenParamNamegenParamNamegen_param_name 'angle_threshold'"angle_threshold". Thus it is not maintained if the line from the sample point to its nearest neighbor on the initial surface differs from the surface normal of the nearest neighbor by an angle more than GenParamNamegenParamNamegen_param_name 'angle_threshold'"angle_threshold". Note that the distances to nearest neighboring triangles will often yield more satisfying results while distances to nearest points can be calculated much faster.

The subsequent optimization of the distance values is the same as the one used in reconstruct_surface_stereoReconstructSurfaceStereo with Methodmethodmethod='surface_fusion'"surface_fusion".

The parameter Smoothingsmoothingsmoothing regulates the ‘jumpiness’ of the distance function by weighing the two terms in the error function: Fidelity to the initial point clouds on the one hand, total variation of the distance function on the other hand. Note that the actual value of Smoothingsmoothingsmoothing for a given data set to be visually pleasing has to be found by trial and error.

Each 3D point of the object model returned in ObjectModel3DFusionobjectModel3DFusionobject_model_3dfusion is extracted from the isosurface where the distance function equals zero. Its normal vector is calculated from the gradient of the distance function. The so-obtained point cloud can also be meshed using the algorithm ‘marching tetrahedra’ by setting the GenParamNamegenParamNamegen_param_name 'point_meshing'"point_meshing" to the GenParamValuegenParamValuegen_param_value 'isosurface'"isosurface".

Troubleshooting🔗

Please follow the workflow above. If the results are not satisfactory, please consult the following hints and ideas:

Runtime🔗

In order to improve the runtime, consider the following hints:

Execution information🔗

Execution information
  • Multithreading type: reentrant (runs in parallel with non-exclusive operators).

  • Multithreading scope: global (may be called from any thread).

  • Automatically parallelized on internal data level.

Parameters🔗

ObjectModel3DobjectModel3Dobject_model_3d (input_control) object_model_3d(-array) → (handle)HTuple (HHandle)HObjectModel3D, HTuple (IntPtr)MaybeSequence[HHandle]Htuple (handle)

Handles of the 3D object models.

BoundingBoxboundingBoxbounding_box (input_control) number-array → (real / integer)HTuple (double / Hlong)HTuple (double / int / long)Sequence[Union[int, float]]Htuple (double / Hlong)

The two opposite bound box corners.

Resolutionresolutionresolution (input_control) number → (real / integer)HTuple (double / Hlong)HTuple (double / int / long)Union[int, float]Htuple (double / Hlong)

Used resolution within the bounding box.

Default: 1.01.0
Suggested values: 1.0, 1.1, 1.5, 10.0, 100.01.0, 1.1, 1.5, 10.0, 100.0

SurfaceTolerancesurfaceTolerancesurface_tolerance (input_control) number → (real / integer)HTuple (double / Hlong)HTuple (double / int / long)Union[int, float]Htuple (double / Hlong)

Distance of expected noise to surface.

Default: 1.01.0
Suggested values: 1.0, 1.1, 1.5, 10.0, 100.01.0, 1.1, 1.5, 10.0, 100.0

MinThicknessminThicknessmin_thickness (input_control) number → (real / integer)HTuple (double / Hlong)HTuple (double / int / long)Union[int, float]Htuple (double / Hlong)

Minimum thickness of the object in direction of the surface normal.

Default: 1.01.0
Suggested values: 1.0, 1.1, 1.5, 10.0, 100.01.0, 1.1, 1.5, 10.0, 100.0

Smoothingsmoothingsmoothing (input_control) number → (real / integer)HTuple (double / Hlong)HTuple (double / int / long)Union[int, float]Htuple (double / Hlong)

Weight factor for data fidelity.

Default: 1.01.0
Suggested values: 1.0, 1.1, 1.5, 10.0, 100.01.0, 1.1, 1.5, 10.0, 100.0

NormalDirectionnormalDirectionnormal_direction (input_control) string(-array) → (string)HTuple (HString)HTuple (string)MaybeSequence[str]Htuple (char*)

Direction of normals of the input models.

Default: 'inwards'"inwards"
List of values: 'inwards', 'outwards'"inwards", "outwards"

GenParamNamegenParamNamegen_param_name (input_control) attribute.name-array → (string)HTuple (HString)HTuple (string)Sequence[str]Htuple (char*)

Name of the generic parameter.

Default: [][]
List of values: 'angle_threshold', 'distance_in_front', 'point_meshing'"angle_threshold", "distance_in_front", "point_meshing"

GenParamValuegenParamValuegen_param_value (input_control) attribute.value-array → (string / real / integer)HTuple (HString / double / Hlong)HTuple (string / double / int / long)Sequence[Union[str, float, int]]Htuple (char* / double / Hlong)

Value of the generic parameter.

Default: [][]
Suggested values: 'isosurface', 'none', 0.0, 0.1, 0.175, 0.524"isosurface", "none", 0.0, 0.1, 0.175, 0.524

ObjectModel3DFusionobjectModel3DFusionobject_model_3dfusion (output_control) object_model_3d → (handle)HTuple (HHandle)HObjectModel3D, HTuple (IntPtr)HHandleHtuple (handle)

Handle of the fused 3D object model.

Result🔗

fuse_object_model_3dFuseObjectModel3d returns 2 (H_MSG_TRUE) if all parameters are correct. If necessary, an exception is raised.

Combinations with other operators🔗

Combinations

Possible predecessors

read_object_model_3dReadObjectModel3d, register_object_model_3d_pairRegisterObjectModel3dPair, register_object_model_3d_globalRegisterObjectModel3dGlobal, surface_normals_object_model_3dSurfaceNormalsObjectModel3d, triangulate_object_model_3dTriangulateObjectModel3d, simplify_object_model_3dSimplifyObjectModel3d, get_object_model_3d_paramsGetObjectModel3dParams

Possible successors

write_object_model_3dWriteObjectModel3d, create_surface_modelCreateSurfaceModel

See also

reconstruct_surface_stereoReconstructSurfaceStereo

References🔗

C. Zach, T. Pock, and H. Bischof: ``A globally optimal algorithm for robust TV-L1 range image integration.’’ Proceedings of IEEE International Conference on Computer Vision (ICCV 2007).

Module🔗

3D Metrology