How to change number of points and cells in a surface model?

Hello Dear Developers and Users

I have several surface models. Specifications of one of these surface models are:

Surface Area: 3492.57 mm^2
Volume: 10828.02 mm^3
Number of Points: 1029
Number of Cells: 336

I want to be able to change these specifications especially Number of Points and Number of Cells. How can I do that?

For example, I want to change these specifications in all my surface models to the following:
Number of Points: 1200
Number of Cells: 400

What modules should I use in Slicer or SlicerSALT?

In summary, My ultimate goal is to same number of points and number of cells in surface models. Please guide me as soon as possible.

Thanks a lot,
Shahrokh

If no of cells is,same as no of triangles, you can use reduce option in meshmixer, a standalone softwate.

The easiest way to achieve matching number of points is to add duplicate points to all models that have less points than the others. Would that be acceptable? Why do you need exact match of number of points?

Do you need correspondence between mesh points (do you expect 123th point in mesh A to be at the same anatomical location as point 123th in mesh B)? If yes, then what you need is a spatial correspondence between meshes: transformation that transforms points of one mesh to the other. This transformation is computed by spatial registration algorithms. Once you have transform between mesh A to B, you can apply that to points of mesh A and get a mesh that has the same shape as mesh B, but contains exactly the same number of points and cells, in the same order, as mesh A.

There are several ways of registering meshes in Slicer. For example, you can import your meshes to Segmentation node and use the methods described in this post: align two segments to each other .

1 Like

You can try to use the Decimation option in the Surface Toolbox module, however there you cannot exactly specify the number of triangles, only a reduction factor. It might still be possible to make them match.

What exactly you want to achieve with having exactly the same number of cells and points?

Hello
Dear Anil, Andras and Csaba

Thank you very much for your advice.
My tomographic images (MRI) are nifti format. Before, I convert region segmented (using itk-snap) to binary images.
I convert these binary images to the model by “Grayscale Model Maker” module using Threshold equal to 1. For example, I have given the specifications of one of theses models in the my first message.

Unfortunately, I can not work with SlicerIGT and If I did not get it wrong, as Andras pointed out, I used “Surface Registration” in “CMF Registration”module to register these models .
In this module, I select “Surface Registration” for “Type of Registration”.
I select one of the models as the Fixed Model and the other model as Moving Model.
The outputs of this module are the “Transform” matrix and the transmitted model.
If I did not get it wrong, how can I use this matrix to integrate the number of points and cells between models? In other words, what Slicer module should I use for this purpose.

Your sincerely;
Shahrokh

Please try doing the segmentation using Slicer’s Segment Editor module. It is a relatively new, much improved segmentation module that I think you will find at least as good as ITK-Snap.

Then you can register the segmentations using the Segment Registration module, for which you need to install the Segment Registration extension from Extension Manager.

Let us know how it goes.

If you already have a segmentation then you can load it into Slicer as a labelmap volume node and import that into a segmentation node (using Segmentations module).

After registration is completed, apply and harden the transform to the first model to get another model that has the same number of points and cells as the first model, but the shape of the second model.

Hello
Dear Andras and Csaba

Sorry about that I can not to do it.
At firstly, I mentioned that I did the steps that Andras pointed out, but unfortunately I did not succeed.
I will explain all the processes that I do.

Process #1: Add Data
At it, I add sample1_C1_group04.nii and sample1_C1_group05.nii. For doing it, I choose these files and tick “LabelMap”option in the window of “Add data into the scene”. I think that I do these step as mentioned Andras.

Process #2: “Model Maker” module
In “Model Maker”, I do the following steps:
1- In Input Volume, I select my first LabelMapVolume with the name ample1_C1_group04
2- I create new ModelHierarchy
3- I named it to ModelS1C1G4
4- I set “Start Label” and “End Label” to 1
5- I set “Smooth” to 0 and then “Apply”.
6- I do steps above for my second LabelMapVolume with the name ample1_C1_group05
After doing it, I have two models with the names of ModelS1C1G4 and ModelS1C1G5 with the following specifications:
ModelS1C1G4:
Surface Area: 3816.23 mm^2
Volume: 133300.13 mm^3
Number of Points: 1479
Number of Cells: 541
ModelS1C1G5:
Surface Area: 2940.01 mm^2
Volume: 9805.02 mm^3
Number of Points: 1168
Number of Cells: 449
After doing, I can clearly see these two models, seperately.
Note: I want that “Number of Points” and “Number of Cells” of ModelS1C1G5 are same as ModelS1C1G4.

