Example #1
0
 def dist_to_spine(self):
     if self.spine_wvs is None:
         self.get_spine()
     ld = scipy.ndimage.morphology.distance_transform_edt(1 -
                                                          self.spine_wvs)
     ld = ld * float(self.working_vs[0])  # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #2
0
    def get_lungs_orig(
        self
    ):  # TODO - this doesnt work correctly, is segmenting a lot of unneeded stuff
        lungs = scipy.ndimage.filters.gaussian_filter(self.data3dr,
                                                      sigma=[4, 2, 2]) > -150
        lungs[0, :, :] = 1

        lungs = scipy.ndimage.morphology.binary_fill_holes(lungs)
        labs, n = scipy.ndimage.measurements.label(lungs == 0)
        cornerlab = [
            labs[0, 0, 0], labs[0, 0, -1], labs[0, -1, 0], labs[0, -1, -1],
            labs[-1, 0, 0], labs[-1, 0, -1], labs[-1, -1, 0], labs[-1, -1, -1]
        ]

        lb = np.median(cornerlab)
        labs[labs == lb] = 0

        labs[labs == labs[0, 0, 0]] = 0
        labs[labs == labs[0, 0, -1]] = 0
        labs[labs == labs[0, -1, 0]] = 0
        labs[labs == labs[0, -1, -1]] = 0
        labs[labs == labs[-1, 0, 0]] = 0
        labs[labs == labs[-1, 0, -1]] = 0
        labs[labs == labs[-1, -1, 0]] = 0
        labs[labs == labs[-1, -1, -1]] = 0

        lungs = labs > 0
        self.lungs = lungs
        #self.body = (labs == 80)
        return resize_to_shape(lungs, self.orig_shape)
Example #3
0
    def get_spine(self):
        """ Should have been named get_bones() """
        # prepare required data
        if self.body is None:
            self.get_body()  # self.body

        # filter out noise in data
        data3dr = scipy.ndimage.filters.median_filter(self.data3dr, 3)

        # tresholding
        # > 240 - still includes kidneys and small part of heart
        # > 280 - still a small bit of kidneys
        # > 350 - only edges of bones
        bones = data3dr > 320
        del (data3dr)
        bones[self.body == 0] = 0  # cut out anything not inside body

        # close holes in data
        bones = scipy.ndimage.morphology.binary_closing(
            bones, structure=np.ones(
                (3, 3, 3)))  # TODO - fix removal of data on edge slices

        # compute center
        self.spine_center_wvs = np.mean(np.nonzero(bones), 1)
        self.spine_center_mm = self.spine_center_wvs * self.working_vs / self.voxelsize_mm.astype(
            np.double)
        # self.center2 = np.mean(np.nonzero(bones), 2)

        self.spine_wvs = bones
        return resize_to_shape(bones, self.orig_shape)
Example #4
0
    def get_spine(self, skip_resize=False):
        """ Should have been named get_bones() """
        # prepare required data
        if self.body is None:
            self.get_body(skip_resize=True) # self.body

        # filter out noise in data
        data3dr = scipy.ndimage.filters.median_filter(self.data3dr, 3)

        # tresholding
        # > 240 - still includes kidneys and small part of heart
        # > 280 - still a small bit of kidneys
        # > 350 - only edges of bones
        bones = data3dr > 320; del(data3dr)
        bones[self.body==0] = 0 # cut out anything not inside body

        # close holes in data
        bones = scipy.ndimage.morphology.binary_closing(bones, structure=np.ones((3,3,3))) # TODO - fix removal of data on edge slices

        # compute center
        self.spine_center_wvs = np.mean(np.nonzero(bones), 1)
        self.spine_center_mm = self.spine_center_wvs * self.working_vs / self.voxelsize_mm.astype(np.double)
        # self.center2 = np.mean(np.nonzero(bones), 2)

        self.spine_wvs = bones
        if skip_resize:
            return bones
        else:
            return resize_to_shape(bones, self.orig_shape)
