Пример #1
0
 def test_Shift(self):
     # two images identical up to a translation less than half the spacing should yield a gamma index
     # equal to the ratio of the length of the translation vector and the DTA.
     print('Test_GammaIndex3dUnequalMesh test_Shift')
     np.random.seed(1234568)
     for i in range(5):
         #print("shift image no. {}".format(i))
         nxyz = np.random.randint(5, 15, 3)
         oxyz = np.random.uniform(-100., 100., 3)
         sxyz = np.random.uniform(0.5, 2.5, 3)
         txyz = np.random.uniform(-0.5, 0.5, 3) * sxyz
         data = np.random.normal(1., 0.1, nxyz)
         img_ref = itk.GetImageFromArray(data.swapaxes(0, 2).copy())
         img_ref.SetSpacing(sxyz)
         img_ref.SetOrigin(oxyz)
         img_target = itk.GetImageFromArray(data.swapaxes(
             0, 2).copy())  # same as ref
         img_target.SetSpacing(sxyz)  # same as ref
         img_target.SetOrigin(oxyz + txyz)  # translated!
         ddp = 3.0  # %
         dta = 2.0  # mm
         img_gamma = gamma_index_3d_unequal_geometry(img_ref,
                                                     img_target,
                                                     dd=ddp,
                                                     dta=dta)
         agamma = itk.GetArrayViewFromImage(img_gamma).swapaxes(0, 2)
         gval_expected = np.sqrt(np.sum((txyz / dta)**2))
         self.assertTrue(np.allclose(agamma, gval_expected))
Пример #2
0
    def vesselsAndBackground(self, DirPath, file):
        imgPath = DirPath + "/" + file

        Imin = 50
        Imax = 80

        img = itk.imread(imgPath)
        dat = itk.GetArrayFromImage(img)

        dat = dat / np.max(dat) * (Imax - Imin) + Imin

        minValue = np.min(dat[dat > 0])
        print(minValue)
        dat[dat == 0] = minValue

        dat = dat.astype(np.uint8)  # for now
        if (dat.dtype == np.uint8):
            img = itk.GetImageFromArray(dat.astype(np.uint8))
        else:
            img = itk.GetImageFromArray(
                dat.astype(np.float32)
            )  # data is in double but it is not supported in itk

        outputPath = DirPath + "/vesselsAndBackground.nii"
        itk.imwrite(img, outputPath)
Пример #3
0
    def noisyImage(self, DirPath, file, outputFile, noiseType):
        imgPath = DirPath + "/" + file

        print(DirPath)
        print(imgPath)

        for id, i in enumerate(self.noiseLevels):
            img = itk.imread(imgPath)
            dat = itk.GetArrayFromImage(img)

            # simulated CT noise poisson + gaussian noise
            if (noiseType == "poisson"):
                datNoisy = 0.5 * np.random.poisson(
                    dat, None) + 0.5 * np.random.normal(dat, i, None)
            elif (noiseType == "rician"):
                datNoisy = rice.rvs(dat / i, scale=i)
            else:
                print("error noise type not supported")

            datNoisy[datNoisy < 0] = 0
            datNoisy[datNoisy > 255] = 255
            # writing image on disk
            if (dat.dtype == np.uint8):
                noisyImg = itk.GetImageFromArray(datNoisy.astype(np.uint8))
            else:
                noisyImg = itk.GetImageFromArray(
                    datNoisy.astype(np.float32)
                )  # data is in double but it is not supported in itk

            print(i)
            outputPath = DirPath + "/" + outputFile + "_" + str(i) + ".nii"
            itk.imwrite(noisyImg, outputPath)

            print(outputPath)
Пример #4
0
 def test_checkerboards(self):
     #print("test 3D checkerboards: have D=0.25 in even voxels and D=0.75 in odd voxels for ref image, vice versa for test image.")
     #for every voxel in the target image, the neighboring voxels in the ref image has the same dose
     #therefore the gamma index should be equal to spacing/dta for all voxels.
     print('Test_GammaIndex3dIdenticalMesh test_checkerboards')
     nx, ny, nz = 4, 5, 6
     ix, iy, iz = np.meshgrid(np.arange(nx, dtype=int),
                              np.arange(ny, dtype=int),
                              np.arange(nz, dtype=int),
                              indexing='ij')
     a_odd = 0.5 * (((ix + iy + iz) % 2) == 1).astype(float) + 0.25
     a_even = 0.5 * (((ix + iy + iz) % 2) == 0).astype(float) + 0.25
     img_odd = itk.GetImageFromArray(a_odd)
     img_even = itk.GetImageFromArray(a_even)
     img_gamma_even_odd = gamma_index_3d_equal_geometry(img_even,
                                                        img_odd,
                                                        dd=10.,
                                                        dta=2.)
     img_gamma_odd_even = gamma_index_3d_equal_geometry(img_odd,
                                                        img_even,
                                                        dd=10.,
                                                        dta=2.)
     self.assertTrue(
         np.allclose(itk.GetArrayViewFromImage(img_gamma_odd_even),
                     itk.GetArrayViewFromImage(img_gamma_even_odd)))
     self.assertTrue(
         np.allclose(itk.GetArrayViewFromImage(img_gamma_odd_even), 0.5))
Пример #5
0
    def vesselsIllumination(self, inputPath, outputPath, nbGaussianArtefacts,
                            aSigmaMin, aSigmaMax, aImin, aImax):
        # Retrieving nifti data into arrays
        img = itk.imread(inputPath)
        dat = itk.GetArrayFromImage(img)
        dat = dat.astype(np.float32)

        # Artefacts
        a = np.zeros(dat.shape)
        if (nbGaussianArtefacts > 0):
            for i in range(nbGaussianArtefacts):
                a += self.makeGaussian(dat, aSigmaMin, aSigmaMax)

            a = a / a.max() * (aImax - aImin) + aImin
            a[a < aImin + 2] = 0
            print("a", np.max(a), np.min(a))
            dat = a + dat

        dat[dat < 0] = 0
        dat[dat > 255] = 255

        dat[0, 0, 0] = 0  # used for easier display in slicer
        dat[0, 0, 1] = 255  # used for easier display in slicer

        # writing image on disk
        # writing image on disk
        if (dat.dtype == np.uint8):
            illuminatedImg = itk.GetImageFromArray(dat.astype(np.uint8))
        else:
            illuminatedImg = itk.GetImageFromArray(
                dat.astype(np.float32)
            )  # data is in double but it is not supported in itk
        print(dat.dtype)

        itk.imwrite(illuminatedImg, outputPath)
Пример #6
0
    def imageFromGaussianPDF(self, inputPath, outputPath, dataType):
        if (dataType == "MRI"):
            print("using MRI")
            gaussianPDFLiver = norm(loc=108, scale=12)
            gaussianPDFVessels = norm(loc=119, scale=16)
        if (dataType == "CT"):
            print("using CT")
            gaussianPDFLiver = norm(loc=101, scale=14)
            gaussianPDFVessels = norm(loc=139, scale=16)

        img = itk.imread(inputPath)
        img_np = itk.GetArrayFromImage(img)

        mask = (img_np == 0)
        img_np[mask] = gaussianPDFLiver.rvs(img_np[mask].shape[0])

        mask_vessels = (img_np > 0)
        img_np[mask_vessels] = gaussianPDFVessels.rvs(
            img_np[mask_vessels].shape[0])

        dat = img_np
        dat = dat.astype(np.uint8)  # for now
        if (dat.dtype == np.uint8):
            img = itk.GetImageFromArray(dat.astype(np.uint8))
        else:
            img = itk.GetImageFromArray(
                dat.astype(np.float32)
            )  # data is in double but it is not supported in itk

        itk.imwrite(img, outputPath)
Пример #7
0
 def test_identity(self):
     # two identical images should give gamma=0.0 in all voxels
     #print("test identity")
     print('Test_GammaIndex3dIdenticalMesh test_identity')
     np.random.seed(1234567)
     a_rnd = np.random.uniform(0., 10., (4, 5, 6))
     img1 = itk.GetImageFromArray(a_rnd)
     img2 = itk.GetImageFromArray(a_rnd)
     img_gamma = gamma_index_3d_equal_geometry(img1, img2, dd=3., dta=2.0)
     self.assertTrue((itk.GetArrayViewFromImage(img_gamma) == 0.).all())
Пример #8
0
 def test_scaling(self):
     #print("test scaling small")
     # two images identical up to a scaling factor 1.03 should give gamma(3%)<=1.0 in all voxels
     print('Test_GammaIndex3dIdenticalMesh test_scaling')
     np.random.seed(1234567)
     a_rnd = np.random.uniform(0., 10., (4, 5, 6))
     img1 = itk.GetImageFromArray(a_rnd)
     img2 = itk.GetImageFromArray(1.03 * a_rnd)
     img_gamma = gamma_index_3d_equal_geometry(img1, img2, dd=3., dta=2.0)
     self.assertTrue((itk.GetArrayViewFromImage(img_gamma) < 1.0001).all())
Пример #9
0
def vtk_to_itk_image(key, vtk_image):
    pixel_data = vtk_image['pointData']['values']
    pixel_type = vtk_image['pointData']['dataType']

    pixel_data = _vtkjs_type_convert(pixel_data, pixel_type)

    # numpy indexes in ZYX order, where X varies the fastest
    dims = [
        vtk_image['extent'][5] - vtk_image['extent'][4] + 1,
        vtk_image['extent'][3] - vtk_image['extent'][2] + 1,
        vtk_image['extent'][1] - vtk_image['extent'][0] + 1,
    ]

    direction = np.zeros((3, 3))
    for x in range(3):
        for y in range(3):
            direction[x][y] = vtk_image['direction'][x * 3 + y]

    itkImage = itk.GetImageFromArray(np.reshape(pixel_data, dims))
    # https://discourse.itk.org/t/set-image-direction-from-numpy-array/844/10
    vnlmat = itk.GetVnlMatrixFromArray(direction)
    itkImage.GetDirection().GetVnlMatrix().copy_in(vnlmat.data_block())
    itkImage.SetOrigin(vtk_image['origin'])
    itkImage.SetSpacing(vtk_image['spacing'])

    return itkImage