Process #3: “Model Registration” module
At it, as mentioned Andras it, I want to calculate transform matrix; so I do the following steps:
1- In “Input fixed (dense) model”, I select ModelS1C1G4.
2- In “Input moving (sparse) model”, I select ModelS1C1G5.
3- I create new LinearTransorm with the name of “LinearTransform_3”
4- In part of “Advanced”, I select “Rigid” for “Transform type”.
5- I click “Apply”.
6- After doing it, I get 1.18665655941 in “Mean distance after registration”.

Process #4: “Transforms” module;
1- I select “LinearTransform_3” in “Active Transform”
2- In the part of “Apply transform”, firstly I select ModelS1C1G4 and apply “LinearTransform_3” to it.
3- In “Data” module, I select ModelS1C1G4 and then right click and select “Harden Transform”

After doing these steps, I expect to be equal to “Number of Points” and “Number of Cells” of ModelS1C1G5 with ModelS1C1G4; but unfortunately, that did not happen.

I’m really confused. Please guide me to solve it.

Thanks a lot;
Shahrokh.

The main point is that when you apply a transform to a model, number of points or cells of that model does not change (compared to the original, non-transformed model).

I would recommend to not use Model Maker (unnecessary, Segmentations take care of conversions between various representations) and use Segment Registration for alignment (since it can do non-linear warping to better match the meshes).

Thanks a lot Andras.

Also,Csaba had also mentioned to use “Segment Registration” module in his message; but unfortunately, I can not find “Segment Registration” module; even I search “Segment Registration” in “Extension Manager” on Slicer. It was not.
I work with Slicer version 4.6.2 r25516.
Should I install this module (Segment Registration)?
OR
is it installed by default on Slicer? If Ok, what version is there?

Thanks a lot.
Shahrokh

Wow, Slicer 4.6 - that was released two years ago! We are making huge improvements to Slicer week by week, so a two-year-old version is completely outdated. You should always use at least the latest stable version(currently Slicer-4.8), and if you don’t find something there or something is not working as expected then try a recent nightly (not older than 1-2 weeks).

:blush:

Dear Andras and Csaba,

Really excuse me, I download Slicer-4.9.0-2018-01-10-linux-amd64 and install “Segment Registration” module. I really hope that my problems will be solved.
Thanks thanks thanks
Shahrokh

Excellent, thanks for the update! I also hope it will work for your use case. Let us know if not.

:disappointed_relieved:

Hello
Dear Andras and Csaba

As mentioned you, at now, I work with Slicer-4.8.1-linux-amd64 and install “Segment Registration” module. Unfortunately I can not same “Number of Points” and “Number of Cells” between two models.

This may be better to point out my purpose. Please look at my post with titled “Shape analysis between non-similar objects?” in “3D Slicer Forum”.
Briefly, suppose I have 5 groups with names A, B, C, D and E and in each group there are 8 meat samples (with size 2x2x2 cm^3 each sample, approximately). Each group was subjected to different laboratory procedures (physicochemical methods) and these procedures had a significant effect on the surface of the samples that it is recognizable by any observer.
I get MRI images from these samples separately. I put meat samples from each group on the flat surface (one chess score sheet) and after MRI acquisition, I cropped sample slice images and convert to binary segmented images using softwares such as itksnap, Seg3D and Slicer. Now I want to 3D surface analysis the effects of these procedures on the surface of these meat samples using SlicerSALT (SPHARM). At that time, Beatriz guide me that I have to check if correspondence is good across all meat samples. (I thank Beatriz for all patiently guidance). Unfortunately, I did not understand how I can match meat samples.

At now, I want to same number of points and cells between two extracted models from MRI samples.

As mentioned Andras and Csaba, I download Slicer-4.8.1-linux-amd64 and install “Segment Registration” module.

For example, I do the following steps for two samples (binary segmented images):

#1: Load data as LabelMap (WITH tick “LabelMap”) :
File menu → Add data → Choose File(s) to Add: sample1_C1_group04.nii and sample1_C1_group04.nii

#2: Load data as volume (WITHOUT tick “LabelMap”):
File menu → Add data → Choose File(s) to Add: sample1_C1_group04.nii and sample1_C1_group04.nii
Rename sample1_C1_group04.nii to Volume_sample1_C1_group04
Rename sample1_C1_group05.nii to Volume_sample1_C1_group05

