neurolabusc / nii2mesh

Convert NIfTI volume to triangulated mesh using marching cubes
https://rordenlab.github.io/nii2meshWeb/
Other
140 stars 17 forks source link

Marching Cubes: invalid triangle #12

Closed abhishekpatil32 closed 1 week ago

abhishekpatil32 commented 2 weeks ago

Hello experts,

This is a very cool tool to convert the nifti (.nii) files to mesh (.obj).

But I am encountering an error like below:

load from disk: 154 ms pre-smooth: 1604 ms intensity range 0..1, isolevel 0.25098 voxel clustering (largest cluster, bubbles): 2578 ms Marching Cubes: invalid triangle 15733 -0.250980 -0.250980 -0.250980 -0.250980 -0.250980 -nan 131071.750000 21941997487060864704716311175242973184.000000

When I try to run the file using the online web server it works fine.. But with the code there is an error. What am I doing wrong?? Can anyone help me resolve this??

neurolabusc commented 2 weeks ago

I am unable to replicate. Perhaps you can share a dataset and specific method to troubleshoot. Here is a recipe that worked for me using the mni152.nii.gz image from NiiVue:

$ git clone git@github.com:neurolabusc/nii2mesh.git
$ cd nii2mesh/src 
$ make
$ ./nii2mesh -v
nii2mesh v1.0.20211220  Clang14.0.3  ARM
...
$ ./nii2mesh ../../mni152.nii.gz -r 0.1 -v 2 mni152.mz3
load from disk: 36 ms
pre-smooth: 57 ms
intensity range 0..88.8585, isolevel 31.5005
voxel clustering (largest cluster, bubbles): 253 ms
marching cubes (207x256x215): 112 ms
Unify vertices found no shared vertices
remove degenerate triangles 580258 -> 580211: 4 ms
 iteration 0 - triangles 580211 threshold 2.187e-06
 iteration 5 - triangles 288579 threshold 0.00209715
 iteration 10 - triangles 95748 threshold 0.0627485
simplify vertices 290191->29039 triangles 580211->58020 (r = 0.0999981): 217 ms
save to disk: 61 ms

If your NIfTI file is a T1-weighted image of the human head, you can try brain2print.org. Alternatively, for CT and other MRI scans, you can try ct2print.org

abhishekpatil32 commented 2 weeks ago

Hello Chris,

Thank you for your quick reply. I am using the segmentations of a model (in .nii format, with intensity values between 0 and 1) for converting them into .obj files. The previous model input is a CT scan (in dicom).

I tried to do the following command nii2mesh input.nii output.obj

I get an error that is given above. I tried using the options commands but that did not affect much I believe.

Please find a sample files attached here which do not work with the code version of nii2mesh but work with the web based nii2mesh given in the link: https://rordenlab.github.io/nii2meshWeb/. segmentations.zip

Am I missing something here in the code?

Thank you

neurolabusc commented 2 weeks ago

I am unable to replicate. Everything runs fine on my machine.

./nii2mesh ~/Downloads/segmentations/segmentation_1.nii output1.obj
./nii2mesh ~/Downloads/segmentations/segmentation_2.nii output2.obj
./nii2mesh ~/Downloads/segmentations/segmentation_2.nii output3.obj

nii2mesh