Пример #10
0
def test_connected_component():
    path = 'C:/Users/SEELE/Desktop/11/a'
    file_list = os.listdir(path)
    file_list.sort()
    label_volume = np.zeros([len(file_list), 512, 512])
    for i in range(len(file_list)):
        one_image_full_path = os.path.join(path, file_list[i])
        one_image_data = cv.imread(one_image_full_path, cv.IMREAD_GRAYSCALE)
        cv.threshold(one_image_data, 127, 255, cv.THRESH_BINARY,
                     one_image_data)
        label_volume[i] = one_image_data
    # cv.imshow('a', label_volume[87])
    # cv.waitKey()
    PixelType = itk.ctype("unsigned char")
    ImageType = itk.Image[PixelType, 3]
    itkimage = itk.GetImageFromArray(label_volume.astype(np.uint8))
    filter = itk.BinaryShapeKeepNObjectsImageFilter[ImageType].New()
    filter.SetAttribute('NumberOfPixels')
    filter.SetForegroundValue(255)
    filter.SetBackgroundValue(0)
    filter.SetNumberOfObjects(1)
    filter.SetInput(itkimage)
    filter.Update()
    output = filter.GetOutput()
    result_label_volume = itk.GetArrayFromImage(output)
    for i in range(result_label_volume.shape[0]):
        one_image_full_path = os.path.join(path, 'a.%d.jpg' % (i))
        cv.imwrite(one_image_full_path, result_label_volume[i])

    pass
Пример #11
0
def itk_to_vtk(itkImage):

    resample_factor = 10

    array = itk.GetArrayFromImage(itkImage)

    #Downsample test
    spacing = itkImage.GetSpacing()
    spacing[2] *= resample_factor
    array = array[::resample_factor, :, :]
    dims = (array.shape[1], array.shape[2], array.shape[0])

    downsampled_image = itk.GetImageFromArray(array)
    print(downsampled_image)

    vtk_array = numpy_support.numpy_to_vtk(num_array=array.ravel(),
                                           deep=True,
                                           array_type=vtk.VTK_FLOAT)

    print(dims, spacing)

    #MN
    vtkImage = vtk.vtkImageData()
    vtkImage.SetDimensions(dims)
    vtkImage.SetSpacing(spacing)
    vtkImage.GetPointData().SetScalars(vtk_array)

    return vtkImage
    def refreshView(self):
            # revise the voxels values to draw a bounding box
            revisedVolMat = drawBB(self.volMat,self.arrayBB)
            # write the revised volume with the bounding box
            revisedVolFilename = self.imgfilename[:-4]+'_bb.hdr'
            itk.imwrite(itk.GetImageFromArray(revisedVolMat.astype(np.float32)),revisedVolFilename)
            imgfilename = revisedVolFilename
            # read the revised volume using vtk
            # Create source
            vtkReader = vtk.vtkNIFTIImageReader()
            vtkReader.SetFileName(imgfilename)
            vtkReader.Update()
            # set a vtkvolume
            self.mapper.SetInputData(vtkReader.GetOutput())
            #self.mapper.Update()
            vtkvolume = vtk.vtkVolume()
            vtkvolume.SetMapper(self.mapper)
            vtkvolume.SetProperty(self.volumeProperty)
            # set renderer
            self.ren.SetBackground(1,1,1)
            self.ren.AddVolume(vtkvolume)
            self.ren.ResetCamera()
            #self.ren.GetActiveCamera().Zoom(1.5)

            self.tipnameLabel.setText(self.displayName)
            self.frame.setLayout(self.vl)
            self.setCentralWidget(self.frame)
        
            self.show()
            self.iren.Initialize()
Пример #13
0
def thinning_diameter(sparse, envelope, multiprocesses=2):
    """Computes twice the shortest distance to the outer shell along the medial axis of the object
    (i.e. diameter of the local maximal fitting sphere)

    This function requires: ITK"""
    if not _have_itk:
        raise ImportError("Please install ITK to use this function.")
    if not _have_itk_thickness:
        raise ImportError(
            "Please install itk-thickness3d to use this function.")

    if multiprocesses == 1:
        warnings.warn(
            "Disabled multiprocessing creates a pool of threads which does not get deallocated. "
            "Subsequent calls with multiprocessing **enabled** will be locked indefinitely."
        )

    sparse.run(
        lambda data, prev: (
            itk.GetArrayFromImage(
                itk.MedialThicknessImageFilter3D.New(
                    itk.GetImageFromArray(data))),
            prev,
        ),
        envelope=envelope,
        skip_neighbours=True,
        multiprocesses=multiprocesses,
    )
Пример #14
0
def _CropImageManuallyWithNumpy(input_img, from_index, to_index):
    """
    We would like to use itk.RegionOfInterestImageFilter but that filter does not recalculate the origin correctly.
    So now we do this manually, through numpy.
    """
    aimg = itk.GetArrayViewFromImage(input_img)
    logger.debug("got input image, the array view {} contiguous".format(
        "IS" if aimg.flags.contiguous else "IS NOT"))
    assert ((from_index > 0).all())
    assert ((to_index <= np.array(aimg.shape[::-1])).all())
    logger.debug(
        "going to create new image, forcing slice of old array to be continuous"
    )
    new_img = itk.GetImageFromArray(
        np.ascontiguousarray(aimg[from_index[2]:to_index[2],
                                  from_index[1]:to_index[1],
                                  from_index[0]:to_index[0]]))
    logger.debug("going to assign spacing and origin to new image")
    #new_img.CopyInformation(input_img)
    spacing = np.array(input_img.GetSpacing())
    old_origin = np.array(input_img.GetOrigin())
    new_origin = old_origin + (from_index) * spacing
    new_img.SetSpacing(spacing)
    new_img.SetOrigin(new_origin)
    logger.debug("cropping done, manually with numpy")
    return new_img