#3: Segmentations module:
In “Active segmentation” → Create new Segmentation with the name MySegmentation
In “Export/import models and labelmaps” → in “Operation”, choose “Import” and in “Input type”choose “Labelmap” and select sample1_C1_group04 and in “Input node” and finally click on “Import” and again select sample1_C1_group05 in “Input node” and finally click on “Import”

#4: “Data” module:
In “Subject hierarchy” tab → right click on “MySegmentation” and click on “Export visible segments to models”

#5: “Segment Registration” module:
In “Fixed image” select Volume_sample1_C1_group04
In “Fixed segmentation” select MySegmentation
In “Fixed segment” select sample1_C1_group04
In “Moving image” select Volume_sample1_C1_group05
In “Moving segmentation” select MySegmentation
In “Moving segment” select sample1_C1_group05

in “Results” and “Applied registration on moving study, select “Deformable” defult and I can not changed it.
Click on “Perform registration”
After doing it, the options of “Applied registration on moving study” in “Results” could be changed.
At this time, I get messages in “Log messages” window; as following:

Performing registration workflow
Cropping moving volume
Pre-aligning segmentations
Fixed segment bounds: [16.945327758789062, 59.18786621093749, -94.15547943115234, -79.90632629394531, -141.16146850585938, -102.09896850585938]
Moving segment bounds: [158.5375518798828, 200.83857727050778, -95.2843017578125, -77.4457015991211, -124.57463836669922, -100.2640151977539]
Moving to fixed segment translation: [-141.62146759033203, -0.6659011840820312, -9.210891723632812]
Resampling fixed volume
Creating contour labelmaps
Performing distance based registration
Setting up result visualization
Performing registration workflow
Cropping moving volume
Pre-aligning segmentations
Fixed segment bounds: [16.945327758789062, 59.18786621093749, -94.15547943115234, -79.90632629394531, -141.16146850585938, -102.09896850585938]
Moving segment bounds: [158.5375518798828, 200.83857727050778, -95.2843017578125, -77.4457015991211, -124.57463836669922, -100.2640151977539]
Moving to fixed segment translation: [-141.62146759033203, -0.6659011840820312, -9.210891723632812]
Warning: In /home/kitware/Dashboards/Package/Slicer-481/Libs/MRML/Core/vtkMRMLTransformNode.cxx, line 1515
vtkMRMLLinearTransformNode (0x6932680): vtkMRMLTransformNode::SetAndObserveMatrixTransformToParent method is deprecated. Use vtkMRMLTransformNode::SetMatrixTransformToParent instead

_DeserializeImageGeometry: Failed to de-serialize geometry string _

ApplyTransformOnReferenceImageGeometry: Failed to get reference image geometry

Resampling fixed volume
_Found CommandLine Module, target is /home/sn/Slicer-4.8.1-linux-amd64/lib/Slicer-4.8/cli-modules/ResampleScalarVolume _
_ModuleType: CommandLineModule _
_Resample Scalar Volume command line: _

_/home/sn/Slicer-4.8.1-linux-amd64/lib/Slicer-4.8/cli-modules/ResampleScalarVolume --spacing 1,1,1 --interpolation lanczos /tmp/Slicer/CCJDG_vtkMRMLScalarVolumeNodeB.nrrd /tmp/Slicer/CCJDG_vtkMRMLScalarVolumeNodeE.nrrd _
_ _
Resample Scalar Volume completed without errors
_ _
Loaded volume from file: /tmp/Slicer/CCJDG_vtkMRMLScalarVolumeNodeE.nrrd. Dimensions: 47x20x44. Number of components: 1. Pixel type: unsigned short.