Example #5
0
 def dist_diaphragm(self):
     if self.diaphragm_mask is None:
         self.get_diaphragm_mask()
     dst = (scipy.ndimage.morphology.distance_transform_edt(
         self.diaphragm_mask) -
            scipy.ndimage.morphology.distance_transform_edt(
                1 - self.diaphragm_mask))
     return resize_to_shape(dst, self.orig_shape)
 def weak_dist_bone(self, bone_hull, body):
     """ Metoda pro zjisteni, jak blizko jsme stredu (nejvzdalenejsimu mistu od povrchu) """
     blank_body = np.ones(body.shape)
     bone_edge_dist = scipy.ndimage.morphology.distance_transform_edt(bone_hull)
     bone_edge_dist_maximum = np.max(bone_edge_dist)
     bone_edge_dist_focus = bone_edge_dist > 0*bone_edge_dist_maximum
     blank_body[:] = bone_edge_dist_focus
     ld = scipy.ndimage.morphology.distance_transform_edt(blank_body)
     return resize_to_shape(ld, self.ss.orig_shape)
 def weak_dist_bone(self, bone_hull, body):
     """ Metoda pro zjisteni, jak blizko jsme stredu (nejvzdalenejsimu mistu od povrchu) """
     blank_body = np.ones(body.shape)
     bone_edge_dist = scipy.ndimage.morphology.distance_transform_edt(
         bone_hull)
     bone_edge_dist_maximum = np.max(bone_edge_dist)
     bone_edge_dist_focus = bone_edge_dist > 0 * bone_edge_dist_maximum
     blank_body[:] = bone_edge_dist_focus
     ld = scipy.ndimage.morphology.distance_transform_edt(blank_body)
     return resize_to_shape(ld, self.ss.orig_shape)
Example #8
0
 def dist_to_ribs(self):
     """
     Distance to ribs.
     The distance is grater than zero inside of body and outside of body
     """
     if self.ribs is None:
         self.get_ribs()
     ld = scipy.ndimage.morphology.distance_transform_edt(1 - self.ribs)
     ld = ld * float(self.working_vs[0])  # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #9
0
 def dist_to_chest(self):
     if self.chest is None:
         self.get_ribs()
     ld_positive = scipy.ndimage.morphology.distance_transform_edt(
         self.chest)
     ld_negative = scipy.ndimage.morphology.distance_transform_edt(
         1 - self.chest)
     ld = ld_positive - ld_negative
     ld = ld * float(self.working_vs[0])  # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #10
0
 def dist_to_ribs(self):
     """
     Distance to ribs.
     The distance is grater than zero inside of body and outside of body
     """
     if self.ribs is None:
         self.get_ribs()
     ld = scipy.ndimage.morphology.distance_transform_edt(1 - self.ribs)
     ld = ld * float(self.working_vs[0]) # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #11
0
    def dist_axial(self):
        if self.diaphragm_mask is None:
            self.get_diaphragm_mask(skip_resize=True)
        axdst = np.ones(self.data3dr.shape, dtype=np.int16)
        axdst[0 ,: ,:] = 0
        iz, ix, iy = np.nonzero(self.diaphragm_mask)
        # print 'dia level ', self.diaphragm_mask_level

        axdst = scipy.ndimage.morphology.distance_transform_edt(axdst) - int(self.diaphragm_mask_level)
        axdst = axdst * self.working_vs[0]
        return resize_to_shape(axdst, self.orig_shape)
Example #12
0
    def dist_axial(self):
        if self.diaphragm_mask is None:
            self.get_diaphragm_mask()
        axdst = np.ones(self.data3dr.shape, dtype=np.int16)
        axdst[0, :, :] = 0
        iz, ix, iy = np.nonzero(self.diaphragm_mask)
        # print 'dia level ', self.diaphragm_mask_level

        axdst = scipy.ndimage.morphology.distance_transform_edt(axdst) - int(
            self.diaphragm_mask_level)
        return resize_to_shape(axdst, self.orig_shape)