Пример #15
0
def get_intersection_volume(roilist,xvoxel=1.,yvoxel=1.):
    # There is probably a clever way to compute this by constructing
    # an "intersection contour" for each layer: for each contour, keep only
    # points that are inside all other contours in the list. But is tough to then
    # put those points in the right order.
    # Instead we'll just make a grid of points and get the volume of the combined mask.
    # With xvoxel and yvoxel the caller can tweak the voxel size of the mask in x and y.
    # In z the voxel size is given by the incoming ROIs.
    dz = min([r.dz for r in roilist])
    assert(dz>0)
    assert(xvoxel>0)
    assert(yvoxel>0)
    bb = bounding_box(bb=roilist[0].bb)
    for roi in roilist[1:]:
        bb.intersect(roi.bb)
    if bb.empty:
        # too bad
        return 0.
    spacing = np.array([xvoxel,yvoxel,dz],dtype=float)
    bb.add_margins(2*spacing)
    dimsize = np.array(np.round((bb.maxcorner-bb.mincorner)/spacing),dtype=int)
    #img = sitk.Image(dimsize,sitk.sitkUInt8)
    img = itk.GetImageFromArray(np.zeros(dimsize[::-2],dtype=np.uint8))
    img.SetOrigin(bb.mincorner)
    img.SetSpacing(spacing)
    itkmask = itk.GetArrayFromImage(roilist[0].get_mask(img))
    for roi in roilist[1:]:
        itkmask *= itk.GetArrayFromImage(roi.get_mask(img))
    return np.sum(itkmask)*np.prod(spacing)
Пример #16
0
def image_interpolate_recurrence(image1, image2, ind1, ind2, output_folder,
                                 img_origin, img_spacing):
    avg_img = (image1 + image2) / 2
    new_ind = (ind1 + ind2) / 2
    integer_ind = int(new_ind)
    if (new_ind == integer_ind):  # even number
        # save this projection
        output_imagename = f'./{output_folder}/secondary{int(integer_ind):04d}.mha'
        outputimage = itk.GetImageFromArray(avg_img)
        outputimage.SetOrigin(img_origin)
        outputimage.SetSpacing(img_spacing)
        itk.imwrite(outputimage, output_imagename)

        # check if can divide more
        if integer_ind - ind1 > 1:
            # call this function again twice, once to the left and once to the right
            image_interpolate_recurrence(image1, avg_img, ind1, integer_ind,
                                         output_folder, img_origin,
                                         img_spacing)
            image_interpolate_recurrence(avg_img, image2, integer_ind, ind2,
                                         output_folder, img_origin,
                                         img_spacing)

    else:
        # check if can divide more
        if new_ind - ind1 > 1:
            # call this function again twice, once to the left and once to the right
            image_interpolate_recurrence(image1, avg_img, ind1,
                                         int(math.ceil(new_ind)),
                                         output_folder, img_origin,
                                         img_spacing)
            image_interpolate_recurrence(avg_img, image2,
                                         int(math.floor(new_ind)), ind2,
                                         output_folder, img_origin,
                                         img_spacing)
Пример #17
0
    def makeHardClassificationPatches(self, DirPath, inputPath, maskPath,
                                      outputPath):
        imgInputPath = DirPath + "/" + inputPath  #"/DATA/vascu_deepV2/maskWholeImage.nii"
        imgMaskPath = DirPath + "/" + maskPath
        imgROIPath = DirPath + "/" + outputPath

        imgInput = itk.imread(imgInputPath)
        imgMask = itk.imread(imgMaskPath)

        PixelType = itk.UC
        Dimension = 3
        ImageType = itk.Image[PixelType, Dimension]

        radiusValue = 4
        StructuringElementType = itk.FlatStructuringElement[Dimension]
        structuringElement = StructuringElementType.Ball(radiusValue)

        DilateFilterType = itk.BinaryDilateImageFilter[ImageType, ImageType,
                                                       StructuringElementType]

        dilateFilter = DilateFilterType.New()

        dilateFilter.SetInput(imgMask)
        dilateFilter.SetKernel(structuringElement)
        dilateFilter.SetForegroundValue(255)
        imgMask = dilateFilter.GetOutput()

        imgInput = itk.GetArrayFromImage(imgInput)
        imgMask = itk.GetArrayFromImage(imgMask)

        imgROI = np.copy(imgInput)
        imgROI[imgMask > 0] = 0

        itk.imwrite(itk.GetImageFromArray(imgROI.astype(np.uint8)), imgROIPath)
Пример #18
0
def RelabelComponents(inputImage,
                      outputImageType = None):
  # relabel = itk.RelabelComponentImageFilter[input_type, output_type].New()
  # relabel.SetInput(inputImage)
  # relabel.Update()
  # return relabel.GetOutput()
  label_field = itk.GetArrayFromImage(inputImage)
  offset = 1
  max_label = int(label_field.max()) # Ensure max_label is an integer
  labels, labels_counts= np.unique(label_field,return_counts=True)
  labels=labels[np.argsort(labels_counts)[::-1]]
  labels0 = labels[labels != 0]
  new_max_label = offset - 1 + len(labels0)
  new_labels0 = np.arange(offset, new_max_label + 1)
  output_type = label_field.dtype
  required_type = np.min_scalar_type(new_max_label)
  if np.dtype(required_type).itemsize > np.dtype(label_field.dtype).itemsize:
      output_type = required_type
  forward_map = np.zeros(max_label + 1, dtype=output_type)
  forward_map[labels0] = new_labels0
  inverse_map = np.zeros(new_max_label + 1, dtype=output_type)
  inverse_map[offset:] = labels0
  relabeled = forward_map[label_field]
  result = itk.GetImageFromArray(relabeled)
  result.SetOrigin(inputImage.GetOrigin())
  result.SetSpacing(inputImage.GetSpacing())
  result.SetDirection(inputImage.GetDirection())
  if not outputImageType is None:
    s,d = itk.template(inputImage)[1]
    output_type = itk.Image[outputImageType,d]
    result = castImage(result, OutputType=output_type)
  return result
