ImageDev

SurfaceFitting3d

Adjusts the positions of the vertices of a structured quadrilateral mesh according to weights provided by a volume.

Access to parameter description

The weights given by the input volume intensities characterize the features or structures on which the input surface must be fitted. For instance, weights can be the distance to a wall to approximate.

This algorithm searches for a best fit along a direction specified for each vertex up to a distance defined by the distance parameter.
A voxel is considered as a best fit based on a criterion given by the fittingCriterion parameter.
A regularization can be applied on the resulting surface to smooth it and limit the effect of outliers.

See also

Function Syntax

This function returns outputSurface.
// Function prototype
std::shared_ptr<iolink::ArrayXd> surfaceFitting3d( std::shared_ptr< iolink::ImageView > inputIntensityImage, std::shared_ptr<iolink::ArrayXd> inputSurface, std::shared_ptr<iolink::ArrayXd> directions, double distance, iolink::Vector2d thresholdRange, double smoothing, SurfaceFitting3d::FittingCriterion fittingCriterion, SurfaceFitting3d::BoundaryCondition topBoundaryCondition, SurfaceFitting3d::BoundaryCondition bottomBoundaryCondition, SurfaceFitting3d::BoundaryCondition leftBoundaryCondition, SurfaceFitting3d::BoundaryCondition rightBoundaryCondition, SurfaceFitting3d::RegularizationType regularizationType, iolink::Vector4d dirichletValues, std::shared_ptr<iolink::ArrayXd> outputSurface = NULL );
This function returns outputSurface.
// Function prototype.
surface_fitting_3d( input_intensity_image,
                    input_surface,
                    directions,
                    distance = 1,
                    threshold_range = [0, 1.7976931348623157e+308],
                    smoothing = 1,
                    fitting_criterion = SurfaceFitting3d.FittingCriterion.MAXIMUM,
                    top_boundary_condition = SurfaceFitting3d.BoundaryCondition.NEUMANN,
                    bottom_boundary_condition = SurfaceFitting3d.BoundaryCondition.NEUMANN,
                    left_boundary_condition = SurfaceFitting3d.BoundaryCondition.NEUMANN,
                    right_boundary_condition = SurfaceFitting3d.BoundaryCondition.NEUMANN,
                    regularization_type = SurfaceFitting3d.RegularizationType.LAPLACIAN,
                    dirichlet_values = [0, 0, 0, 0],
                    output_surface = None )
This function returns outputSurface.
// Function prototype.
public static IOLink.ArrayXd
SurfaceFitting3d( IOLink.ImageView inputIntensityImage,
                  IOLink.ArrayXd inputSurface,
                  IOLink.ArrayXd directions,
                  double distance = 1,
                  double[] thresholdRange = null,
                  double smoothing = 1,
                  SurfaceFitting3d.FittingCriterion fittingCriterion = ImageDev.SurfaceFitting3d.FittingCriterion.MAXIMUM,
                  SurfaceFitting3d.BoundaryCondition topBoundaryCondition = ImageDev.SurfaceFitting3d.BoundaryCondition.NEUMANN,
                  SurfaceFitting3d.BoundaryCondition bottomBoundaryCondition = ImageDev.SurfaceFitting3d.BoundaryCondition.NEUMANN,
                  SurfaceFitting3d.BoundaryCondition leftBoundaryCondition = ImageDev.SurfaceFitting3d.BoundaryCondition.NEUMANN,
                  SurfaceFitting3d.BoundaryCondition rightBoundaryCondition = ImageDev.SurfaceFitting3d.BoundaryCondition.NEUMANN,
                  SurfaceFitting3d.RegularizationType regularizationType = ImageDev.SurfaceFitting3d.RegularizationType.LAPLACIAN,
                  double[] dirichletValues = null,
                  IOLink.ArrayXd outputSurface = null );

Class Syntax

Parameters

Class Name SurfaceFitting3d

Parameter Name Description Type Supported Values Default Value
input
inputSurface
The input mesh that represents the surface to fit. This mesh is represented as a three-dimensional array storing the coordinates of each vertex.
The dimensions of this ArrayXd must be [3, N, M] with :
  • 3, the number of coordinates of a 3D point, respectively corresponding to X, Y, and Z expressed in the calibration unit.
  • N, the number of vertices per column of the mesh (N-1 cells per column).
  • M, the number of vertices per row of the mesh (M-1 cells per row).