Example #13
0
 def dist_to_surface(self):
     """
     Positive values in mm inside of body.
     :return:
     """
     if self.body is None:
         self.get_body(skip_resize=True)
     # return self._resize_and_dist(self.body)
     ld = scipy.ndimage.morphology.distance_transform_edt(self.body)
     ld = ld*float(self.working_vs[0]) # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #14
0
    def get_body(self):
        # create segmented 3d data
        body = OrganDetectionAlgo.getBody(\
            scipy.ndimage.filters.gaussian_filter(self.data3dr, sigma=2), \
            self.working_vs)
        self.body = body

        # get body width and height
        widths = []
        heights = []
        for z in range(body.shape[0]):
            x_sum = np.sum(body[z, :, :], axis=0)  # suma kazdeho sloupcu
            x_start = next((i for i, x in enumerate(list(x_sum)) if x != 0),
                           None)
            x_end = next(
                (i for i, x in enumerate(reversed(list(x_sum))) if x != 0),
                None)
            if x_start is None or x_end is None:
                width = 0
            else:
                width = (body.shape[2] - x_end) - x_start
            widths.append(width)

            y_sum = np.sum(body[z, :, :], axis=1)  # suma kazdeho radku
            y_start = next((i for i, y in enumerate(list(y_sum)) if y != 0),
                           None)
            y_end = next(
                (i for i, y in enumerate(reversed(list(y_sum))) if y != 0),
                None)
            if y_start is None or y_end is None:
                height = 0
            else:
                height = (body.shape[1] - y_end) - y_start
            heights.append(height)

        # get value which is bigger then 90% of calculated values (to ignore bad data)
        body_width = np.percentile(np.asarray(widths), 90.0)
        body_height = np.percentile(np.asarray(heights), 90.0)
        # convert to original resolution
        body_width = body_width * (self.orig_shape[2] /
                                   float(self.body.shape[2]))
        body_height = body_height * (self.orig_shape[1] /
                                     float(self.body.shape[1]))
        # conver to mm
        self.body_width = body_width * float(self.voxelsize_mm[2])
        self.body_height = body_height * float(self.voxelsize_mm[1])

        return resize_to_shape(self.body, self.orig_shape)
Example #15
0
    def dist_diaphragm(self):
        """
        Get positive values in superior to (above) diaphragm and negative values inferior (under) diaphragm.
        :return:
        """
        if self.diaphragm_mask is None:
            self.get_diaphragm_mask(skip_resize=True)
        dst = (scipy.ndimage.morphology.distance_transform_edt(
                self.diaphragm_mask)#, sampling=self.voxelsize_mm)
               -
               scipy.ndimage.morphology.distance_transform_edt(
                1 - self.diaphragm_mask)#, sampling=self.voxelsize_mm)
              )

        dst = dst * self.working_vs[0]
        return resize_to_shape(dst, self.orig_shape)
Example #16
0
    def get_body(self, skip_resize=False):
        # create segmented 3d data
        body = OrganDetectionAlgo.getBody(\
            scipy.ndimage.filters.gaussian_filter(self.data3dr, sigma=2), \
            self.working_vs)
        self.body = body

        # get body width and height
        widths = []; heights = []
        for z in range(body.shape[0]):
            x_sum = np.sum(body[z, :, :], axis=0) # suma kazdeho sloupcu
            x_start = next((i for i, x in enumerate(list(x_sum)) if x!=0), None)
            x_end = next((i for i, x in enumerate(reversed(list(x_sum))) if x!=0), None)
            if x_start is None or x_end is None:
                width = 0
            else:
                width = (body.shape[2]-x_end) - x_start
            widths.append(width)

            y_sum = np.sum(body[z, :, :], axis=1) # suma kazdeho radku
            y_start = next((i for i, y in enumerate(list(y_sum)) if y!=0), None)
            y_end = next((i for i, y in enumerate(reversed(list(y_sum))) if y!=0), None)
            if y_start is None or y_end is None:
                height = 0
            else:
                height = (body.shape[1]-y_end) - y_start
            heights.append(height)

        # get value which is bigger then 90% of calculated values (to ignore bad data)
        body_width = np.percentile(np.asarray(widths), 90.0)
        body_height = np.percentile(np.asarray(heights), 90.0)
        # convert to original resolution
        body_width = body_width * (self.orig_shape[2]/float(self.body.shape[2]))
        body_height = body_height * (self.orig_shape[1]/float(self.body.shape[1]))
        # conver to mm
        self.body_width = body_width * float(self.voxelsize_mm[2])
        self.body_height = body_height * float(self.voxelsize_mm[1])

        if skip_resize:
            return self.body
        else:
            return resize_to_shape(self.body, self.orig_shape)
