InsightSoftwareConsortium / ITK

Insight Toolkit (ITK) -- Official Repository. ITK builds on a proven, spatially-oriented architecture for processing, segmentation, and registration of scientific images in two, three, or more dimensions.
https://itk.org
Apache License 2.0
1.42k stars 664 forks source link

Out-of-bounds issues when converting between Masks and Meshes #2416

Open nslay opened 3 years ago

nslay commented 3 years ago

Description

ITK does not currently handle meshes near the boundaries of masks very well. Converting meshes to masks via itk::TriangleMeshToBinaryImageFilter can cause corruption when the mesh is near a mask edge (in my case, at the top of a mask). Converting masks to meshes works when using itk::BinaryMask3DMeshSource by itself. If you decimate with an itk::NumberOfFacesCriterion when using itk::SquaredEdgeLengthDecimationQuadEdgeMeshFilter, you get a crash.

Steps to Reproduce

  1. Make a mesh that corresponds to a mask that borders the top of a volume.
  2. Setup an ITK pipeline that uses an itk::MeshFileReader and itk::TriangleMeshToBinaryImageFilter to convert the mesh to mask. Observe the corrupted slice at the top of the mask (I will see about sharing an image).
  3. Setup an ITK pipeline that uses an itk::BinaryMask3DMeshSource, itk::SquaredEdgeLengthDecimationQuadEdgeMeshFilter with, say 1000 faces criterion, and itk::MeshFileWriter. Observe the SEGV crash.

I think I can share my code and an example with you. I will check.

Expected behavior

When converting meshes to mask, we should not see corruption at the boundaries of masks. When converting masks to meshes with face decimation, we should not experience SEGV crashes (valgrind confirms invalid reads here).

Actual behavior

Converting meshes to mask where the mesh borders the top of a mask can result in silent corruption along the boundaries (in my case, at the top slice... i.e. largest slice index). Converting masks to meshes with face decimation (and possibly other criteria) can result in SEGV crashes.

Reproducibility

100%

Versions

ITK 5.1.1 and ITK 5.1.2

Environment

Linux lambda 5.4.0-66-generic #74~18.04.2-Ubuntu SMP Fri Feb 5 11:17:31 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux GCC 7.5.0

//\n the STL (STereoLithography)file format. https://hdl.handle.net/10380/3452 Module_IOMeshSTL:BOOL=ON

//Override default GIT_TAG value for remote module IOMeshSTL Module_IOMeshSTL_GIT_TAG:STRING=f4d21b63fcc3c87338cbe65c7996a953034c3b18

Additional Information

As I am working with publicly available ProstateX data, I think I will be able to follow up with code, image, mask and mesh (after I get permission!).

I read/write meshes with IOMeshSTL which is an external ITK module. This might (possibly?) be related. Also, there's lots of confusion about what kinds of mesh representations ITK is using internally (mesh support is super confusing in ITK!). To my knowledge, I am using either a general itk::Mesh or an itk::QuadEdgeMesh.

Work Around

Padding the mask by 1 pixel in all dimensions solves all of these problems. In combination with valgrind, this confirms some out-of-bound reads/writes as the culprits of silent corruption and crashes.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions.

nicktasios commented 2 years ago

I'm having the same issue when converting medical image segmentations that are saved as meshes. When using TriangleMeshToBinaryImageFilter to make a label mask out of the mesh, I get corrupted slices when the mesh is close to the edges of the image boundary.

Example of how the layer of the resulting label mask looks like:

image
stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions.