Subtract 2 models from each other

295 views
Skip to first unread message

Bart Cornelissen

unread,
Feb 25, 2015, 3:28:29 AM2/25/15
to vmtk-...@googlegroups.com
Dear VMTK people,

I have a model of a middle cerebral artery with an intracranial aneurysm and a model of the reconstructed parent vessel (see figure). I want to delineate the aneurysm by subtracting those 2 surfaces from each other. The vmtksurfacebooleanoperation should do the trick, but this does not work in my case. Maybe because the 2 models do not exactly overlap? Also when using the tolerance switch, i do not get the result I want.

Therefore I want to use vmtkimagecompose in order to subtract the image files of the aneurysm model and the reconstructed parent vessel model. With vmtksurfacemodeller it is possible to calculate vti files from the surface models, however, the vti contains a distance map. Is it possible to write a surface to a binary image which allows me to subtract those images later on?

I hope somebody can help.

Best regards,
Bart
Aneurysm.png

Luca Antiga

unread,
Feb 28, 2015, 4:25:36 PM2/28/15
to Bart Cornelissen, vmtk-...@googlegroups.com
Hi Bart,
a practical way to use vmtksurfacebooleanoperation might be to scale the inner model up a bit (eventually translate both so that the barycenter of the inner surface is at the origin). Also, remember to use vmtksurfacecapper prior to vmtksurfacebooleanoperation or the latter may not recognize the surface inner/outer orientation.

vmtkimagecompose is another way to do it, but you shouldn’t actually aim at subtracting.
Since vmtksurfacemodeller produces images that are positive outside and negative inside the surfaces, in order to get the “subtracted” surface you’re aiming for, you have to obtain the region of space where the aneurysm model image is negative and the parent vessel model image is positive. So I would rather multiply the two images, since the aneurysm will be the only region of space where one image is positive (the parent vessel image) and the other is negative (the full aneurysm model).

Once you multiply, you get the subtracted surface by running vmtkmarchingcubes (since you’ll get the surface at the negative / positive transition).

Best,

Luca
--
You received this message because you are subscribed to the Google Groups "vmtk-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vmtk-users+...@googlegroups.com.
To post to this group, send email to vmtk-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

-- 
Luca Antiga, PhD
Co-founder and Principal Scientist, OROBIX Srl
via Gabriele Camozzi 144, 24121 Bergamo, Italy

twitter: @lantiga
mobile: +39.347.43.16.596
office: +39 035.027.37.86

"This message originates from OROBIX Srl and its contents and attachments are privileged and confidential and are intended only for the individual(s) or entity(ies) named above. This message should not be forwarded, distributed or disclosed. Any unauthorized use, dissemination and duplication is strictly prohibited and may be unlawful. All personal messages express views solely of the sender, which are not to be attributed to OROBIX Srl, and may not be copied or distributed without this disclaimer. If you are not the intended recipient or received this message in error, please delete this message and notify the sender by reply e-mail. Opinions, conclusions and other information in this message that do not relate to the official business of OROBIX Srl shall be understood as neither given nor endorsed by it."

Evan Kao

unread,
Feb 28, 2015, 7:12:42 PM2/28/15
to vmtk-...@googlegroups.com, Bart Cornelissen
Hello Luca, Bart,

I had a similar problem and was wondering if there were other ways in VMTK that would work.  Right now, I just import the surfaces into a commercial solid modeling program, "dilate" the parent surface, and then perform a surface/volume boolean operation.  Overall, it's similar to "scaling" the parent vessel as Luca mentioned, but I'd like to avoid having to deal with translations.  I assume the software translates the vertices along the normals, and then retriangulates the surfaces.  I think it would be simple enough to translate the points, but there may be some issues with self-intersecting faces along concave bends.  Would vmtksurfaceremeshing fix this?