Example #17
0
    def get_lungs_orig(self, skip_resize=False):
        lungs_density_threshold_hu = -150
        lungs = scipy.ndimage.filters.gaussian_filter(self.data3dr, sigma=[4, 2, 2]) > lungs_density_threshold_hu

        if self.head_first:
            bottom_slice_id = -1
        else:
            bottom_slice_id = 0
        lungs[bottom_slice_id, :, :] = 1

        lungs = scipy.ndimage.morphology.binary_fill_holes(lungs)
        labs, n = scipy.ndimage.measurements.label(lungs==0)
        cornerlab = [
            labs[0,0,0],
            labs[0,0,-1],
            labs[0,-1,0],
            labs[0,-1,-1],
            labs[-1,0,0],
            labs[-1,0,-1],
            labs[-1,-1,0],
            labs[-1,-1,-1]
            ]

        lb = np.median(cornerlab)
        labs[labs==lb] = 0

        labs[labs==labs[0,0,0]] = 0
        labs[labs==labs[0,0,-1]] = 0
        labs[labs==labs[0,-1,0]] = 0
        labs[labs==labs[0,-1,-1]] = 0
        labs[labs==labs[-1,0,0]] = 0
        labs[labs==labs[-1,0,-1]] = 0
        labs[labs==labs[-1,-1,0]] = 0
        labs[labs==labs[-1,-1,-1]] = 0

        lungs = labs > 0
        self.lungs = lungs
        #self.body = (labs == 80)
        if skip_resize:
            return self.lungs
        else:
            return resize_to_shape(lungs, self.orig_shape)
Example #18
0
def uncrop(data, crinfo, orig_shape, resize=False):

    crinfo = fix_crinfo(crinfo)
    data_out = np.zeros(orig_shape, dtype=data.dtype)

    # print 'uncrop ', crinfo
    # print orig_shape
    # print data.shape
    if resize:
        data = resize_to_shape(data, crinfo[:, 1] - crinfo[:, 0])

    startx = np.round(crinfo[0][0]).astype(int)
    starty = np.round(crinfo[1][0]).astype(int)
    startz = np.round(crinfo[2][0]).astype(int)

    data_out[
        # np.round(crinfo[0][0]).astype(int):np.round(crinfo[0][1]).astype(int)+1,
        # np.round(crinfo[1][0]).astype(int):np.round(crinfo[1][1]).astype(int)+1,
        # np.round(crinfo[2][0]).astype(int):np.round(crinfo[2][1]).astype(int)+1
        startx:startx + data.shape[0], starty:starty + data.shape[1],
        startz:startz + data.shape[2]] = data

    return data_out
Example #19
0
    def get_diaphragm_mask(self, axis=0):
        if self.lungs is None:
            self.get_lungs()
        ia, ib, ic = self._get_ia_ib_ic(axis)
        data = self.lungs
        ou = self.get_diaphragm_profile_image(axis=axis)
        # reconstruction mask array
        mask = np.zeros(data.shape)
        for i in range(mask.shape[ia]):
            if ia == 0:
                mask[i, :, :] = ou > i
            elif ia == 1:
                mask[:, i, :] = ou > i
            elif ia == 2:
                mask[:, :, i] = ou > i

        self.diaphragm_mask = mask

        # maximal point is used for axial ze
        # ro plane
        self.diaphragm_mask_level = np.median(ou)
        self.center0 = self.diaphragm_mask_level * self.working_vs[0]

        return resize_to_shape(self.diaphragm_mask, self.orig_shape)
