fuse_object_model_3dT_fuse_object_model_3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3d (Operator)

Name

fuse_object_model_3dT_fuse_object_model_3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3d — Fuse 3D object models into a surface.

Signature

fuse_object_model_3d( : : ObjectModel3D, BoundingBox, Resolution, SurfaceTolerance, MinThickness, Smoothing, NormalDirection, GenParamName, GenParamValue : ObjectModel3DFusion)

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)

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 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 void HOperatorSet.FuseObjectModel3d(HTuple objectModel3D, HTuple boundingBox, HTuple resolution, HTuple surfaceTolerance, HTuple minThickness, HTuple smoothing, HTuple normalDirection, HTuple genParamName, HTuple genParamValue, out HTuple objectModel3DFusion)

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)

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

Description

fuse_object_model_3dfuse_object_model_3dFuseObjectModel3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3d fuses multiple point clouds representing an object surface into a watertight surface ObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionobjectModel3DFusionobject_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_stereoreconstruct_surface_stereoReconstructSurfaceStereoReconstructSurfaceStereoReconstructSurfaceStereoreconstruct_surface_stereo instead of fuse_object_model_3dfuse_object_model_3dFuseObjectModel3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3d.

Workflow

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

  2. If not already available, compute triangles or point normals for the point clouds using triangulate_object_model_3dtriangulate_object_model_3dTriangulateObjectModel3dTriangulateObjectModel3dTriangulateObjectModel3dtriangulate_object_model_3d or surface_normals_object_model_3dsurface_normals_object_model_3dSurfaceNormalsObjectModel3dSurfaceNormalsObjectModel3dSurfaceNormalsObjectModel3dsurface_normals_object_model_3d. 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 GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'disp_normals'"disp_normals""disp_normals""disp_normals""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 NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_direction accordingly to 'inwards'"inwards""inwards""inwards""inwards""inwards" or 'outwards'"outwards""outwards""outwards""outwards""outwards".

  4. Specify the volume of interest in BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box. To obtain a first guess for BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box, use get_object_model_3d_paramsget_object_model_3d_paramsGetObjectModel3dParamsGetObjectModel3dParamsGetObjectModel3dParamsget_object_model_3d_params with GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name set to 'bounding_box1'"bounding_box1""bounding_box1""bounding_box1""bounding_box1""bounding_box1".

  5. Specify an initial set of parameters: a rough ResolutionResolutionResolutionResolutionresolutionresolution (e.g., 1/100 of the diameter of the BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box), SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance at least a bit larger (e.g., 5*ResolutionResolutionResolutionResolutionresolutionresolution), MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_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 BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box), SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing set to 1.0.

  6. Apply fuse_object_model_3dfuse_object_model_3dFuseObjectModel3dFuseObjectModel3dFuseObjectModel3dfuse_object_model_3d and readjust the parameters to improve the results with respect to quality and runtime, see below. Use a ResolutionResolutionResolutionResolutionresolutionresolution 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 GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_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 ObjectModel3DObjectModel3DObjectModel3DObjectModel3DobjectModel3Dobject_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_3dcopy_object_model_3dCopyObjectModel3dCopyObjectModel3dCopyObjectModel3dcopy_object_model_3d 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.

NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_direction is used to specify whether the point or triangle normals point 'inwards'"inwards""inwards""inwards""inwards""inwards" or 'outwards'"outwards""outwards""outwards""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.

BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_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 BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box are discarded, not clipped. The BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_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 MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_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_paramsget_object_model_3d_paramsGetObjectModel3dParamsGetObjectModel3dParamsGetObjectModel3dParamsget_object_model_3d_params with the parameter 'diameter_axis_aligned_bounding_box'"diameter_axis_aligned_bounding_box""diameter_axis_aligned_bounding_box""diameter_axis_aligned_bounding_box""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_3daffine_trans_object_model_3dAffineTransObjectModel3dAffineTransObjectModel3dAffineTransObjectModel3daffine_trans_object_model_3d or rigid_trans_object_model_3drigid_trans_object_model_3dRigidTransObjectModel3dRigidTransObjectModel3dRigidTransObjectModel3drigid_trans_object_model_3d.