Other ideas on how to dilate the parent vessel:
  1. Regarding vmtksurfacemodeller, would it be easier than using vmtkimagecompose to just perform vmtkmarchingcubes with a slightly negative value to get a slightly larger surface and then perform vmtksurfacebooleanoperation?

  2. Along similar lines, the paralleltransportvoronoidiagram.py script uses vtkvmtkpolyballmodeller to create an image of the parent vessel and then vtkMarchingCubes to get the surface.  Would it make sense to simply change the value of the threshold in vtkMarchingCubes to a negative number?

  3. If that doesn't work, does it make sense to change any values used by vtkvmtkpolyballmodeller to reconstruct the surface, like the MaximumInscribedSphereRadius array or polyball image size?  For instance, if I increased the values in the MaximumInscribedSphereRadius array by 10% or so, what exactly would that change?

Thanks,

Evan Kao

Luca Antiga

unread,
Mar 9, 2015, 6:28:16 AM3/9/15
to Evan Kao, vmtk-...@googlegroups.com, Bart Cornelissen
Hello Evan,

On 1 Mar 2015 at 01:12:43, Evan Kao (tos...@gmail.com) wrote:

Hello Luca, Bart,

I had a similar problem and was wondering if there were other ways in VMTK that would work.  Right now, I just import the surfaces into a commercial solid modeling program, "dilate" the parent surface, and then perform a surface/volume boolean operation.  Overall, it's similar to "scaling" the parent vessel as Luca mentioned, but I'd like to avoid having to deal with translations.  I assume the software translates the vertices along the normals, and then retriangulates the surfaces.  I think it would be simple enough to translate the points, but there may be some issues with self-intersecting faces along concave bends.  Would vmtksurfaceremeshing fix this?

It may, although there are no strong guarantees.


Other ideas on how to dilate the parent vessel:
  1. Regarding vmtksurfacemodeller, would it be easier than using vmtkimagecompose to just perform vmtkmarchingcubes with a slightly negative value to get a slightly larger surface and then perform vmtksurfacebooleanoperation?

Sure, you can do that. In fact, a dilate operation can be done by offsetting the distance transform to the surface (i.e. its implicit representation), which is essentially what you are proposing. This way you also overcome the self-intersection problems, the price to pay is that you lose guarantees on the topology, but this shouldn’t be too much of a practical issue.

  1. Along similar lines, the paralleltransportvoronoidiagram.py script uses vtkvmtkpolyballmodeller to create an image of the parent vessel and then vtkMarchingCubes to get the surface.  Would it make sense to simply change the value of the threshold in vtkMarchingCubes to a negative number?

Assuming you’re still using the poly ball modeller to get the volume of the parent vessel, this is correct.

  1. If that doesn't work, does it make sense to change any values used by vtkvmtkpolyballmodeller to reconstruct the surface, like the MaximumInscribedSphereRadius array or polyball image size?  For instance, if I increased the values in the MaximumInscribedSphereRadius array by 10% or so, what exactly would that change?

There’s nothing like trying :-)


Luca


Thanks,

Evan Kao


On Sat, Feb 28, 2015 at 1:25 PM, Luca Antiga <luca....@orobix.com> wrote:
Hi Bart,
a practical way to use vmtksurfacebooleanoperation might be to scale the inner model up a bit (eventually translate both so that the barycenter of the inner surface is at the origin). Also, remember to use vmtksurfacecapper prior to vmtksurfacebooleanoperation or the latter may not recognize the surface inner/outer orientation.

vmtkimagecompose is another way to do it, but you shouldn’t actually aim at subtracting.
Since vmtksurfacemodeller produces images that are positive outside and negative inside the surfaces, in order to get the “subtracted” surface you’re aiming for, you have to obtain the region of space where the aneurysm model image is negative and the parent vessel model image is positive. So I would rather multiply the two images, since the aneurysm will be the only region of space where one image is positive (the parent vessel image) and the other is negative (the full aneurysm model).

Once you multiply, you get the subtracted surface by running vmtkmarchingcubes (since you’ll get the surface at the negative / positive transition).