Example #20
0
    def get_diaphragm_mask(self, axis=0, skip_resize=False):
        """
        Get False in inferior to diaphragm and True in superior to diaphragm.
        :param axis:
        :param skip_resize:
        :return: Boolean 3D ndarray
        """
        if self.lungs is None:
            self.get_lungs()
        ia, ib, ic = self._get_ia_ib_ic(axis)
        data = self.lungs
        ou = self.get_diaphragm_profile_image(axis=axis)
        # reconstruction mask array
        mask = np.zeros(data.shape)
        for i in range(mask.shape[ia]):
            if ia == 0:
                mask[i,:,:] = ou > i
            elif ia == 1:
                mask[:,i,:] = ou > i
            elif ia == 2:
                mask[:,:,i] = ou > i

        if not self.head_first:
            # invert mask
            mask = mask == False

        self.diaphragm_mask = mask

        # maximal point is used for axial ze
        # ro plane
        self.diaphragm_mask_level = np.median(ou)
        self.center0 = self.diaphragm_mask_level * self.working_vs[0]

        if skip_resize:
            return self.diaphragm_mask
        return resize_to_shape(self.diaphragm_mask, self.orig_shape)
Example #21
0
    def get_lungs_martin(self):
        '''
        Improved version of get.lungs function. Call with ss.get_lungs if get_lungs_martin is default.
        first part checks if the CT-bed enables a clear segmentation of the background.
        Then we threshold and label all cavities. After that, we compare the mean value of the real grayscale-image in
        these labeled areas and only take the brighter ones. (Because in lung areas there are "white" alveoli)
        '''

        lungs = scipy.ndimage.filters.gaussian_filter(self.data3dr, sigma=[4, 2, 2]) > -450
        lungs[0, :, :] = 1

        lungs = scipy.ndimage.morphology.binary_fill_holes(lungs)
        labs, n = scipy.ndimage.measurements.label(lungs == 0)
        cornerlab = [
            labs[0, 0, 0],
            labs[0, 0, -1],
            labs[0, -1, 0],
            labs[0, -1, -1],
            labs[-1, 0, 0],
            labs[-1, 0, -1],
            labs[-1, -1, 0],
            labs[-1, -1, -1]
        ]

        lb = np.median(cornerlab)
        labs[labs == lb] = 0

        labs[labs == labs[0, 0, 0]] = 0
        labs[labs == labs[0, 0, -1]] = 0
        labs[labs == labs[0, -1, 0]] = 0
        labs[labs == labs[0, -1, -1]] = 0
        labs[labs == labs[-1, 0, 0]] = 0
        labs[labs == labs[-1, 0, -1]] = 0
        labs[labs == labs[-1, -1, 0]] = 0
        labs[labs == labs[-1, -1, -1]] = 0

        lungs = labs > 0
        self.lungs = lungs
        # self.body = (labs == 80)


    # new code transformed into function

        segmented = self.data3dr < -400

        preselection_cavities = lungs * segmented

        #setting the first slice to one to close all of the cavities, so the fill holes works better
        first_slice = copy.copy(preselection_cavities[-1, :, :])  # -1 means last slice, which is here the uppest in the image
        preselection_cavities[-1, :, :] = 1
        precav_filled = scipy.ndimage.morphology.binary_fill_holes(preselection_cavities)
        precav_filled[-1, :, :] = first_slice

        precav_erosion = scipy.ndimage.morphology.binary_erosion(precav_filled)
        labeled = skimage.morphology.label(precav_erosion)

        for f in range(1, np.max(labeled) + 1):

            cavity = self.data3dr[labeled == f]

            cavity_mean_intensity = np.std(cavity)

            if cavity_mean_intensity > 50: #not too sure about the value of 50
                #idea would be to take the mean value of the highest ones and set the little lower one as the limit
                # this sets not lung-areas to zero. Theoretically :D
                precav_erosion[labeled == f] = 0
                #print(cavity_mean_intensity)

        precav_erosion = scipy.ndimage.morphology.binary_dilation(precav_filled) #dilation becuase of erosion before

        # return precav_erosion
        self.lungs = precav_erosion
        return resize_to_shape(precav_erosion, self.orig_shape)