ResolutionResolutionResolutionResolutionresolutionresolution specifies the distance of neighboring grid points in each coordinate direction in the discretization of the BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box. ResolutionResolutionResolutionResolutionresolutionresolution is set in the same unit as used in ObjectModel3DObjectModel3DObjectModel3DObjectModel3DobjectModel3Dobject_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. SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing may need to be adapted when ResolutionResolutionResolutionResolutionresolutionresolution is changed. ResolutionResolutionResolutionResolutionresolutionresolution should always be a bit smaller than SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance in order to avoid discretization artifacts.

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

MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness specifies the thickness of the object in normal direction of the initial surfaces. MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness is set in the same unit as used in ObjectModel3DObjectModel3DObjectModel3DObjectModel3DobjectModel3Dobject_model_3d. Points which are specified by NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_direction (and also GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name='angle_threshold'"angle_threshold""angle_threshold""angle_threshold""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 MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness. Note that this can lead to a hollow part of the object. MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness always has to be larger than SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance. For point clouds representing the object from different sides, MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_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 MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_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).

SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing determines how important a small total variation of the distance function is compared to data fidelity. Thus, SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing regulates the 'jumpiness' of the resulting surface. Note that the actual value of SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing 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 SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance and MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness). SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing may need to be adapted when ResolutionResolutionResolutionResolutionresolutionresolution is changed.

image/svg+xml SurfaceTolerance MinThickness s o o o o o o c i i i i i s s s s s s s s s s s s s s s s s s s c o c c o i i i i i i i c s o o . . SurfaceTolerance 'distance_in_front' s s image/svg+xml SurfaceTolerance MinThickness s o o o o o o o i i i i i s s s s s s s s s s s s s s s s s s s o o o o o i i i i i i i o o o o . . SurfaceTolerance 'distance_in_front' o o
(1) (2)
Schematic view of the parameters SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance, MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness and the value 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""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""distance_in_front""distance_in_front""distance_in_front""distance_in_front" smaller than SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance (2): 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" larger than SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance.

By setting GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name to the following values, the additional parameters can be set with GenParamValueGenParamValueGenParamValueGenParamValuegenParamValuegen_param_value:

'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front"