Creating contour labelmaps
Performing distance based registration
Traceback (most recent call last):
_ File “/home/sn/.config/NA-MIC/Extensions-26813/SlicerProstate/lib/Slicer-4.8/qt-scripted-modules/DistanceMapBasedRegistration.py”, line 249, in onApplyButton_
_ logic.run(self.parameterNode)_
_ File “/home/sn/.config/NA-MIC/Extensions-26813/SlicerProstate/lib/Slicer-4.8/qt-scripted-modules/DistanceMapBasedRegistration.py”, line 356, in run_
_ (bbMin,bbMax) = self.getBoundingBox(fixedLabelNodeID, movingLabelNodeID)_
_ File “/home/sn/.config/NA-MIC/Extensions-26813/SlicerProstate/lib/Slicer-4.8/qt-scripted-modules/DistanceMapBasedRegistration.py”, line 501, in getBoundingBox_
_ unionLabelImage = (cast.Execute(fixedLabelImage) + cast.Execute(movingLabelImage)) > 0_
_ File “/home/sn/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/SimpleITK/SimpleITK.py”, line 4254, in add_
_ return Add( self, other )_
_ File “/home/sn/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/SimpleITK/SimpleITK.py”, line 11002, in Add_
_ return SimpleITK.Add(*args)
RuntimeError: Exception thrown in SimpleITK Add: /home/kitware/Dashboards/Package/Slicer-481-package/ITKv4/Modules/Core/Common/include/itkImageToImageFilter.hxx:241:
itk::ERROR: AddImageFilter(0x6675f10): Inputs do not occupy the same physical space! _
InputImage Origin: [1.2437664e+02, 9.9558647e+01, -1.4970284e+02], InputImage_1 Origin: [-1.7810860e+01, 9.4871147e+01, -1.3251534e+02]
_ Tolerance: 1.5625000e-06

Setting up result visualization

#5: “Data” module:
In “Transform hierarchy” and in “Deformable Transform” list, right click on “Volume_sample1_C1_group05” and select “Harden transform”

#6: “Models” module:
Unfortunately, I see that “Number of Points” and “Number of Cells” are NOT the same. Why?!

Please guide me;
Shahrokh

I’m not familiar with the shape analysis methods you’re trying to use, but ensuring an exact match between number of vertices seems like a very unrealistic goal.

Surface models are mostly used for 3D visualization, and analysis is almost always done on labelmaps, so such limitations have not been needed. But even if you achieve the same number of vertices somehow, it’s very hard to ensure that if you set a correspndence between each pair of vertex, they will really correspond spatially. As the shape and size of triangles is not a priority to keep consistent, there will be a “drift” eventually when you want to set up correspondence.
You can use regularization methods to keep triangles the same size and shape, but then the smallest difference in your samples will result in a difference in number of vertices.

Have you considered using labelmaps or even other representations such as simplex meshes?

Hello
Dear Csaba and Andras

Thanks a lot for your replies. According with your guidance, I want to use labelmap volumes. I have some questions about it.
1- Can I do comparison the surfaces of labelmaps between several groups?
2- Can I create a average labmap volume from existing labmaps in a group?
3- Can I compare between surface features of MRI (meat) samples such as shrinkage?
4- Can I compute distance between two labelmaps just like as “ModelToModelDistance” module?

The point I should mention is that MRI images taken from meat samples are in following conditions:
a- The dimensions of the meat samples are not exactly the same. Their volume is almost equal to 8.0 cm^3 but certainly their dimensions are not same.
b- The orientation of meat fibers is not the same.
However, I think as two signals can be different in the frequency spectra, two surfaces can also be different in features such as spherical harmonics. In other words, I imagine MRI meat samples like as 3D signals that I want to extract fundamental frequencies and compare between them. How can I do it?

Also you mention to use simplex mesh. Please guide me to understand difference between simplex mesh and mesh available in 3DSlicer. At it, please give me more guidance.

Thanks a lot;
Shahrokh

Segment statistics module provides surface area measurement for each individual segment.

You can, for example by aligning segments to each other, export them to labelmap, computing distance map (using Simple Filters module), average distance maps, and threshold it at 0.

Segment statistics gives you segment volume, so you can easily compute shrinkage.

Yes, I think difference of distance maps should provide that. Or, apply model to model distance on the segment exported to a model node.

Check out SlicerSalt shape analysis toolbox. You may also experiment with simple PCA-based modeling, but for that you need to wrap ITK filters in a Slicer CLI module, as I don’t seem to find any module that wraps ITK’s PCA filters (ITK: itk::ImagePCAShapeModelEstimator< TInputImage, TOutputImage > Class Template Reference and others).

You can also use the Segment Comparison module from the SlicerRT extension.
Of course it only makes sense after you established spatial correspondence, for example using the Segment Registration extension.

Simplex mesh is a very special class of mesh that has been developed at Inria. It is a hexagon-based mesh that is designed to be regular. As far as I know there is no support for it in Slicer at this point, and it never became a standard representation, but if you like its features then it may be of interest. Keep in mind that adding its support in Slicer might be a huge project. Here’s a paper about it.