Example #22
0
 def _resize_to_orig_shape(self, data):
     return resize_to_shape(data, self.orig_shape)
Example #23
0
 def dist_to_lungs(self):
     if self.lungs is None:
         self.get_lungs()
     ld = scipy.ndimage.morphology.distance_transform_edt(1 - self.lungs)
     ld = ld*float(self.working_vs[0]) # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #24
0
 def dist_to_spine(self):
     if self.spine_wvs is None:
         self.get_spine(skip_resize=True)
     ld = scipy.ndimage.morphology.distance_transform_edt(1 - self.spine_wvs)
     ld = ld*float(self.working_vs[0]) # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #25
0
 def dist_to_surface(self):
     if self.body is None:
         self.get_body()
     ld = scipy.ndimage.morphology.distance_transform_edt(self.body)
     ld = ld * float(self.working_vs[0])  # convert distances to mm
     return resize_to_shape(ld, self.orig_shape)
Example #26
0
    def get_lungs_martin(self):
        '''
        Improved version of get.lungs function. Call with ss.get_lungs if get_lungs_martin is default.
        first part checks if the CT-bed enables a clear segmentation of the background.
        Then we threshold and label all cavities. After that, we compare the mean value of the real grayscale-image in
        these labeled areas and only take the brighter ones. (Because in lung areas there are "white" alveoli)
        '''

        lungs = scipy.ndimage.filters.gaussian_filter(self.data3dr,
                                                      sigma=[4, 2, 2]) > -450
        lungs[0, :, :] = 1

        lungs = scipy.ndimage.morphology.binary_fill_holes(lungs)
        labs, n = scipy.ndimage.measurements.label(lungs == 0)
        cornerlab = [
            labs[0, 0, 0], labs[0, 0, -1], labs[0, -1, 0], labs[0, -1, -1],
            labs[-1, 0, 0], labs[-1, 0, -1], labs[-1, -1, 0], labs[-1, -1, -1]
        ]

        lb = np.median(cornerlab)
        labs[labs == lb] = 0

        labs[labs == labs[0, 0, 0]] = 0
        labs[labs == labs[0, 0, -1]] = 0
        labs[labs == labs[0, -1, 0]] = 0
        labs[labs == labs[0, -1, -1]] = 0
        labs[labs == labs[-1, 0, 0]] = 0
        labs[labs == labs[-1, 0, -1]] = 0
        labs[labs == labs[-1, -1, 0]] = 0
        labs[labs == labs[-1, -1, -1]] = 0

        lungs = labs > 0
        self.lungs = lungs
        # self.body = (labs == 80)

        # new code transformed into function

        segmented = self.data3dr < -400

        preselection_cavities = lungs * segmented

        #setting the first slice to one to close all of the cavities, so the fill holes works better
        first_slice = copy.copy(
            preselection_cavities[-1, :, :]
        )  # -1 means last slice, which is here the uppest in the image
        preselection_cavities[-1, :, :] = 1
        precav_filled = scipy.ndimage.morphology.binary_fill_holes(
            preselection_cavities)
        precav_filled[-1, :, :] = first_slice

        precav_erosion = scipy.ndimage.morphology.binary_erosion(precav_filled)
        labeled = skimage.morphology.label(precav_erosion)

        for f in range(1, np.max(labeled) + 1):

            cavity = self.data3dr[labeled == f]

            cavity_mean_intensity = np.std(cavity)

            if cavity_mean_intensity > 50:  #not too sure about the value of 50
                #idea would be to take the mean value of the highest ones and set the little lower one as the limit
                # this sets not lung-areas to zero. Theoretically :D
                precav_erosion[labeled == f] = 0
                #print(cavity_mean_intensity)

        precav_erosion = scipy.ndimage.morphology.binary_dilation(
            precav_filled)  #dilation becuase of erosion before

        # return precav_erosion
        self.lungs = precav_erosion
        return resize_to_shape(precav_erosion, self.orig_shape)