Пример #19
0
    def execute(self,
                image: sitk.Image,
                params: fltr.IFilterParams = None) -> sitk.Image:
        # input image is an sitkImage. The itk.CoocurrenceTextureFeatureImageFilter needs an itkImage as input. So
        # convert to an itkImage via a numpy array.
        img1_arr = (sitk.GetArrayFromImage(image)).astype(np.uint16)
        img1 = itk.GetImageFromArray(img1_arr)

        mask = itk.BinaryThresholdImageFilter.New(img1)
        mask.SetLowerThreshold(1)
        mask.SetInsideValue(1)

        filtr = itk.CoocurrenceTextureFeaturesImageFilter.New(img1)
        filtr.SetMaskImage(mask)
        filtr.SetNumberOfBinsPerAxis(10)
        filtr.SetHistogramMinimum(0)
        filtr.SetHistogramMaximum(2**16 - 1)
        filtr.SetNeighborhoodRadius([5, 5, 5])

        result1 = filtr.GetOutput()

        # convert to simpleITK image type, since the rest of the pipeline requires this datatype
        # we take care of the correct origin and orientation by copying this information from the input sitkImage
        result_arr = itk.GetArrayFromImage(result1)
        result = sitk.GetImageFromArray(result_arr)
        result.CopyInformation(image)

        return result
Пример #20
0
def multiscaleSheetness(multiScaleInput,
                        scales,
                        SmoothingImageType,
                        roi = None,
                        alpha = 0.5,
                        beta = 0.5,
                        gamma = 0.5):
  if not roi is None:
    roi = itk.GetArrayFromImage(roi)
  multiscaleSheetness = singlescaleSheetness(singleScaleInput = multiScaleInput,
                                             scale = scales[0],
                                             SmoothingImageType = SmoothingImageType,
                                             roi = roi,
                                             alpha = alpha,
                                             beta = beta,
                                             gamma = gamma)

  if len(scales) > 1:
    for scale in scales[1:]:
      singleScaleSheetness  = singlescaleSheetness(multiScaleInput,
                                                   scale = scale,
                                                   SmoothingImageType = SmoothingImageType,
                                                   roi = roi,
                                                   alpha = alpha,
                                                   beta = beta,
                                                   gamma = gamma)
      refinement = abs(singleScaleSheetness) > abs(multiscaleSheetness)
      multiscaleSheetness[refinement] = singleScaleSheetness[refinement]
  multiscaleSheetness = itk.GetImageFromArray(multiscaleSheetness.astype(np.float32))
  multiscaleSheetness.SetOrigin(multiScaleInput.GetOrigin())
  multiscaleSheetness.SetSpacing(multiScaleInput.GetSpacing())
  multiscaleSheetness.SetDirection(multiScaleInput.GetDirection())
  return multiscaleSheetness
Пример #21
0
def binaryThresholding(inputImage,
                       lowerThreshold,
                       upperThreshold,
                       outputImageType = None,
                       insideValue = 1,
                       outsideValue = 0):
  # Old version:
  # s,d = itk.template(inputImage)[1]
  # input_type = itk.Image[s,d]
  # output_type = input_type if outputImageType is None else itk.Image[outputImageType,d]
  # thresholder = itk.BinaryThresholdImageFilter[input_type, output_type].New()
  # thresholder.SetInput(inputImage)
  # thresholder.SetLowerThreshold( lowerThreshold )
  # thresholder.SetUpperThreshold( upperThreshold )
  # thresholder.SetInsideValue(insideValue)
  # thresholder.SetOutsideValue(outsideValue)
  # thresholder.Update()
  # return thresholder.GetOutput()
  values = itk.GetArrayFromImage(inputImage)
  cond = (values>=lowerThreshold) & (values<=upperThreshold)
  values[ cond ] = insideValue
  values[ np.logical_not(cond) ] = outsideValue
  result = itk.GetImageFromArray(values)
  result.SetOrigin(inputImage.GetOrigin())
  result.SetSpacing(inputImage.GetSpacing())
  result.SetDirection(inputImage.GetDirection())
  if not outputImageType is None:
    s,d = itk.template(inputImage)[1]
    output_type = itk.Image[outputImageType,d]
    result = castImage(result, OutputType=output_type)
  return result
Пример #22
0
    def noisyImage(self, inputPath, outputName, noiseType):

        for id, i in enumerate(self.noiseLevels):
            img = itk.imread(inputPath)
            dat = itk.GetArrayFromImage(img)
            dat = dat.astype(np.float32)
            # simulated CT noise poisson + gaussian noise
            if (noiseType == "poisson"):
                datNoisy = 0.5 * np.random.poisson(
                    dat, None) + 0.5 * np.random.normal(dat, i, None)
            elif (noiseType == "rician"):
                datNoisy = rice.rvs(dat / i, scale=i)
            else:
                print("error noise type not supported")

            datNoisy[datNoisy < 0] = 0
            datNoisy[datNoisy > 255] = 255
            # writing image on disk
            noisyImg = itk.GetImageFromArray(datNoisy.astype(np.uint8))

            print(i)
            outputPath = outputName + "_" + str(i) + ".nii"
            itk.imwrite(noisyImg, outputPath)

            print(outputPath)