Points in the exterior of the object as specified by NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_direction (and also GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name='angle_threshold'"angle_threshold""angle_threshold""angle_threshold""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""distance_in_front""distance_in_front""distance_in_front""distance_in_front". This is the outside analogous to MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness of the interior, except that 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" does not have to be larger than SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance. In case 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" is smaller than SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_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""distance_in_front""distance_in_front""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""distance_in_front""distance_in_front""distance_in_front""distance_in_front" is set in the same unit as used in ObjectModel3DObjectModel3DObjectModel3DObjectModel3DobjectModel3Dobject_model_3d. 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" should always be a bit larger than ResolutionResolutionResolutionResolutionresolutionresolution in order to avoid discretization artifacts. Per default, 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""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.001, 0.1, 1, 10.

Default value: Larger than the bounding box diameter.

Assertion: 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" > 0

'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""angle_threshold""angle_threshold"

specifies the angle of a cone around a surface normal. 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""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""angle_threshold""angle_threshold""angle_threshold""angle_threshold" can be set to 0.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""angle_threshold""angle_threshold""angle_threshold""angle_threshold" has to be set to a higher value. When outliers disrupt the result, decreasing 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""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""angle_threshold""angle_threshold""angle_threshold""angle_threshold" may help.

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

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

Assertion: 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""angle_threshold""angle_threshold" >= 0

'point_meshing'"point_meshing""point_meshing""point_meshing""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""point_meshing""point_meshing""point_meshing""point_meshing" to 'isosurface'"isosurface""isosurface""isosurface""isosurface""isosurface". Note that there are more points in ObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionobjectModel3DFusionobject_model_3dfusion if meshing of the isosurface is enabled even if the used ResolutionResolutionResolutionResolutionresolutionresolution is the same.

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

Default value: 'isosurface'"isosurface""isosurface""isosurface""isosurface""isosurface".

Fusion algorithm

The algorithm will produce a watertight, closed surface (which is maybe cut off at the BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_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 ResolutionResolutionResolutionResolutionresolutionresolution.

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 NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_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 SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance but not MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness, while a point on the outside counts as exteriorly if the distance exceeds 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front".

Fidelity to the initial point clouds is only considered for those sample points lying within MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness inside or within GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""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 GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""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 GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""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_stereoreconstruct_surface_stereoReconstructSurfaceStereoReconstructSurfaceStereoReconstructSurfaceStereoreconstruct_surface_stereo with MethodMethodMethodMethodmethodmethod='surface_fusion'"surface_fusion""surface_fusion""surface_fusion""surface_fusion""surface_fusion".

The parameter SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing 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 SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing 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 ObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionobjectModel3DFusionobject_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 GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'point_meshing'"point_meshing""point_meshing""point_meshing""point_meshing""point_meshing" to the GenParamValueGenParamValueGenParamValueGenParamValuegenParamValuegen_param_value 'isosurface'"isosurface""isosurface""isosurface""isosurface""isosurface".

Troubleshooting

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

Quality of the input point clouds

The input point clouds should represent the entire object surface. If point normals are used, the points should be dense on the entire surface, not only along edges of the object. In particular, for CAD-data typically triangulation has to be used.

Used attribute

Using triangles instead of point normals will typically yield results of higher quality. If both attributes are present, point normals are used per default. If triangles should be used, use copy_object_model_3dcopy_object_model_3dCopyObjectModel3dCopyObjectModel3dCopyObjectModel3dcopy_object_model_3d to obtain only point and triangle information.

Outliers

If outliers of the input models disturb the output surface even for high values of SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing, try to decrease GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""angle_threshold""angle_threshold". If wanted, outliers of the input models can also be removed, for example using connection_object_model_3dconnection_object_model_3dConnectionObjectModel3dConnectionObjectModel3dConnectionObjectModel3dconnection_object_model_3d. With reduced influence also modifying GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" may help to reduce certain outliers.

Closing of holes

If holes in the surface are not closed even for high values of SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing (for example a jump in the surface along the viewing direction of the sensor), try to decrease GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front". Enlarging GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""angle_threshold""angle_threshold" may help the algorithm to close the gap. Note that triangulate_object_model_3dtriangulate_object_model_3dTriangulateObjectModel3dTriangulateObjectModel3dTriangulateObjectModel3dtriangulate_object_model_3d can close gaps when triangulating sensor data which contains a 2D mapping.

Empty output

If the output contains no point, try to decrease SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing. If there is no output even for very low values of SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing, you may want to check if MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness is set too large and if the set NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_direction is correct.

Runtime

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

Extent of the bounding box

The bounding box should be tight around the volume of interest. Else, the runtime will increase drastically but without any benefit.

Resolution

Enlarging the parameter ResolutionResolutionResolutionResolutionresolutionresolution will speed up the execution considerably.

Used attribute

Using point normals instead of triangles will speed up the execution. If both, normals and triangles, are present in the input models, normals are used per default.

Density of input point clouds

The input point clouds can be thinned out using sample_object_model_3dsample_object_model_3dSampleObjectModel3dSampleObjectModel3dSampleObjectModel3dsample_object_model_3d (if normals are used) or simplify_object_model_3dsimplify_object_model_3dSimplifyObjectModel3dSimplifyObjectModel3dSimplifyObjectModel3dsimplify_object_model_3d with GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'avoid_triangle_flips'"avoid_triangle_flips""avoid_triangle_flips""avoid_triangle_flips""avoid_triangle_flips""avoid_triangle_flips" set to 'true'"true""true""true""true""true" (if triangles are used).

Distances to surface

Make sure that MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness and GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front" are not set unnecessarily large, since this can slow down the preparation and distance computation.

Execution Information

Parameters

ObjectModel3DObjectModel3DObjectModel3DObjectModel3DobjectModel3Dobject_model_3d (input_control)  object_model_3d(-array) HObjectModel3D, HTupleMaybeSequence[HHandle]HTupleHtuple (handle) (IntPtr) (HHandle) (handle)

Handles of the 3D object models.

BoundingBoxBoundingBoxBoundingBoxBoundingBoxboundingBoxbounding_box (input_control)  number-array HTupleSequence[Union[int, float]]HTupleHtuple (real / integer) (double / int / long) (double / Hlong) (double / Hlong)

The two opposite bound box corners.

ResolutionResolutionResolutionResolutionresolutionresolution (input_control)  number HTupleUnion[int, float]HTupleHtuple (real / integer) (double / int / long) (double / Hlong) (double / Hlong)

Used resolution within the bounding box.

Default value: 1.0

Suggested values: 1.0, 1.1, 1.5, 10.0, 100.0

SurfaceToleranceSurfaceToleranceSurfaceToleranceSurfaceTolerancesurfaceTolerancesurface_tolerance (input_control)  number HTupleUnion[int, float]HTupleHtuple (real / integer) (double / int / long) (double / Hlong) (double / Hlong)

Distance of expected noise to surface.

Default value: 1.0

Suggested values: 1.0, 1.1, 1.5, 10.0, 100.0

MinThicknessMinThicknessMinThicknessMinThicknessminThicknessmin_thickness (input_control)  number HTupleUnion[int, float]HTupleHtuple (real / integer) (double / int / long) (double / Hlong) (double / Hlong)

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

Default value: 1.0

Suggested values: 1.0, 1.1, 1.5, 10.0, 100.0

SmoothingSmoothingSmoothingSmoothingsmoothingsmoothing (input_control)  number HTupleUnion[int, float]HTupleHtuple (real / integer) (double / int / long) (double / Hlong) (double / Hlong)

Weight factor for data fidelity.

Default value: 1.0

Suggested values: 1.0, 1.1, 1.5, 10.0, 100.0

NormalDirectionNormalDirectionNormalDirectionNormalDirectionnormalDirectionnormal_direction (input_control)  string(-array) HTupleMaybeSequence[str]HTupleHtuple (string) (string) (HString) (char*)

Direction of normals of the input models.

Default value: 'inwards' "inwards" "inwards" "inwards" "inwards" "inwards"

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

GenParamNameGenParamNameGenParamNameGenParamNamegenParamNamegen_param_name (input_control)  attribute.name-array HTupleSequence[str]HTupleHtuple (string) (string) (HString) (char*)

Name of the generic parameter.

Default value: []

List of values: 'angle_threshold'"angle_threshold""angle_threshold""angle_threshold""angle_threshold""angle_threshold", 'distance_in_front'"distance_in_front""distance_in_front""distance_in_front""distance_in_front""distance_in_front", 'point_meshing'"point_meshing""point_meshing""point_meshing""point_meshing""point_meshing"

GenParamValueGenParamValueGenParamValueGenParamValuegenParamValuegen_param_value (input_control)  attribute.value-array HTupleSequence[Union[str, float, int]]HTupleHtuple (string / real / integer) (string / double / int / long) (HString / double / Hlong) (char* / double / Hlong)

Value of the generic parameter.

Default value: []

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

ObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionObjectModel3DFusionobjectModel3DFusionobject_model_3dfusion (output_control)  object_model_3d HObjectModel3D, HTupleHHandleHTupleHtuple (handle) (IntPtr) (HHandle) (handle)

Handle of the fused 3D object model.

Result

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

Possible Predecessors

read_object_model_3dread_object_model_3dReadObjectModel3dReadObjectModel3dReadObjectModel3dread_object_model_3d, register_object_model_3d_pairregister_object_model_3d_pairRegisterObjectModel3dPairRegisterObjectModel3dPairRegisterObjectModel3dPairregister_object_model_3d_pair, register_object_model_3d_globalregister_object_model_3d_globalRegisterObjectModel3dGlobalRegisterObjectModel3dGlobalRegisterObjectModel3dGlobalregister_object_model_3d_global, surface_normals_object_model_3dsurface_normals_object_model_3dSurfaceNormalsObjectModel3dSurfaceNormalsObjectModel3dSurfaceNormalsObjectModel3dsurface_normals_object_model_3d, triangulate_object_model_3dtriangulate_object_model_3dTriangulateObjectModel3dTriangulateObjectModel3dTriangulateObjectModel3dtriangulate_object_model_3d, simplify_object_model_3dsimplify_object_model_3dSimplifyObjectModel3dSimplifyObjectModel3dSimplifyObjectModel3dsimplify_object_model_3d, get_object_model_3d_paramsget_object_model_3d_paramsGetObjectModel3dParamsGetObjectModel3dParamsGetObjectModel3dParamsget_object_model_3d_params

Possible Successors

write_object_model_3dwrite_object_model_3dWriteObjectModel3dWriteObjectModel3dWriteObjectModel3dwrite_object_model_3d, create_surface_modelcreate_surface_modelCreateSurfaceModelCreateSurfaceModelCreateSurfaceModelcreate_surface_model

See also

reconstruct_surface_stereoreconstruct_surface_stereoReconstructSurfaceStereoReconstructSurfaceStereoReconstructSurfaceStereoreconstruct_surface_stereo

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