yatengLG / ISAT_with_segment_anything

Labeling tool with SAM(segment anything model),supports SAM, SAM2, sam-hq, MobileSAM EdgeSAM etc.交互式半自动图像标注工具
https://www.yatenglg.cn/isat/
Other
1.18k stars 129 forks source link

Reading and exporting in .nii.gz. format? #191

Closed dat-rohit closed 1 month ago

dat-rohit commented 1 month ago

Hi,

Thanks for your amazing tool. I was wondering if the tool allowed the user to import images stored in the .nii.gz. format for medical images and also, is it possible to export the segmented labels in that same .nii.gz. format?

Thank you a lot in advance!

yatengLG commented 1 month ago

The update for multi sequence image support is being prepared. But now, your must unzip nii.gz before label.

dat-rohit commented 1 month ago

Thank you! Any idea as to when the update will be released?

Also, do you have any idea how I could export the labels into a NIFTI format?

yatengLG commented 1 month ago

Thank you! Any idea as to when the update will be released?

Also, do you have any idea how I could export the labels into a NIFTI format?

The update is not ready yet, but I can provide some simple scripts for you to use first.

Can you provid a nii image to me for test code?

dat-rohit commented 1 month ago

Thanks for your quick answer. Here is an example of .nii.gz file I would like to upload and work with on your tool.

I can provide some simple scripts for you to use

That would be amazing!

yatengLG commented 1 month ago

script1

# -*- coding: utf-8 -*-
# @Author  : LG
import os.path

import nibabel
import nibabel as nib
import numpy as np
from matplotlib import pyplot as plt
from ISAT.scripts.voc import VOC

class NII(VOC):
    def __init__(self, isat_jsons_root):
        super().__init__()
        self.isat_jsons_root = isat_jsons_root
        self.read_from_ISAT(isat_jsons_root)

    def save_nii_label(self, nii_path, save_nii_root):
        jsons = [json for json in os.listdir(self.isat_jsons_root) if json.endswith('.json')]
        nii_f = nib.load(nii_path)
        nii_shape = nii_f.get_fdata().shape
        h, w, c = nii_shape
        nii_name = os.path.split(nii_path)[-1][:-7]

        for cat in self.cates:
            if cat == '__background__':
                continue

            result = np.zeros(shape=(h, w, c))
            for i in range(c):
                json_name = '{}_{:0>8d}'.format(nii_name, i)
                if json_name in self.annos:
                    slice_label = self._to_numpy(self.annos[json_name], cat)
                    result[:, :, i] = slice_label
            if np.sum(result) < 0:
                continue
            nibabel.save(nib.Nifti1Image(result, np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]])),
                         os.path.join(save_nii_root, '{}_{}.nii.gz'.format(nii_name, cat)))

    def _to_numpy(self, anno, category):
        info = anno.info
        objects = anno.objs

        img_name = info.name
        width = info.width
        height = info.height
        img = np.zeros(shape=(height, width), dtype=np.uint8)

        objects = sorted(objects, key=lambda obj: obj.layer)

        for obj in objects:
            if obj.category != category:
                return img
            segmentation = obj.segmentation
            iscrowd = obj.iscrowd
            if iscrowd:
                if not self.keep_crowd:
                    continue
            segmentation = [(int(p[1]), int(p[0])) for p in segmentation]

            self.fill_polygon(segmentation, img, color=1)
        return img

def nii_to_jpgs(nii_path, jpg_save_root):
    nii_image = nib.load(nii_path)
    slices = nii_image.get_fdata()

    num_slices = slices.shape[-1]

    for i in range(num_slices):
        slice = slices[:, :, i]
        plt.imsave(os.path.join(jpg_save_root,
                                '{}_{:0>8d}.jpg'.format(os.path.split(nii_path)[-1][:-7], i)),
                   slice, cmap='gray')
    return True

if __name__ == '__main__':

    # unzip nii image to jpgs
    nii_to_jpgs('nii/ori_flair.nii.gz', 'nii/1')

    # after labeling, generate ISAT jsons in nii/1

    # open isat jsons with class NII.
    nii = NII('nii/1')
    nii.save_nii_label('nii/ori_flair.nii.gz', 'nii/2')

script2

# -*- coding: utf-8 -*-
# @Author  : LG
import matplotlib.pyplot as plt
import nibabel as nib

nii1 = 'nii/ori_flair.nii.gz'
nii2 = 'nii/2/ori_flair_label1.nii.gz'
nii3 = 'nii/2/ori_flair_label2.nii.gz'
nii4 = 'nii/2/ori_flair_label3.nii.gz'

slices1 = nib.load(nii1).get_fdata()
slices2 = nib.load(nii2).get_fdata()
slices3 = nib.load(nii3).get_fdata()
slices4 = nib.load(nii4).get_fdata()

num_slices = slices1.shape[-1]

for i in range(num_slices):
    slice1 = slices1[:, :, i]
    slice2 = slices2[:, :, i]
    slice3 = slices3[:, :, i]
    slice4 = slices4[:, :, i]

    fig, (axe1, axe2, axe3, axe4) = plt.subplots(1, 4)

    axe1.imshow(slice1, cmap='gray')
    axe2.imshow(slice2, cmap='gray')
    axe3.imshow(slice3, cmap='gray')
    axe4.imshow(slice4, cmap='gray')
    plt.show()

You can use script1 to export isat jsons into a nii file. And you can test it use demo.zip.

dat-rohit commented 1 month ago

Thank you a lot for your answer, I will definitely try this.

Meanwhile, for my own purpose, I had to develop a standalone GUI that offers to convert images from .nii.gz to JPG and mask annotations from JSON to .nii.gz. This complements your ISAT tool very well for my use case.

I uploaded the code here in case anyone would be interested.