Пример #23
0
def to_itk_image(other_image_datatype):
    if is_arraylike(other_image_datatype):
        array = np.asarray(other_image_datatype)
        case_use_view = array.flags['OWNDATA']
        if have_dask and isinstance(other_image_datatype,
                                    dask.array.core.Array):
            case_use_view = False
        if case_use_view:
            image_from_array = itk.GetImageViewFromArray(array)
        else:
            image_from_array = itk.GetImageFromArray(array)
        return image_from_array
    elif have_vtk and isinstance(other_image_datatype, vtk.vtkImageData):
        from vtk.util import numpy_support as vtk_numpy_support
        array = vtk_numpy_support.vtk_to_numpy(
            other_image_datatype.GetPointData().GetScalars())
        array.shape = tuple(other_image_datatype.GetDimensions())[::-1]
        image_from_array = itk.GetImageViewFromArray(array)
        image_from_array.SetSpacing(other_image_datatype.GetSpacing())
        image_from_array.SetOrigin(other_image_datatype.GetOrigin())
        return image_from_array
    elif have_imglyb and isinstance(
            other_image_datatype,
            imglyb.util.ReferenceGuardingRandomAccessibleInterval):
        array = imglyb.to_numpy(other_image_datatype)
        image_from_array = itk.GetImageViewFromArray(array)
        return image_from_array

    return None
Пример #24
0
def image_keep_max_region(label_volume_data):
    label_volume = image_threshold_binaray_3d(label_volume_data, 127)
    # labels = measure.label(image_3d_ref, connectivity=2)
    # props = measure.regionprops(labels)
    # max_area = 0
    # max_area_index = 0
    # for i in range(len(props)):
    #     area = props[i].area
    #     if area > max_area:
    #         max_area_index = i
    #         max_area = area
    # box = props[max_area_index].bbox
    # label_volume_with_max_region = np.zeros(image_3d_ref.shape, np.uint8)
    # label_volume_with_max_region[box[0]:box[3], box[1]:box[4], box[2]:box[5]] = \
    #     image_3d_ref[box[0]:box[3], box[1]:box[4], box[2]:box[5]]
    # assert box[3] - box[0] < depth + 1
    # for i in range(label_volume_with_max_region.shape[0]):
    #     cv.imwrite('D:\\tmp\\MIS\\other\\%d.jpg' % (i), label_volume_with_max_region[i])

    PixelType = itk.ctype("unsigned char")
    ImageType = itk.Image[PixelType, 3]
    itkimage = itk.GetImageFromArray(label_volume.astype(np.uint8))
    filter = itk.BinaryShapeKeepNObjectsImageFilter[ImageType].New()
    filter.SetAttribute('NumberOfPixels')
    filter.SetForegroundValue(255)
    filter.SetBackgroundValue(0)
    filter.SetNumberOfObjects(1)
    filter.SetInput(itkimage)
    filter.Update()
    output = filter.GetOutput()
    result_label_volume = itk.GetArrayFromImage(output)
    return result_label_volume
Пример #25
0
def main():
    print("Start main()")
    example = return_example_volume()
    example_itk_pointer = itk.GetImageFromArray(example)

    image_type_input = type(example_itk_pointer)

    # Convert input image to itk.SS
    image_type = itk.Image[itk.SS, 3]
    ImageCast = itk.CastImageFilter[image_type_input, image_type].New()
    ImageCast.SetInput(example_itk_pointer)

    # Extract threshold volume from image
    ThresholdFilter = itk.BinaryThresholdImageFilter[image_type, image_type].New()
    ThresholdFilter.SetInput(ImageCast.GetOutput())
    ThresholdFilter.SetLowerThreshold(19)
    ThresholdFilter.SetUpperThreshold(21)
    ThresholdFilter.SetOutsideValue(False)
    ThresholdFilter.SetInsideValue(True)

    # Convert to mesh
    mesh_type = itk.Mesh[itk.D, 3]
    MeshFilter = itk.BinaryMask3DMeshSource[image_type, mesh_type].New()
    MeshFilter.SetInput(ThresholdFilter.GetOutput())
    MeshFilter.SetObjectValue(1)

    # Write file to hdd
    Writer = itk.MeshFileWriter[mesh_type].New()
    Writer.SetFileName("Test.obj")
    Writer.SetInput(MeshFilter.GetOutput())
    Writer.Update()
Пример #26
0
def get_bounding_box(image_3d_ref, depth, xy_padding=15, z_padding=8):
    image_3d_ref = image_threshold_binaray_3d(image_3d_ref, 127)

    PixelType = itk.ctype("unsigned char")
    ImageType = itk.Image[PixelType, 3]
    itkimage = itk.GetImageFromArray(image_3d_ref.astype(np.uint8))
    filter = itk.BinaryShapeKeepNObjectsImageFilter[ImageType].New()
    filter.SetAttribute('NumberOfPixels')
    filter.SetForegroundValue(255)
    filter.SetBackgroundValue(0)
    filter.SetNumberOfObjects(1)
    filter.SetInput(itkimage)
    filter.Update()
    output = filter.GetOutput()
    result_label_volume = itk.GetArrayFromImage(output)
    z, y, x = result_label_volume.nonzero()
    z_min = max(0, min(z) - z_padding)
    z_max = min(image_3d_ref.shape[0] - 1, z_min + depth)
    y_min = min(y)
    y_max = max(y)
    x_min = min(x)
    x_max = max(x)
    width = x_max - x_min
    height = y_max - y_min
    length = max(width, height)

    start_z = z_min
    end_z = z_max
    start_y = max(y_min - xy_padding, 0)
    end_y = min(start_y + length + 2 * xy_padding, image_3d_ref.shape[1] - 1)
    start_x = max(x_min - xy_padding, 0)
    end_x = min(start_x + length + 2 * xy_padding, image_3d_ref.shape[2] - 1)
    bbox_size = [start_z, end_z, start_y, end_y, start_x, end_x]

    return bbox_size