Best,

Luca

On 25 Feb 2015 at 09:28:31, Bart Cornelissen (b.m.w.co...@student.utwente.nl) wrote:

Dear VMTK people,

I have a model of a middle cerebral artery with an intracranial aneurysm and a model of the reconstructed parent vessel (see figure). I want to delineate the aneurysm by subtracting those 2 surfaces from each other. The vmtksurfacebooleanoperation should do the trick, but this does not work in my case. Maybe because the 2 models do not exactly overlap? Also when using the tolerance switch, i do not get the result I want.

Therefore I want to use vmtkimagecompose in order to subtract the image files of the aneurysm model and the reconstructed parent vessel model. With vmtksurfacemodeller it is possible to calculate vti files from the surface models, however, the vti contains a distance map. Is it possible to write a surface to a binary image which allows me to subtract those images later on?

I hope somebody can help.

Best regards,
Bart
--
You received this message because you are subscribed to the Google Groups "vmtk-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vmtk-users+...@googlegroups.com.
To post to this group, send email to vmtk-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
-- 

Luca Antiga, PhD
Co-founder and Principal Scientist, OROBIX Srl
via Gabriele Camozzi 144, 24121 Bergamo, Italy

twitter: @lantiga
mobile: +39.347.43.16.596
office: +39 035.027.37.86

"This message originates from OROBIX Srl and its contents and attachments are privileged and confidential and are intended only for the individual(s) or entity(ies) named above. This message should not be forwarded, distributed or disclosed. Any unauthorized use, dissemination and duplication is strictly prohibited and may be unlawful. All personal messages express views solely of the sender, which are not to be attributed to OROBIX Srl, and may not be copied or distributed without this disclaimer. If you are not the intended recipient or received this message in error, please delete this message and notify the sender by reply e-mail. Opinions, conclusions and other information in this message that do not relate to the official business of OROBIX Srl shall be understood as neither given nor endorsed by it."
--
You received this message because you are subscribed to the Google Groups "vmtk-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vmtk-users+...@googlegroups.com.
To post to this group, send email to vmtk-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "vmtk-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vmtk-users+...@googlegroups.com.
To post to this group, send email to vmtk-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Evan Kao

unread,
Mar 26, 2015, 3:57:44 PM3/26/15
to Luca Antiga, vmtk-...@googlegroups.com
Hello all,