I can not help you if I can not replicate. Can I suggest you follow the recipe in my previous post, where I compile from source and run the program twice:

  1. once with no arguments (so it will give me some idea about your compiler and architecture as well as the software version, e.g. nii2mesh v1.0.20211220 Clang14.0.3 ARM and also tell me your operating system (MacOS, Linux or Windows).
  2. Run the code a second time with the verbosity set (e.g. add -v 1) so you see details of the processing stages to isolate the failure.
  3. You can also use make sanitize to compile a debug version that will provide a line number for any error.
abhishekpatil32 commented 2 weeks ago

Hello Chris,

I am using Linux (Google Colab) to run the code.

Here is the code that I have used for the same

Code starts here

import os !apt-get install git build-essential -y

if not os.path.exists('nii2mesh'): !git clone https://github.com/neurolabusc/nii2mesh.git

%cd nii2mesh/src !make %cd /content

input_nifti = '/content/segmentation_3.nii' output_mesh = '/content/try.obj'

output_directory = os.path.dirname(output_mesh) if not os.path.exists(output_directory): os.makedirs(output_directory)

command = f'./nii2mesh/src/nii2mesh {input_nifti} {output_mesh}' exit_code = os.system(command)

if exit_code != 0 or not os.path.exists(output_mesh): print(f"Mesh generation failed for {input_nifti}.") else: print(f"Mesh generated successfully for {input_nifti}.")

Code ends here

I get the following error:

Reading package lists... Done Building dependency tree... Done Reading state information... Done build-essential is already the newest version (12.9ubuntu3). git is already the newest version (1:2.34.1-1ubuntu1.11). 0 upgraded, 0 newly installed, 0 to remove and 45 not upgraded. /content/nii2mesh/src gcc slow marching cubes (to compile with clang/llvm 'make CXX=clang') gcc -O3 -DNII2MESH isolevel.c meshify.c quadric.c bwlabel.c radixsort.c nii2mesh.c -DHAVE_FORMATS base64.c MarchingCubes.c -lm -lz -DHAVE_ZLIB -o nii2mesh /content Mesh generation failed for /content/segmentation_3.nii.

Is there anything wrong I am trying to do?? I get a similar output for each of the files.

neurolabusc commented 2 weeks ago

I am not familiar with this tool chain - you may want to consult someone with Google colab expertise. Can you please see if the code below works. Also, are you sure that the input file exists and has read permissions, and the output location has write permissions with sufficient space.

$ git clone git@github.com:neurolabusc/nii2mesh.git
$ cd nii2mesh/src 
$ make
$ ./nii2mesh -v
nii2mesh v1.0.20211220  Clang14.0.3  ARM
...
$ ./nii2mesh ../../mni152.nii.gz -r 0.1 -v 2 mni152.mz3
abhishekpatil32 commented 2 weeks ago

Yes I am sure the input file exists and has read permissions as well as there is sufficient space for the file to store... As I have mentioned the code above doesn't work for only a few nii files. Rest of the files provide the correct obj files.

I initially thought there is an error with the dataset but if its running well at your end and hence it should run on my end as well...

The above code gave me the following output:

Reading package lists... Done Building dependency tree... Done Reading state information... Done make is already the newest version (4.3-4.1build1). clang is already the newest version (1:14.0-55~exp2). git is already the newest version (1:2.34.1-1ubuntu1.11). 0 upgraded, 0 newly installed, 0 to remove and 49 not upgraded. fatal: destination path 'nii2mesh' already exists and is not an empty directory. [Errno 20] Not a directory: 'nii2mesh/src' /content/nii2mesh/src gcc slow marching cubes (to compile with clang/llvm 'make CXX=clang') gcc -O3 -DNII2MESH isolevel.c meshify.c quadric.c bwlabel.c radixsort.c nii2mesh.c -DHAVE_FORMATS base64.c MarchingCubes.c -lm -lz -DHAVE_ZLIB -o nii2mesh

nii2mesh v1.0.20211220 GCC11.4.0 x86-64 Converts a NIfTI voxelwise volume to triangulated mesh. Usage: ./nii2mesh inputNIfTI [options] outputMesh Options -a s atlas text file (e.g. '-a D99_v2.0_labels_semicolon.txt') -b v bubble fill (0=bubbles included, 1=bubbles filled, default 0) -i v isosurface intensity (d=dark, m=mid, b=bright, number for custom, default medium) -l v only keep largest cluster (0=all, 1=largest, default 1) -o v Original marching cubes (0=Improved Lewiner, 1=Original, default 0) -p v pre-smoothing (0=skip, 1=smooth, default 1) -r v reduction factor (default 0.25) -q v quality (0=fast, 1= balanced, 2=best, default 1) -s v post-smoothing iterations (default 0) -v v verbose (0=silent, 1=verbose, default 0) mesh extension sets format (.gii, .json, .mz3, .obj, .ply, .pial, .stl, .vtk) Example: './nii2mesh voxels.nii mesh.obj' Example: './nii2mesh bet.nii.gz -i 22 myOutput.obj' Example: './nii2mesh bet.nii.gz -v 1 -i b bright.obj' Example: './nii2mesh img.nii -p 0 -r 1 large.ply' Example: './nii2mesh img.nii -r 0.1 small.gii' Example: './nii2mesh bet.nii -r 0.2 mesh.mz3' Example: './nii2mesh mesh.mz3 -r 0.1 small.mz3'

load from disk: 18 ms pre-smooth: 32 ms intensity range 0..8235.73, isolevel 2982.52 voxel clustering (largest cluster, bubbles): 94 ms marching cubes (91x109x91): 46 ms Unify vertices found no shared vertices remove degenerate triangles 66744 -> 66736: 5 ms iteration 0 - triangles 66736 threshold 2.187e-06 iteration 5 - triangles 50430 threshold 0.00209715 iteration 10 - triangles 26880 threshold 0.0627485 iteration 15 - triangles 12876 threshold 0.61222 iteration 20 - triangles 6754 threshold 3.40483 simplify vertices 33382->3347 triangles 66736->6674 (r = 0.100006): 196 ms save to disk: 12 ms

abhishekpatil32 commented 2 weeks ago

For the segmentation file that I have sent you gives me the following error:

load from disk: 190 ms pre-smooth: 2071 ms intensity range 0..1, isolevel 0.25098 voxel clustering (largest cluster, bubbles): 2924 ms Marching Cubes: invalid triangle 15733 -0.250980 -0.250980 -0.250980 -0.250980 -0.250980 -nan 131071.750000 21941997487060864704716311175242973184.000000 ... ... ... marching cubes (512x512x191): 91 ms vertex welding 11381 -> 10955: 1 ms remove degenerate triangles 19253 -> 18962: 1 ms double free or corruption (out)

neurolabusc commented 1 week ago

Can you recompile the latest commit (it will report nii2mesh v1.0.20240904 and see if this resolves your issue.

abhishekpatil32 commented 1 week ago

Hii Chris,

Thank you for your help. The latest git has improved a lot.

Previously I had many files which did not convert to .obj, it has reduced significantly. But I now face another issue with 1-2 odd files. When I run the following:

./nii2mesh segmentation1.nii -r 0.25 -v 1 segmentation_1.obj

The run stops at something like:

nii2mesh v1.0.20240904  GCC11.4.0  x86-64
load from disk: 157 ms
pre-smooth: 1787 ms
intensity range 0..0.675, isolevel 0.25098
voxel clustering (largest cluster, bubbles): 2641 ms

The issue is I believe for some files the operation does not save the files.

neurolabusc commented 1 week ago

I am unable to replicate. Can you share a file that exhibits this behavior?

abhishekpatil32 commented 1 week ago

I used the script

./nii2mesh segment.nii -r 0.25 -v 2 segment.obj

which gives the output

nii2mesh v1.0.20240904  GCC11.4.0  x86-64
load from disk: 153 ms
pre-smooth: 1533 ms
intensity range 0..0.773125, isolevel 0.25098
voxel clustering (largest cluster, bubbles): 2562 ms

Please find the attached nifit file that exhibits this behavior. segmentation.zip

neurolabusc commented 1 week ago

This is a limitation with your segmentation, not the software. nii2mesh returns an error code that you can detect, for example from the command line with $?:

$ ./nii2mesh segment.nii -r 0.25 -v 2 segment.obj
nii2mesh v1.0.20240904  Clang14.0.3  ARM
load from disk: 46 ms
pre-smooth: 1521 ms
intensity range 0..0.773125, isolevel 0.25098
voxel clustering (largest cluster, bubbles): 616 ms25098
$ echo $?
1

I have made a commit that now explicitly provides text describing the error:

marching cubes failed to identify triangles with an isolevel of 0.25098

The only non-zero images in this image are in the very top slice. Marching cubes expects voxels above the isosurface value to be surrounded by voxels below this threshold.

Screenshot 2024-09-05 at 8 35 27 AM

abhishekpatil32 commented 1 week ago

Okay. I understand now..

Thank you for your help..