Пример #27
0
    def reg_image_sitk_to_itk(self, cast_to_float32: bool = True) -> None:
        """
        Convert SimpleITK to ITK for use in ITKElastix.

        Parameters
        ----------
        cast_to_float32: bool
            Whether to make image float32 for ITK, needs to be true for registration.

        """
        origin = self._reg_image.GetOrigin()
        spacing = self._reg_image.GetSpacing()
        # direction = image.GetDirection()
        is_vector = self._reg_image.GetNumberOfComponentsPerPixel() > 1
        if cast_to_float32 is True:
            self._reg_image = sitk.Cast(self._reg_image, sitk.sitkFloat32)
            self._reg_image = sitk.GetArrayFromImage(self._reg_image)
        else:
            self._reg_image = sitk.GetArrayFromImage(self._reg_image)

        self._reg_image = itk.GetImageFromArray(self._reg_image,
                                                is_vector=is_vector)
        self._reg_image.SetOrigin(origin)
        self._reg_image.SetSpacing(spacing)

        if self._mask is not None:
            origin = self._mask.GetOrigin()
            spacing = self._mask.GetSpacing()
            # direction = image.GetDirection()
            is_vector = self._mask.GetNumberOfComponentsPerPixel() > 1
            if cast_to_float32 is True:
                self._mask = sitk.Cast(self._mask, sitk.sitkFloat32)
                self._mask = sitk.GetArrayFromImage(self._mask)
            else:
                self._mask = sitk.GetArrayFromImage(self._mask)

            self._mask = itk.GetImageFromArray(self._mask, is_vector=is_vector)
            self._mask.SetOrigin(origin)
            self._mask.SetSpacing(spacing)

            mask_im_type = itk.Image[itk.UC, 2]
            self._mask = itk.binary_threshold_image_filter(
                self._mask,
                lower_threshold=1,
                inside_value=1,
                ttype=(type(self._mask), mask_im_type),
            )
Пример #28
0
def merge_pred(results_folder, ROI_list):

    # get the list of Task folders
    tasks_folders = glob.glob(f'{results_folder}/segm_results/Task*')

    if len(tasks_folders) != 3:
        print('Not all direction available, no merging was performed')
        sys.exit()

    # get the list of labels
    all_patients = glob.glob(
        f'{results_folder}/segm_results/{os.path.basename(tasks_folders[0])}/predicted_labels/*'
    )

    merged_labels = f'{results_folder}/segm_results/merged_labels'
    merged_binaries = f'{results_folder}/segm_results/merged_binaries'
    maybe_mkdir_p(merged_labels)
    maybe_mkdir_p(merged_binaries)

    # loop through the patient
    for patient in all_patients:
        label_name = os.path.basename(patient)
        patient_name = label_name.replace('label_', '')
        merged_binaries_patient = f'{merged_binaries}/{os.path.splitext(patient_name)[0]}'
        maybe_mkdir_p(merged_binaries_patient)

        # load labels in each direction
        label_d1_img = itk.imread(
            f'{tasks_folders[0]}/predicted_labels/{label_name}')
        label_origin = label_d1_img.GetOrigin()
        label_spacing = label_d1_img.GetSpacing()
        label_direction = label_d1_img.GetDirection()

        label_d1 = itk.GetArrayFromImage(label_d1_img)
        label_d2 = itk.GetArrayFromImage(
            itk.imread(f'{tasks_folders[1]}/predicted_labels/{label_name}'))
        label_d3 = itk.GetArrayFromImage(
            itk.imread(f'{tasks_folders[2]}/predicted_labels/{label_name}'))

        # get the intersection of every 2 labels
        intersec1 = np.where(label_d1 == label_d2, label_d1, 0)
        intersec2 = np.where(label_d1 == label_d3, label_d1, 0)
        intersec3 = np.where(label_d2 == label_d3, label_d2, 0)

        # get where 2 labels agree
        merged_label = np.zeros(label_d1.shape)
        merged_label = np.where(intersec1 != 0, intersec1, merged_label)
        merged_label = np.where(intersec2 != 0, intersec2, merged_label)
        merged_label = np.where(intersec3 != 0, intersec3, merged_label)

        merged_label_img = itk.GetImageFromArray(merged_label)
        merged_label_img.SetOrigin(label_origin)
        merged_label_img.SetSpacing(label_spacing)
        merged_label_img.SetDirection(label_direction)

        itk.imwrite(merged_label_img, f'{merged_labels}/{label_name}')

        segmap_to_binaries(merged_label, merged_binaries_patient, label_origin,
                           label_spacing, label_direction, ROI_list)