ArrayXd nullptr
input
inputIntensityImage
The 3D input image containing the weight values to consider for the fitting. Image Grayscale nullptr
input
directions
The search direction for each vertex.
The dimensions of this ArrayXd has to be the same as the inputSurface.
ArrayXd nullptr
input
distance
The maximum distance to which the vertices can be moved.
This distance is expressed in world coordinates of the input mesh.
Float64 >=0 1
input
thresholdRange
The range of values that can be considered for the best fit.
A value outside of this range is considered as an outlier.
Vector2d Any value {0.f, 1.7976931348623157e+308f}
input
smoothing
The strength of the regularization applied on the fitted mesh.
A regularization is applied on the fitted mesh in order to smooth it and limit the effect of outliers.
The smoothing factor defines the strength of this regularization. The greater the value is the greater the smoothing is.
A smoothing value of 0 will disable the regularization.
Float64 >=0 1
input
fittingCriterion
The criterion according to which a vertex can be kept as the best fit.
A value outside of this range is considered as an outlier.
MINIMUM The surface is fitted on the intensity image minima.
MAXIMUM The surface is fitted on the intensity image maxima.
Enumeration MAXIMUM
input
leftBoundaryCondition
The type of boundary conditions to apply on the left of the mesh.
DIRICHLET The Dirichlet boundary conditions are enabled for the left border. Displacements of vertices are clamped to the value defined by the parameter dirichletValues.
NEUMANN The Neumann boundary conditions are enabled for the left border. The variation of displacements in the direction perpendicular to the border is null. It means that the displacement of a vertex at the border is equal to the displacement of its direct right neighbor.
Enumeration NEUMANN
input
rightBoundaryCondition
The type of boundary conditions to apply on the right of the mesh.
DIRICHLET The Dirichlet boundary conditions are enabled for the right border. Displacements of vertices are clamped to the value defined by the parameter dirichletValues.
NEUMANN The Neumann boundary conditions are enabled for the right border. The variation of displacements in the direction perpendicular to the border is null. It means that the displacement of a vertex at the border is equal to the displacement of its direct left neighbor.
Enumeration NEUMANN
input
topBoundaryCondition
The type of boundary conditions to apply on the top of the mesh.
DIRICHLET The Dirichlet boundary conditions are enabled for the top border. Displacements of vertices are clamped to the value defined by the parameter dirichletValues.
NEUMANN The Neumann boundary conditions are enabled for the top border. The variation of displacements in the direction perpendicular to the border is null. It means that the displacement of a vertex at the border is equal to the displacement of its direct bottom neighbor.
Enumeration NEUMANN
input
bottomBoundaryCondition
The type of boundary conditions to apply on the bottom of the mesh.
DIRICHLET The Dirichlet boundary conditions are enabled for the bottom border. Displacements of vertices are clamped to the value defined by the parameter dirichletValues.
NEUMANN The Neumann boundary conditions are enabled for the bottom border. The variation of displacements in the direction perpendicular to the border is null. It means that the displacement of a vertex at the border is equal to the displacement of its direct top neighbor.
Enumeration NEUMANN
input
regularizationType
The type of regularization used to smooth the mesh.
LAPLACIAN The mesh is smoothed by a classical Laplacian operator. This type of regularization is subject to a "shrinking effect": the surface can lie slightly below the best score points (detected along the normals).
LAPLACIAN_2 The mesh is smoothed by a second order Laplacian operator. This type of regularization does not suffer from the shrinking effect but can be less stable.
Enumeration LAPLACIAN
input
dirichletValues
The Dirichlet values for the left, right, top, and bottom boundary conditions. If set to 0, the vertices are not moved on the borders for which the Dirichlet conditions are enabled. This value is ignored when the Neumann boundary conditions are enabled for the corresponding mesh border. Vector4d Any value {0.f, 0.f, 0.f, 0.f}
output
outputSurface
The output surface fitting the input volume weights. This mesh is represented as a three-dimensional array storing the coordinates of each vertex.
The dimensions of this ArrayXd are [3, N, M] with :
  • 3, the number of coordinates of a 3D point, respectively corresponding to X, Y, and Z expressed in the calibration unit.
  • N, the number of vertices per column of the mesh (N-1 cells per column).
  • M, the number of vertices per row of the mesh (M-1 cells per row).
ArrayXd nullptr

Object Examples

auto dental_distmap = readVipImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "dental_distmap.vip" );
std::shared_ptr< iolink::ArrayXd> dental_extruded_mesh( new iolink::ArrayXd( { 0 } ) );
readArrayXd( std::string( IMAGEDEVDATA_OBJECTS_FOLDER ) + "dental_extruded_mesh.arrayxd", dental_extruded_mesh);
std::shared_ptr< iolink::ArrayXd> dental_normals( new iolink::ArrayXd( { 0 } ) );
readArrayXd( std::string( IMAGEDEVDATA_OBJECTS_FOLDER ) + "dental_normals.arrayxd", dental_normals);

