Skip to content

Commit

Permalink
Merge pull request #3 from ivadomed/ws/fill-csf-fix
Browse files Browse the repository at this point in the history
Add script to fill CSF seg for canal
  • Loading branch information
sandrinebedard authored Apr 17, 2024
2 parents 97ca45f + 62b108a commit 3aac52f
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Installation
Pour utiliser le code de segmentation du canal spinal à partir des segmentations de la moelle et du CSF il est nécessaire d'installer les librairies utilisées. la ligne qui permet d'installer ces librairie est incluse dans celles pour cloner le Github.
Ensuite, il faut cloner le Github à l'aide de la suite de commande suivante :
~~~
git clone https://github.com/ivadomed/model-csf-seg.git
cd model-csg-seg
pip install -r requirements.txt
~~~

# Fonctionnement
À partir de la segmentation de la moelle, le centre de masse est déterminé pour chaque tranche transversale.
- Si il n'y as pas de segmentation du CSF (le CSF n'apparait pas sur l'image), on ne remplace pas l'image.
- Si il n'y as pas de segmentation de la moelle, on met l'image à 0.
- Si le CSF et la moelle on des segmentations sur la tranche, un floodfill est fait à partir du centre de masse déterminé plus haut.
- Le code évalue ensuite si l'image est pleine de 1 (région non fermée lors du floodfill)
- Si l'image est pleine de 1, on reprend l'image de base et on fait une fermeture.
- Le fait de faire la fermeture sur certaines images ne semble pas causée d'ajout de bruit à l'extérieur du CSF selon ce que j'ai observé.

# Utilisation
Le code prend en entrée 3 arguments
* `-i`: Segmentation du CSF (.nii.gz)

* `-s`: Segmentation de la moelle épinière (.nii.gz)

* `-o` Le nom que vous souhaiter donner au fichier (.nii.gz)

Voici donc un exemple de commande pour utiliser la fonction :
~~~
python3 fill-csf.py -i <CSF seg> -s <spinal cord seg> -o <output>
~~~


79 changes: 79 additions & 0 deletions fill-csf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#Authors : William Sirois

# For usage, type: python fill-csf.py -h or in WSL python3 fill-csf.py -h
#J'importe ce dont j'ai besoin
import nibabel as nib
import cv2 as cv
from skimage.morphology import disk
from skimage.segmentation import flood_fill
import scipy as sc
import numpy as np
import argparse
def get_parser():
parser = argparse.ArgumentParser(
description="Close the segmentation of the CSF to get the segmentation of the canal." )
parser.add_argument('-i', dest='CSF_seg', required = True, type=str,
help="Input segmentation of the CSF.")
parser.add_argument('-o', dest='Output_name', required = True, type=str,
help="Ouput image name.")
parser.add_argument('-s', dest='Cord_seg', required = True, type=str,
help="Segmentation of the spinal cord ")

return parser

def main() :

parser = get_parser()
args = parser.parse_args()

#Fonction pour sauvegarder fournis par Sandrine
def save_Nifti1(data, original_image, filename):
empty_header = nib.Nifti1Header()
image = nib.Nifti1Image(data, original_image.affine, empty_header)
nib.save(image, filename)

#Je load l'image
moelle = nib.load(args.Cord_seg)
moelle_np = moelle.get_fdata()
img = nib.load(args.CSF_seg)
img_np = img.get_fdata()

#Je copie l'image pour avoir l'original pour la sauvegarder à la fin
img_b = img_np.copy()
moelle_b = moelle_np.copy()
#Image qui sera remplie (besoin pour éviter les floodfill quand ce n'est pas fermé)
img_fill = img_b.copy()

#Méthode du floodfill avec le centre de masse
imagenbr = img_b.shape[2]#Je prend le nombre de coupe transversale
slice = 0
h,w = img_b[:, :, 1].shape

while slice < imagenbr : #J'itère sur les images de coupe
if np.sum(img_b[:,:,slice] == 1) == 0 :#Si il n'y as pas de segmentation sur le csf on ne change rien
img_fill[:, :, slice] = img_b[:, :, slice]

elif np.sum(moelle_b[:,:,slice] == 1) == 0:#Si il n'y as pas de segmentation sur la moelle je ne change rien et je retire la segmentation du csf
img_fill[:, :, slice] = 0

else :
cmmoelle = (sc.ndimage.center_of_mass(moelle_b[:, :, slice]))
cmmoelle = list(cmmoelle)
cmmoelle[0] = int(cmmoelle[0])
cmmoelle[1] = int(cmmoelle[1])
img_fill[:,:,slice] = flood_fill(img_fill[:,:,slice], (cmmoelle[0],cmmoelle[1]), 1)

if np.sum(img_fill[:,:,slice] == 1) == (h*w): #Si ma forme n'est pas fermée je reprend l'image de base et je fais une fermeture
img_fill[:, :, slice] = cv.morphologyEx(img_b[:,:,slice], cv.MORPH_CLOSE,disk(5))

slice = slice+1 #Je passe à la prochaine slice

#Je sauvegarde l'image(Je ne sais pas comment renommer mes images seulement une façon qui ressemble à la votre)
save_Nifti1(img_fill, img, args.Output_name)


if __name__ == '__main__':
parser = get_parser()
args = parser.parse_args()
main()
print(f'Segmentation realised and saved in {args.Output_name}')
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nibabel
argparse
opencv-python
scikit-image

0 comments on commit 3aac52f

Please sign in to comment.