As an update to this, I found that the simplest option (#2 - modifying the script to use a Marching Cubes threshold of 1.0 instead of 0.0), works pretty well for producing a parent vessel suitable for boolean subtraction.

However, then there's the issue of capping the isolated aneurysm to get a proper measurement from vmtksurfacemassproperties.  vmtksurfacecapper by itself has trouble capping the surface and there's some pretty odd discontinuities along the aneurysm surface, perhaps due to the boolean operation:



Applying vmtksurfaceremeshing before vmtksurfacecapper is also not reliable.  vmtksurfacecapper still apparently has trouble finding the boundary (red line is the output from vtkvmtkPolyDataBoundaryExtractor) and decreasing the remeshing target area or edgelength doesn't really help that much.  Additionally vmtksurfaceremeshing can sometimes crash python:



Applying vmtksurfacecapper successively until the surface is fully capped helps but doesn't always work either because sometimes vtkvmtkPolyDataBoundaryExtractor fails to detect any boundary at all, like in the following surface:




I've found that applying vmtksurfaceremeshing and vmtksurfacesmoothing multiple times can help, though it may smooth the surface more than I'd like, and isn't very systematic or robust (green = smoothed): 




So, a few questions:
  1. Is there a better, more systematic/automatic way to reliably cap the surface?
  2. Why does vtkvmtkPolyDataBoundaryExtractor fail and how can I avoid false outputs?
  3. How can I avoid crashing python with vmtksurfaceremeshing?
Thanks for your time,
Evan Kao

Luca Antiga

unread,
Mar 29, 2015, 11:59:13 AM3/29/15
to Evan Kao, vmtk-...@googlegroups.com
Hi Evan,
I believe all three questions come down to getting a better surface after the boolean operation.

By looking at the surface, I think it doesn’t have the topology it looks like it has. It’s not a simple
surface, it probably has a “lining”, which prevents all the downstream filters from operating correctly.

Try visualizing edges with opacity < 1: if the above is the case, you should see two overlapped 
meshes looking at the surface from the inside outwards.

A clue is also the rendering artifact in the first screenshot: in that area, the renderer cannot
find a correct orientation for the triangles, which produces the black shadows.

All this can be caused by issues in the boolean operation. Can you post a screenshot of 
the surfaces you used for the boolean operation?

I also suggest that you try to use the vmtkimagecompose way to produce your final surface.

Best,

Luca
ii_i7qixzmo2_14c57742205c7f97
ii_i7qkqvaw7_14c57a256e732c5f
ii_i7qk1zi85_14c57909ec546d5a
ii_i7qk3t6c6_14c5791ebd81e321
ii_i7qj526p4_14c57792cd7491d3
ii_i7qiv9ne0_14c577237c066097
ii_i7qixceg1_14c5773af9139b36

Evan Kao

unread,
Mar 30, 2015, 6:54:41 PM3/30/15
to Luca Antiga, vmtk-...@googlegroups.com
Hello Luca,

Here is a screenshot of one pair of surfaces used for the boolean operation that results in the artificial shadows:



In terms of the "overlapping meshes", it does look like the boolean operation potentially results in "hanging faces", which the boundary extractor seems to have trouble with:





Clipping these hanging faces crudely with vmtksurfaceclipper seems to solve the issue.  I think these cells could be detected automatically with vtkFeatureEdges, but I'm open to better suggestions.

I've been attempting the vmtkimagecompose method as well, but that approach seems to have its own issues.  vmtksurfacemodeller can produce artifacts that can make recovering the aneurysm through image composition more difficult or impossible:






In the first image, the artifacts make the process more cumbersome because I have to clean the result with vmtksurfaceconnectivity using 'closest' instead of 'largest'.

For the latter image, the "confusion" between the outside and inside of the surface makes it impossible to extract the aneurysm with image composition.

- Evan Kao

ii_i7qkqvaw7_14c57a256e732c5f
ii_i7qixceg1_14c5773af9139b36
ii_i7qk1zi85_14c57909ec546d5a
ii_i7qj526p4_14c57792cd7491d3
ii_i7qk3t6c6_14c5791ebd81e321
ii_i7qixzmo2_14c57742205c7f97
ii_i7qiv9ne0_14c577237c066097

Luca Antiga

unread,
Apr 5, 2015, 4:22:09 PM4/5/15
to Evan Kao, vmtk-...@googlegroups.com
Hi Evan,
thanks for the details. The fact that the vmtksurfacemodeller can’t figure out inside and outside gets me thinking.
Can you send the surface you are using vmtksurfacemodeller on?
Thanks

Luca
ECA72CB7-6FF9-44C1-BDD1-8B1543FDC2D1
ii_i7wgrvrk5_14c6cdc72fbc00fa
A0DE9AD7-AFC2-43B8-AAF0-A6124BC9B6D1
ii_i7wfuayp4_14c6cc48a72a3daf
ii_i7wfmxap2_14c6cbf48b3ae631
ii_i7wgxptq7_14c6ce09b552f6ee
ii_i7wftmur3_14c6cc4108770b2a
080985AD-2738-4247-9325-4415BE0EADA9
7CE96206-B1E5-4BE9-BE2E-6E2A0E52696C
ii_i7wecgx81_14c6c9e3145539f3
89EE5B8E-6464-4162-98D9-525CDA18B484
C84EA049-02F6-4DAE-8C2E-8EEA0371017B
3026D52C-BCC1-4F8E-A063-9E213DA6211F
Reply all
Reply to author
Forward
0 new messages