SurfaceFitting3d surfaceFitting3dAlgo;
surfaceFitting3dAlgo.setInputIntensityImage( dental_distmap );
surfaceFitting3dAlgo.setInputSurface( dental_extruded_mesh );
surfaceFitting3dAlgo.setDirections( dental_normals );
surfaceFitting3dAlgo.setDistance( 15 );
surfaceFitting3dAlgo.setThresholdRange( {0, 1000000} );
surfaceFitting3dAlgo.setSmoothing( 10 );
surfaceFitting3dAlgo.setFittingCriterion( SurfaceFitting3d::FittingCriterion::MAXIMUM );
surfaceFitting3dAlgo.setTopBoundaryCondition( SurfaceFitting3d::BoundaryCondition::NEUMANN );
surfaceFitting3dAlgo.setBottomBoundaryCondition( SurfaceFitting3d::BoundaryCondition::NEUMANN );
surfaceFitting3dAlgo.setLeftBoundaryCondition( SurfaceFitting3d::BoundaryCondition::DIRICHLET );
surfaceFitting3dAlgo.setRightBoundaryCondition( SurfaceFitting3d::BoundaryCondition::DIRICHLET );
surfaceFitting3dAlgo.setRegularizationType( SurfaceFitting3d::RegularizationType::LAPLACIAN_2 );
surfaceFitting3dAlgo.setDirichletValues( {15, 15, 15, 15} );
surfaceFitting3dAlgo.execute();

std::cout << "outputSurface:" << surfaceFitting3dAlgo.outputSurface()->shape();
dental_distmap = imagedev.read_vip_image(imagedev_data.get_image_path("dental_distmap.vip"))
dental_extruded_mesh = np.zeros(0, dtype=np.double)
dental_extruded_mesh = imagedev.read_array_xd(imagedev_data.get_object_path("dental_extruded_mesh.arrayxd"), dental_extruded_mesh)
dental_normals = np.zeros(0, dtype=np.double)
dental_normals = imagedev.read_array_xd(imagedev_data.get_object_path("dental_normals.arrayxd"), dental_normals)

surface_fitting_3d_algo = imagedev.SurfaceFitting3d()
surface_fitting_3d_algo.input_intensity_image = dental_distmap
surface_fitting_3d_algo.input_surface = dental_extruded_mesh
surface_fitting_3d_algo.directions = dental_normals
surface_fitting_3d_algo.distance = 15
surface_fitting_3d_algo.threshold_range = [0, 1000000]
surface_fitting_3d_algo.smoothing = 10
surface_fitting_3d_algo.fitting_criterion = imagedev.SurfaceFitting3d.MAXIMUM
surface_fitting_3d_algo.top_boundary_condition = imagedev.SurfaceFitting3d.NEUMANN
surface_fitting_3d_algo.bottom_boundary_condition = imagedev.SurfaceFitting3d.NEUMANN
surface_fitting_3d_algo.left_boundary_condition = imagedev.SurfaceFitting3d.DIRICHLET
surface_fitting_3d_algo.right_boundary_condition = imagedev.SurfaceFitting3d.DIRICHLET
surface_fitting_3d_algo.regularization_type = imagedev.SurfaceFitting3d.LAPLACIAN_2
surface_fitting_3d_algo.dirichlet_values = [15, 15, 15, 15]
surface_fitting_3d_algo.execute()

print( "output_surface:", str( surface_fitting_3d_algo.output_surface ) )
ImageView dental_distmap = Data.ReadVipImage( @"Data/images/dental_distmap.vip" );
IOLink.ArrayXd dental_extruded_mesh = new IOLink.ArrayXd(new IOLink.VectorXu64( 0 ) ) ;
dental_extruded_mesh = Data.ReadArrayXd( @"Data/objects/dental_extruded_mesh.arrayxd", dental_extruded_mesh );
IOLink.ArrayXd dental_normals = new IOLink.ArrayXd(new IOLink.VectorXu64( 0 ) ) ;
dental_normals = Data.ReadArrayXd( @"Data/objects/dental_normals.arrayxd", dental_normals );