Пример #29
0
def _CropAndPadImageManuallyWithNumpy(input_img, from_index, to_index,
                                      hu_value_for_padding):
    """
    We would like to use itk.RegionOfInterestFilter but that filter does recalculate the origin correctly.
    So now we do this manually, through numpy.
    """
    logger.debug("crop and pad manually with numpy")
    aimg = itk.GetArrayViewFromImage(input_img)
    logger.debug("got input image, the array view {} contiguous".format(
        "IS" if aimg.flags.contiguous else "IS NOT"))

    if (from_index > 0).all() and (to_index <= np.array(
            aimg.shape[::-1])).all():
        logger.debug("only cropping, no padding")
        return _CropImageManuallyWithNumpy(input_img, from_index, to_index)

    logger.debug("both cropping and padding")
    atype = aimg.dtype.type
    asize = np.array(aimg.shape)[::-1]
    new_size = to_index - from_index
    logger.debug("old size: {} new size: {}".format(asize, new_size))
    from_old = np.array([max(i, 0) for i in from_index
                         ])  # i<0: padding, i>0: cropping; i==0: no change
    to_old = np.array([min(s, j) for j, s in zip(to_index, asize)
                       ])  # j>s: padding, j<s: cropping; j==s: no change
    from_new = np.array([max(-i, 0) for i in from_index
                         ])  # i<0: padding, i>0: cropping; i==0: no change
    to_new = np.array([
        inew + jorig - iorig
        for inew, iorig, jorig in zip(from_new, from_old, to_old)
    ])
    logger.debug("from indices in orig: {}".format(from_old))
    logger.debug("to indices in orig: {}".format(to_old))
    logger.debug("from indices in output: {}".format(from_new))
    logger.debug("to indices in output: {}".format(to_new))
    assert ((to_new <= new_size).all())
    assert ((to_new - from_new == to_old - from_old).all())
    assert ((to_new - from_new > 0).all())
    anew = np.full(new_size[::-1],
                   fill_value=hu_value_for_padding,
                   dtype=atype)
    logger.debug("new image array {} contiguous".format(
        "IS" if anew.flags.contiguous else "IS NOT"))
    anew[from_new[2]:to_new[2],from_new[1]:to_new[1],from_new[0]:to_new[0]] = \
    aimg[from_old[2]:to_old[2],from_old[1]:to_old[1],from_old[0]:to_old[0]]
    logger.debug("new image array with shape {} is now filled".format(
        aimg.shape))
    new_img = itk.GetImageFromArray(anew)
    logger.debug("new image created from array, it has size {}".format(
        new_img.GetLargestPossibleRegion().GetSize()))
    #new_img.CopyInformation(input_img)
    spacing = np.array(input_img.GetSpacing())
    old_origin = np.array(input_img.GetOrigin())
    new_origin = old_origin + (from_index) * spacing
    new_img.SetSpacing(spacing)
    new_img.SetOrigin(new_origin)
    logger.debug("cropping and padding done, manually with numpy")
    return new_img
Пример #30
0
    def __call__(self, volume, spacing, para, img_shape, img_spacing):
        itk_vol = itk.GetImageFromArray(volume)
        itk_vol.SetSpacing(spacing)
        vol_origin = itk_vol.GetOrigin()  # Origin is [0, 0, 0]
        vol_res = itk_vol.GetSpacing()
        vol_region = itk_vol.GetBufferedRegion()
        vol_size = vol_region.GetSize()
        InputImageType = itk.Image.SS3
        pixeltype = itk.D

        vol_center = itk.Point[pixeltype, self.dimension](
            np.array(vol_res) * np.array(vol_size) / 2)
        focalpoint = itk.Point[pixeltype, self.dimension](
            (vol_center[0], vol_center[1], self.focal_length - self.distance))

        rx, ry, rz, tx, ty, tz = para
        translation = itk.Vector[pixeltype, self.dimension]((tx, ty, tz))
        transform = itk.CenteredEuler3DTransform.D.New()
        transform.SetCenter(vol_center)
        transform.SetComputeZYX(True)
        transform.SetTranslation(translation)
        transform.SetRotation(np.deg2rad(rx), np.deg2rad(ry), np.deg2rad(rz))

        interpolator = itk.RayCastInterpolateImageFunction[
            InputImageType, itk.ctype('double')].New()
        interpolator.SetTransform(transform)
        interpolator.SetThreshold(self.threshold)
        interpolator.SetFocalPoint(focalpoint)

        itk_vol.SetOrigin((0, 0, 0))
        resample_filter = itk.ResampleImageFilter[InputImageType,
                                                  InputImageType].New()
        resample_filter.SetInterpolator(interpolator)
        resample_filter.SetInput(itk_vol)
        resample_filter.SetDefaultPixelValue(0)
        resample_filter.SetTransform(transform)

        img_size = itk.Size[self.dimension]((img_shape[0], img_shape[1], 1))
        resample_filter.SetSize(img_size)
        resample_filter.SetOutputSpacing((img_spacing[0], img_spacing[1], 1.0))

        # outputorigin indicate the ralationship between projection image (0, 0) and CT volume(0,0,0)
        img_origin = np.array(
            vol_center)[:2] - np.array(img_shape) * img_spacing / 2
        outputorigin = itk.Point[pixeltype, self.dimension](
            (img_origin[0], img_origin[1],
             -self.distance))  # physical corrdinate
        resample_filter.SetOutputOrigin(outputorigin)
        resample_filter.Update()

        ray = resample_filter.GetOutput()
        drr = itk.GetArrayFromImage(ray)
        drr = drr.squeeze()
        #         grayimg = (drr - drr.min())/(drr.max() - drr.min()) * 255
        grayimg = (np.zeros_like(drr) - (drr - drr.min()) /
                   (drr.max() - drr.min())) * 255

        return grayimg