SurfaceFitting3d surfaceFitting3dAlgo = new SurfaceFitting3d
{
    inputIntensityImage = dental_distmap,
    inputSurface = dental_extruded_mesh,
    directions = dental_normals,
    distance = 15,
    thresholdRange = new double[]{0, 1000000},
    smoothing = 10,
    fittingCriterion = SurfaceFitting3d.FittingCriterion.MAXIMUM,
    topBoundaryCondition = SurfaceFitting3d.BoundaryCondition.NEUMANN,
    bottomBoundaryCondition = SurfaceFitting3d.BoundaryCondition.NEUMANN,
    leftBoundaryCondition = SurfaceFitting3d.BoundaryCondition.DIRICHLET,
    rightBoundaryCondition = SurfaceFitting3d.BoundaryCondition.DIRICHLET,
    regularizationType = SurfaceFitting3d.RegularizationType.LAPLACIAN_2,
    dirichletValues = new double[]{15, 15, 15, 15}
};
surfaceFitting3dAlgo.Execute();

Console.WriteLine( "outputSurface:" + surfaceFitting3dAlgo.outputSurface.ToString() );

Function Examples

auto dental_distmap = readVipImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "dental_distmap.vip" );
std::shared_ptr< iolink::ArrayXd> dental_extruded_mesh( new iolink::ArrayXd( { 0 } ) );
readArrayXd( std::string( IMAGEDEVDATA_OBJECTS_FOLDER ) + "dental_extruded_mesh.arrayxd", dental_extruded_mesh);
std::shared_ptr< iolink::ArrayXd> dental_normals( new iolink::ArrayXd( { 0 } ) );
readArrayXd( std::string( IMAGEDEVDATA_OBJECTS_FOLDER ) + "dental_normals.arrayxd", dental_normals);

auto result = surfaceFitting3d( dental_distmap, dental_extruded_mesh, dental_normals, 15, {0, 1000000}, 10, SurfaceFitting3d::FittingCriterion::MAXIMUM, SurfaceFitting3d::BoundaryCondition::NEUMANN, SurfaceFitting3d::BoundaryCondition::NEUMANN, SurfaceFitting3d::BoundaryCondition::DIRICHLET, SurfaceFitting3d::BoundaryCondition::DIRICHLET, SurfaceFitting3d::RegularizationType::LAPLACIAN_2, {15, 15, 15, 15} );

std::cout << "outputSurface:" << result->shape();
dental_distmap = imagedev.read_vip_image(imagedev_data.get_image_path("dental_distmap.vip"))
dental_extruded_mesh = np.zeros(0, dtype=np.double)
dental_extruded_mesh = imagedev.read_array_xd(imagedev_data.get_object_path("dental_extruded_mesh.arrayxd"), dental_extruded_mesh)
dental_normals = np.zeros(0, dtype=np.double)
dental_normals = imagedev.read_array_xd(imagedev_data.get_object_path("dental_normals.arrayxd"), dental_normals)

result = imagedev.surface_fitting_3d( dental_distmap, dental_extruded_mesh, dental_normals, 15, [0, 1000000], 10, imagedev.SurfaceFitting3d.MAXIMUM, imagedev.SurfaceFitting3d.NEUMANN, imagedev.SurfaceFitting3d.NEUMANN, imagedev.SurfaceFitting3d.DIRICHLET, imagedev.SurfaceFitting3d.DIRICHLET, imagedev.SurfaceFitting3d.LAPLACIAN_2, [15, 15, 15, 15] )

print( "output_surface:", str( result ) )
ImageView dental_distmap = Data.ReadVipImage( @"Data/images/dental_distmap.vip" );
IOLink.ArrayXd dental_extruded_mesh = new IOLink.ArrayXd(new IOLink.VectorXu64( 0 ) ) ;
dental_extruded_mesh = Data.ReadArrayXd( @"Data/objects/dental_extruded_mesh.arrayxd", dental_extruded_mesh );
IOLink.ArrayXd dental_normals = new IOLink.ArrayXd(new IOLink.VectorXu64( 0 ) ) ;
dental_normals = Data.ReadArrayXd( @"Data/objects/dental_normals.arrayxd", dental_normals );

IOLink.ArrayXd result = Processing.SurfaceFitting3d( dental_distmap, dental_extruded_mesh, dental_normals, 15, new double[]{0, 1000000}, 10, SurfaceFitting3d.FittingCriterion.MAXIMUM, SurfaceFitting3d.BoundaryCondition.NEUMANN, SurfaceFitting3d.BoundaryCondition.NEUMANN, SurfaceFitting3d.BoundaryCondition.DIRICHLET, SurfaceFitting3d.BoundaryCondition.DIRICHLET, SurfaceFitting3d.RegularizationType.LAPLACIAN_2, new double[]{15, 15, 15, 15} );

Console.WriteLine( "outputSurface:" + result.ToString() );