Ejemplo n.º 1
0
def detect_plate(image):
    """
    Crops to plate and outputs mask (assumes it was taken on a dark background)
    :param image:
    :return:
    """

    lab = rgb2lab(image)
    l = lab[:, :,
            0]  # Lum is the only channel we really care about for plate segmentation
    edges = canny(l, 30)
    filled = binary_fill_holes(edges)
    eroded = binary_erosion(filled, disk(10))
    mask = binary_dilation(eroded, disk(10))  # This is the mask

    mask_area = np.count_nonzero(mask)
    plate_radius = np.sqrt(mask_area / np.pi)
    padded_plate_radius = plate_radius + 0.1 * plate_radius

    indices = np.argwhere(mask)
    center = np.mean(indices, axis=0)

    y_min = int(max(0, np.round(center[0] - padded_plate_radius)))
    y_max = int(min(image.shape[0], np.round(center[0] + padded_plate_radius)))
    x_min = int(max(0, np.round(center[1] - padded_plate_radius)))
    x_max = int(min(image.shape[1], np.round(center[1] + padded_plate_radius)))

    cropped_image = image[y_min:y_max, x_min:x_max, :]
    cropped_mask = mask[y_min:y_max, x_min:x_max]
    new_center = np.mean(np.argwhere(cropped_mask), axis=0)

    cropped_mask = binary_erosion(cropped_mask, structure=disk(50))

    return cropped_image, cropped_mask, new_center
Ejemplo n.º 2
0
Archivo: cafe.py Proyecto: jni/cafe
def encode_centro_telomeres(image_centro, image_telo,
                            centro_offset=0.0, centro_factor=1.0,
                            centro_min_size=36, centro_radius=10,
                            telo_offset=0.0, telo_adapt_radius=49,
                            telo_open_radius=4):
    """Find centromeres, telomeres, and their overlap.

    Parameters
    ----------
    image_centro : array, shape (M, N)
        The grayscale channel for centromeres.
    image_telo : array, shape (M, N)
        The grayscale channel for telomeres.
    centro_offset : float, optional
        Offset Otsu's threshold by this amount (i.e. be less stringent
        about what image intensity constitutes a centromere)
    centro_factor : float, optional
        Offset Otsu's threshold by a multiplicative constant.
    centro_min_size : int, optional
        Remove objects smaller than this, as they would be too small to
        be a centromere.
    centro_radius : int, optional
        Consider anything within this radius to be "near" a centromere.
    telo_offset : float, optional
        Offset the telomere image threshold by this amount.
    telo_adapt_radius : int, optional
        Use this radius to threshold telomere image adaptively.
    telo_open_radius : int, optional
        Use this radius for a binary opening of thresholded telomeres
        (removes noise).

    Returns
    -------
    encoded_regions : array of int, shape (M, N)
        A uint8 image with the following values:
         - 0: background
         - 1: telomeres
         - 2: centromeres
         - 3: centromere/telomere overlap
    """
    centros = otsu(image_centro, centro_offset, centro_factor)
    centros = remove_small_objects(centros, centro_min_size)
    centro_strel = selem.disk(centro_radius)
    centros = nd.binary_dilation(centros, structure=centro_strel)
    telos = imfilter.threshold_adaptive(image_telo, telo_adapt_radius,
                                        offset=telo_offset)
    telo_strel = selem.disk(telo_open_radius)
    telos = nd.binary_opening(telos, structure=telo_strel)
    encoded_regions = 2 * centros.astype(np.uint8) + telos
    return encoded_regions
Ejemplo n.º 3
0
def CE_e(img, radius=None, stop_condition=40):
    '''
    Contrast Enhancement of Medical X-Ray ImageUsing Morphological Operators with OptimalStructuring Element,
    https://arxiv.org/pdf/1905.08545.pdf
    :param img: 2D np array, image
    :param radius: int [1-N], radius of the structuring element used for morphology operations
    :param stop_condition: int, value to which Edge content (EC) difference is compared, if EC difference is smaller
    then 'stop_condition' current value of radius consider to be optimal (recommended: 10-100 depending on the problem)
    :return: 2D np array, Contrast enhanced image normalized in between values [0-1]
    '''
    A = minmax(img)
    ECA = np.sum(gaussian_gradient_magnitude(A, 1))
    prevEC = 0
    # radius adapt to the image
    if radius is None:
        convMtx = [np.Inf]
        for r in range(1,15):
            # define SE as B
            B = selem.disk(r)
            # opening and closing operations defined in the paper
            Atop = A - opening(A, selem=B)
            Abot = closing(A, selem=B) - A
            Aenhanced = A + Atop - Abot
            Aenhanced = np.clip(Aenhanced, a_min=0, a_max=None)
            # Edge content calculations
            EC = np.sum(gaussian_gradient_magnitude(Aenhanced, 1))
            # min max scaling processed image
            Aenhanced_normed = (Aenhanced - np.min(Aenhanced))/(np.max(Aenhanced)-np.min(Aenhanced))
            # stopping condition
            conv = EC - prevEC
            convMtx.append(conv)
            if convMtx[-2]-convMtx[-1] < stop_condition:
                break
            prevEC = EC
    # pre-defined radius
    else:
        print("Radius =", radius)
        B = selem.disk(radius)
        Atop = A - opening(A, selem=B)
        Abot = closing(A, selem=B) - A
        Aenhanced = A + Atop - Abot
        Aenhanced = np.clip(Aenhanced, a_min=0, a_max=None)

        EC = np.sum(gaussian_gradient_magnitude(Aenhanced, 1))

        Aenhanced_normed = (Aenhanced - np.min(Aenhanced)) / (np.max(Aenhanced) - np.min(Aenhanced))
        print("EC =", EC)
    return Aenhanced_normed
Ejemplo n.º 4
0
def _define_kernel(shape, size, dtype):
    """Build a kernel to apply a filter on images.

    Parameters
    ----------
    shape : str
        Shape of the kernel used to compute the filter ('diamond', 'disk',
        'rectangle' or 'square').
    size : int, Tuple(int) or List(int)
        The size of the kernel:
            - For the rectangle we expect two values (width, height).
            - For the square one value (width).
            - For the disk and the diamond one value (radius).
    dtype : type
        Dtype used for the kernel (the same as the image).

    Returns
    -------
    kernel : skimage.morphology.selem object
        Kernel to use with a skimage filter.

    """
    # build the kernel
    if shape == "diamond":
        kernel = diamond(size, dtype=dtype)
    elif shape == "disk":
        kernel = disk(size, dtype=dtype)
    elif shape == "rectangle" and isinstance(size, tuple):
        kernel = rectangle(size[0], size[1], dtype=dtype)
    elif shape == "square":
        kernel = square(size, dtype=dtype)
    else:
        raise ValueError("Kernel definition is wrong.")

    return kernel
Ejemplo n.º 5
0
Archivo: cafe.py Proyecto: jni/cafe
def get_centromere_neighbourhood(im, dilation_size=3, threshold=None,
                                 threshold_function=imfilter.threshold_otsu):
    """Obtain the locations near centromeres in an image.

    Parameters
    ----------
    im : np.ndarray, shape (M, N)
        The input image, containing fluorescently-labelled centromeres.
    dilation_size : int (optional, default 3)
        Size in pixels of neighbourhood around actual centromere locations.
    threshold : float (optional, default None)
        Use this threshold instead of one computed by `threshold_function`.
    threshold_function : function, im -> int or im -> im
                         (optional, default `skimage.filter.threshold_otsu`)
        Use this function to find a suitable threshold for the input image.

    Returns
    -------
    centro : np.ndarray of bool, shape (M, N)
        The locations around centromeres marked as `True`.
    """
    if threshold is None:
        threshold = threshold_function(im)
    centro = im > threshold
    strel = selem.disk(dilation_size)
    centro = nd.binary_dilation(centro, structure=strel)
    return centro
Ejemplo n.º 6
0
def find_valid_pixels(mDataTrain):
    # find valid pixels
    mThresh = 0.75
    mm = mDataTrain > mThresh
    strel = selem.disk(5)
    mm = binary.binary_dilation(mm, strel)
    mm = morphology.remove_small_objects(mm, 1000, 4)
    pixValid = mm[mm > 0]
    return pixValid
Ejemplo n.º 7
0
def grabcut_binarization(bfly_rgb, bfly_bin):
    """Extract shape of the butterfly using OpenCV's grabcut. Greatly improves
    binarization of blue-colored butterflies.

    Arguments
    ---------
    bfly_rgb : (M, N, 3) ndarray
        Input RGB image of butterfly (ruler and tags cropped out)
    bfly_bin : (M, N) ndarray
        Binarizaed image of butterfly (ruler and tags cropped out) Expected 
        to be binarized saturation channel of bfly_rgb.

    Returns
    -------
    bfly_grabcut_bin : (M, N) ndarray
        Resulting binarized image of butterfly after segmentation by grabcut.
    """

    # Dilation of image to capture butterfly region
    selem_arr = selem.disk(DILATION_SIZE)
    bfly_bin_dilated = binary_dilation(bfly_bin, selem_arr)
    bfly_bin_dilated_markers, _ = ndi.label(
        bfly_bin_dilated, ndi.generate_binary_structure(2, 1))
    bfly_bin_dilated_regions = regionprops(bfly_bin_dilated_markers)
    bfly_bin_dilated_regions_sorted = sorted(bfly_bin_dilated_regions,
                                             key=lambda r: r.area,
                                             reverse=True)
    bfly_region = bfly_bin_dilated_regions_sorted[0]

    # Downscale image to improve grabcut speed
    bfly_rgb_rescale = rescale(bfly_rgb, GRABCUT_RESCALE_FACTOR)
    bfly_rgb_rescale = img_as_ubyte(bfly_rgb_rescale)

    # Determine grabcut highlight region using butterfly region (after rescaling)
    padding = 0
    rect = (int(GRABCUT_RESCALE_FACTOR * bfly_region.bbox[1] - padding),
            int(GRABCUT_RESCALE_FACTOR * bfly_region.bbox[0] - padding),
            int(GRABCUT_RESCALE_FACTOR * bfly_region.bbox[3] + padding),
            int(GRABCUT_RESCALE_FACTOR * bfly_region.bbox[2] + padding))

    # Grabcut
    mask = np.zeros(bfly_rgb_rescale.shape[:2], np.uint8)
    bgd_model = np.zeros((1, 65), np.float64)
    fgd_model = np.zeros((1, 65), np.float64)

    cv.grabCut(bfly_rgb_rescale, mask, rect, bgd_model, fgd_model,
               GRABCUT_ITERATIONS, cv.GC_INIT_WITH_RECT)

    mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
    bfly_grabcut_rescale = bfly_rgb_rescale * mask2[:, :, np.newaxis]

    # Rescale the image back up and get binary of result
    bfly_grabcut = rescale(bfly_grabcut_rescale,
                           bfly_rgb.shape[0] / bfly_rgb_rescale.shape[0])
    bfly_grabcut_bin = np.max(bfly_grabcut, axis=2) > 0

    return bfly_grabcut_bin
def find_valid_pixels(mDataTrain):
	# find valid pixels
	mThresh = 0.75
	mm = mDataTrain > mThresh
	strel = selem.disk(5)
	mm = binary.binary_dilation(mm, strel)
	mm = morphology.remove_small_objects(mm, 1000, 4)
	pixValid = mm[mm > 0]
	return pixValid
Ejemplo n.º 9
0
	def callback(self, image, info, jstate, seg_res_msg):
		# only process if moving slowly
		if np.linalg.norm(np.asarray(jstate.velocity)[2:9]) > 1e-1:
			rospy.logdebug("!!!To fast!!! {} | {}".format(np.linalg.norm(jstate.velocity), np.asarray(jstate.velocity)[2:9]))
			return
			
		cv_image = self.depth_scale*self.bridge.imgmsg_to_cv2(image, desired_encoding="32FC1").copy()
		old_shape = cv_image.shape
		cv_image = cv2.resize(cv_image, (240, 180), interpolation=cv2.INTER_NEAREST)  # TODO: Define and use a central point where voxel size, max distance and viewfield are given as a rosparam and adapt along the image chain
		mask = np.bitwise_or(np.bitwise_and(self.value_to_replace-0.1 < cv_image, cv_image < self.value_to_replace+0.1), (cv_image < 0.1)) # get robot and invalid pixels 
		mask = binary_dilation(mask, structure=disk(10)) # grow regions of robot pixels
		# mask = binary_dilation(mask, structure=disk(25)) # grow regions of robot pixels
		cv_image[mask] = np.nan # Replace extended robot pixels with nan
		# mask =  cv_image < 0.1 # remove close pixels where filter fails
		# cv_image[mask] = np.nan
		
		# cv_rgb_image = self.bridge.imgmsg_to_cv2(rgb_image, desired_encoding="passthrough").copy()
		# cv_rgb_image = cv2.resize(cv_rgb_image, (240, 180), interpolation=cv2.INTER_NEAREST)
		cv_seg_image_cans = self.filter_seg_res(seg_res_msg, ["bottle", "cup"], np.asarray([255, 0, 0], dtype=np.uint8))
		cv_seg_image_table = self.filter_seg_res(seg_res_msg, ["dining table"], np.asarray([0, 255, 0], dtype=np.uint8))
		cv_seg_image = cv_seg_image_cans
		cv_seg_image[cv_seg_image_cans[:,:,0]==0] = cv_seg_image_table[cv_seg_image_cans[:,:,0]==0] # Table is in the background # Be more clever --> bigger objects must be farther in the background?!
		cv_seg_image = cv2.resize(cv_seg_image, (240, 180), interpolation=cv2.INTER_NEAREST)
		
		try:
			new_depth_img_msg = self.bridge.cv2_to_imgmsg(cv_image, "32FC1")
			new_depth_img_msg.header = image.header
			new_depth_img_msg.header.frame_id = "panda/panda_camera"
			new_seg_image_msg = self.bridge.cv2_to_imgmsg(cv_seg_image, "rgb8")
			new_seg_image_msg.header = seg_res_msg.header
			new_seg_image_msg.header.frame_id = "panda/panda_camera"
			new_info = deepcopy(info)
			new_info.header = info.header
			new_info.header.frame_id = "panda/panda_camera"
			new_info.height = 180
			new_info.width = 240
			# print("Old image size: {}, new: {}".format(old_shape, cv_image.shape))
			new_info.K = np.asarray(new_info.K)
			new_info.K[0] = new_info.K[0] * 240.0/old_shape[1] # from https://answers.opencv.org/question/150551/how-does-resizing-an-image-affect-the-intrinsics/
			new_info.K[4] = new_info.K[4] * 180.0/old_shape[0]
			new_info.K[2] = new_info.K[2] * 240.0/old_shape[1]
			new_info.K[5] = new_info.K[5] * 180.0/old_shape[0]
			new_info.P = np.asarray(new_info.P)
			new_info.P[0] = new_info.P[0] * 240.0/old_shape[1] 
			new_info.P[2] = new_info.P[2] * 240.0/old_shape[1]
			new_info.P[5] = new_info.P[5] * 180.0/old_shape[0]
			new_info.P[6] = new_info.P[6] * 180.0/old_shape[0]
			
			self.image_pub.publish(new_depth_img_msg)
			rospy.logdebug("Image sent")
			self.rgb_image_pub.publish(new_seg_image_msg)
			rospy.logdebug("RGB Image sent")
			self.info_pub.publish(new_info)
			rospy.logdebug("Camera Info sent")
		except CvBridgeError as e:
			rospy.logerr(e)
Ejemplo n.º 10
0
    def setUp(self):
        k = 5
        arrname = '%03i' % k

        self.disk = selem.disk(k)

        fname_opening = os.path.join(data_dir, "disk-open-matlab-output.npz")
        self.expected_opening = np.load(fname_opening)[arrname]

        fname_closing = os.path.join(data_dir, "disk-close-matlab-output.npz")
        self.expected_closing = np.load(fname_closing)[arrname]
Ejemplo n.º 11
0
def create_mask(im_arr, erode=0):

    if im_arr.shape[2] == 3:
        im_arr = rgb2gray(im_arr)

    thresh = 0.05
    inv_bin = np.invert(im_arr > thresh)
    all_labels = measure.label(inv_bin)

    # Select largest object and invert
    seg_arr = all_labels == 0

    if erode > 0:
        strel = selem.disk(erode, dtype=np.bool)
        seg_arr = binary_erosion(seg_arr, selem=strel)
    elif erode < 0:
        strel = selem.disk(abs(erode), dtype=np.bool)
        seg_arr = binary_dilation(seg_arr, selem=strel)

    return seg_arr.astype(np.bool)
Ejemplo n.º 12
0
    def setUp(self):
        k = 5
        arrname = '%03i' % k

        self.disk = selem.disk(k)

        fname_opening = os.path.join(data_dir, "disk-open-matlab-output.npz")
        self.expected_opening = np.load(fname_opening)[arrname]

        fname_closing = os.path.join(data_dir, "disk-close-matlab-output.npz")
        self.expected_closing = np.load(fname_closing)[arrname]
Ejemplo n.º 13
0
def generate_spot_background(spotmask, distance=3, annulus=5):
    """
    
    compute an annulus around each spot to estimate background.
    
    Parameters
    ----------
    spotmask : binary mask of spots
    distance : distance from the edge of segmented spot.
    annulus : width of the annulus

    Returns
    -------
    spotbackgroundmask: binary mask of annuli around spots.
    
    TODO: 'comets' should be ignored, and this approach may not be robust to it.
    """
    se_inner = selem.disk(distance, dtype=bool)
    se_outer = selem.disk(distance+annulus, dtype=bool)
    inner = binary_dilation(spotmask, se_inner)
    outer = binary_dilation(spotmask, se_outer)
    spot_background = np.bitwise_xor(inner, outer)

    return spot_background
Ejemplo n.º 14
0
def basic_pen_mask(image, pen_size_threshold, pen_mask_expansion):
    green_mask = np.bitwise_and(
        image[:, :, RGB_GREEN_CHANNEL] > image[:, :, RGB_GREEN_CHANNEL],
        image[:, :, RGB_GREEN_CHANNEL] - image[:, :, RGB_GREEN_CHANNEL] >
        MIN_COLOR_DIFFERENCE)

    blue_mask = np.bitwise_and(
        image[:, :, RGB_BLUE_CHANNEL] > image[:, :, RGB_GREEN_CHANNEL],
        image[:, :, RGB_BLUE_CHANNEL] - image[:, :, RGB_GREEN_CHANNEL] >
        MIN_COLOR_DIFFERENCE)

    masked_pen = np.bitwise_or(green_mask, blue_mask)
    new_mask_image = remove_small_objects(masked_pen, pen_size_threshold)

    return maximum(np.where(new_mask_image, 1, 0),
                   disk(pen_mask_expansion)).astype(bool)
Ejemplo n.º 15
0
def features_opening_aubin(opening_sizes, rna_coord, mask_cyt):
    # get number of rna
    nb_rna = len(rna_coord)

    # apply opening operator and count the loss of rna
    features = []
    for size in opening_sizes:
        s = disk(size, dtype=bool)
        mask_cyt_transformed = binary_opening(mask_cyt, selem=s)
        mask_rna = mask_cyt_transformed[rna_coord[:, 1], rna_coord[:, 2]]
        rna_after_opening = rna_coord[mask_rna]

        nb_rna_after_opening = len(rna_after_opening)
        diff_opening = (nb_rna - nb_rna_after_opening) / nb_rna
        features.append(diff_opening)

    return features
Ejemplo n.º 16
0
def create_mask(im_arr, erode=3):

    if im_arr.shape[2] == 3:
        im_arr = rgb2gray(im_arr)

    thresh = threshold_otsu(im_arr)
    inv_bin = np.invert(im_arr > thresh)
    all_labels = measure.label(inv_bin)

    # Select largest object and invert
    seg_arr = np.invert(all_labels == 1)

    if erode:
        strel = selem.disk(erode, dtype=np.bool)
        seg_arr = binary_erosion(seg_arr, selem=strel)

    return seg_arr.astype(np.bool)
Ejemplo n.º 17
0
def features_protrusion(rna_coord_out, mask_cyt, mask_nuc, mask_cyt_out):
    # get number of rna outside nucleus and cell area
    nb_rna_out = len(rna_coord_out)
    area_nuc = mask_nuc.sum()
    area_cyt_out = mask_cyt_out.sum()
    eps = stack.get_eps_float32()

    # case where we do not detect any rna outside the nucleus
    if nb_rna_out == 0:
        features = [0., np.log2(eps), 0.]
        return features

    # apply opening operator and count the loss of rna outside the nucleus
    features = []
    for size in [30]:
        s = disk(size, dtype=bool)
        mask_cyt_transformed = binary_opening(mask_cyt, selem=s)
        mask_cyt_transformed[mask_nuc] = True
        new_area_cell_out = mask_cyt_transformed.sum() - area_nuc
        area_protrusion = area_cyt_out - new_area_cell_out
        if area_protrusion > 0:
            factor = nb_rna_out * area_protrusion / area_cyt_out
            mask_rna = mask_cyt_transformed[rna_coord_out[:, 1],
                                            rna_coord_out[:, 2]]
            rna_after_opening = rna_coord_out[mask_rna]
            nb_rna_protrusion = nb_rna_out - len(rna_after_opening)
            index_rna_opening = (nb_rna_protrusion + eps) / factor
            log2_index_rna_opening = np.log2(index_rna_opening)
            proportion_rna_opening = nb_rna_protrusion / nb_rna_out

            features += [
                index_rna_opening, log2_index_rna_opening,
                proportion_rna_opening
            ]
        else:
            features += [0., np.log2(eps), 0.]

    return features
Ejemplo n.º 18
0
    def generate_circle_map(game, sprites_group, rows, columns):
        """Map with circular sea in the center."""
        ones = np.ones((rows, columns), dtype=np.uint8)
        ones[int(rows / 2), int(columns / 2)] = 0  # 0 pixel in the middle
        se = selem.disk(int(min([rows, columns]) /
                            2))  # radius of se R = 1/3 of min(row,col)
        ones = erosion(ones,
                       selem=se)  # expand (erode) the central 0 pixel to R

        land_bool_map = ones > 0
        mountains_bool_map = MapGenerator.generate_mountains(rows, columns)
        coast_bool_map = feature.canny(255 *
                                       np.array(land_bool_map, dtype=np.uint8))

        # make mountains only on land:
        mountains_bool_map = np.logical_and(mountains_bool_map, land_bool_map)

        number_map = np.zeros((rows, columns), dtype=np.uint8)
        number_map[land_bool_map] = TILE_TYPE_DICT['land']
        number_map[coast_bool_map] = TILE_TYPE_DICT['sand']
        number_map[mountains_bool_map] = TILE_TYPE_DICT['mountain']

        return MapGenerator.generate_tiles(game, sprites_group, number_map)
Ejemplo n.º 19
0
def _define_kernel(shape, size, dtype):
    """Build a kernel to apply a filter on images.

    Parameters
    ----------
    shape : str
        Shape of the kernel used to compute the filter (`diamond`, `disk`,
        `rectangle` or `square`).
    size : int, Tuple(int) or List(int)
        The size of the kernel:
            - For the rectangle we expect two values (`height`, `width`).
            - For the square one value (`width`).
            - For the disk and the diamond one value (`radius`).
    dtype : type
        Dtype used for the kernel (the same as the image).

    Returns
    -------
    kernel : skimage.morphology.selem object
        Kernel to use with a skimage filter.

    """
    # build the kernel
    if shape == "diamond":
        kernel = diamond(size, dtype=dtype)
    elif shape == "disk":
        kernel = disk(size, dtype=dtype)
    elif shape == "rectangle" and isinstance(size, (tuple, list)):
        kernel = rectangle(size[0], size[1], dtype=dtype)
    elif shape == "square":
        kernel = square(size, dtype=dtype)
    else:
        raise ValueError("Kernel definition is wrong. Shape of the kernel "
                         "should be 'diamond', 'disk', 'rectangle' or "
                         "'square'. Not {0}.".format(shape))

    return kernel
Ejemplo n.º 20
0
Archivo: cafe.py Proyecto: jni/cafe
def get_chromatin(im, background_diameter=51, opening_size=2, opening_iter=2,
                  size_filter=256):
    """Find the chromatin in an unevenly illuminated image.

    Parameters
    ----------
    im : np.ndarray, shape (M, N)
        The chromatin grayscale image.
    background_diameter : int, optional
        The diameter of the block size in which to find the background. (This
        is used by the scikit-image function `threshold_adaptive`.)
        (default: 51)
    opening_size : int, optional
        Perform a binary opening with a disk of this radius. (default: 2)
    opening_iter : int, optional
        Perform this many opening iterations. (default: 2)
    size_filter : int, optional
        After the morphological opening, filter out segments smaller than this
        size. (default: 256)

    Returns
    -------
    chrs : np.ndarray, shape (M, N)
        A thresholded image of the chromatin regions.
    """
    if im.ndim == 3 and im.shape[2] == 3:
        im = im[..., 0]
    fg = imfilter.threshold_adaptive(im, background_diameter)
    # on an unevenly lit image, `fg` will have all sorts of muck lying around,
    # in addition to the chromatin. Thankfully, the muck is noisy and full of
    # holes, whereas the chromatin is solid. An opening followed by a size
    # filtering removes it quite effectively.
    strel = selem.disk(opening_size)
    fg_open = nd.binary_opening(fg, strel, iterations=opening_iter)
    chrs = remove_small_objects(fg_open, size_filter)
    return chrs
Ejemplo n.º 21
0
    def segment(self, img, plot=False):
        # print("Segmenting shape ", np.asarray(img).shape)

        new_mask = np.zeros(shape=color.rgb2ycbcr(img).shape)
        """

        ##### HISTOGRAM BASED #######################################
        img_transformed = color.rgb2ycbcr(img)
        new_mask[(img_transformed[:,:,1] > self.LOWER_THRESHOLD_R) & (img_transformed[:,:,1] < self.UPPER_THRESHOLD_R) & (img_transformed[:,:,2] > self.LOWER_THRESHOLD_B) &(img_transformed[:,:,2] < self.UPPER_THRESHOLD_B)] = 1
        ##### UNCOMMENT THIS IF YOU WANT TO CHANGE THE STRATEGY #####

        img_RGB = img.copy()
        img_HSV = color.rgb2hsv(img)

        new_mask[(img_HSV[:,:,0] >= 0) &
        (img_HSV[:,:,0] <= 50) &
        (img_HSV[:,:,1] >= 0.23) &
        (img_HSV[:,:,1] <= 0.68) &
        (img_RGB[:,:,0] > 95) &
        (img_RGB[:,:,1] > 40) &
        (img_RGB[:,:,2] > 20) &
        (img_RGB[:,:,0] > img_RGB[:,:,1]) &
        (img_RGB[:,:,0] > img_RGB[:,:,2]) &
        (np.abs((img_RGB[:,:,0] - img_RGB[:,:,1])) > 15)] = 1
        
        img_RGB = img.copy()
        img_YCbCr = color.rgb2ycbcr(img)

        new_mask[(img_RGB[:,:,0] > 95) &
        (img_RGB[:,:,1] > 40) &
        (img_RGB[:,:,2] > 20) &
        (img_RGB[:,:,0] > img_RGB[:,:,1]) &
        (img_RGB[:,:,0] > img_RGB[:,:,2]) &
        (img_YCbCr[:,:,1] > 85) &
        (img_YCbCr[:,:,0] > 80) &
        (img_YCbCr[:,:,2] <= ((1.5862 * img_YCbCr[:,:,1]) + 20)) &
        (img_YCbCr[:,:,2] >= ((0.3448 * img_YCbCr[:,:,1]) + 76.2069)) &
        (img_YCbCr[:,:,2] >= ((-4.5652 * img_YCbCr[:,:,1]) + 234.5652)) &
        (img_YCbCr[:,:,2] <= ((-1.15 * img_YCbCr[:,:,1]) + 301.75)) &
        (img_YCbCr[:,:,2] <= ((-2.2857 * img_YCbCr[:,:,1]) + 432.85))] = 1
        """
        """
        img_RGB = img.copy()
        img_LAB = color.rgb2lab(img)
        new_mask[
        #(img_RGB[:,:,0] > 95) &
        #(img_LAB[:,:,0] >= 70) &
        #(img_LAB[:,:,0] <= 90) &
        (img_LAB[:,:,1] >= 9.5) &
        (img_LAB[:,:,1] <= 25) &
        (np.abs((img_LAB[:,:,1] - img_LAB[:,:,2])) < 10)
        #(img_LAB[:,:,2] >= 25)
        
        ] = 1
       
        """
        img_RGB = img.copy()
        img_LAB = color.rgb2lab(img)
        img_YCbCr = color.rgb2ycbcr(img)
        img_HSV = color.rgb2hsv(img)

        new_mask[
            # YCbCr
            (img_YCbCr[:, :, 1] >= 77) & (img_YCbCr[:, :, 1] <= 127) &
            (img_YCbCr[:, :, 2] >= 133) & (img_YCbCr[:, :, 2] <= 173) &

            # RGB
            (img_RGB[:, :, 0] > 70) & (img_RGB[:, :, 1] > 40) &
            (img_RGB[:, :, 2] > 20) & (img_RGB[:, :, 0] > img_RGB[:, :, 1]) &
            (img_RGB[:, :, 0] > img_RGB[:, :, 2]) &
            #(np.abs((img_RGB[:,:,0] - img_RGB[:,:,1])) <= 15) &

            # HSV
            (img_HSV[:, :, 0] > 0.0275) &  ##
            (img_HSV[:, :, 0] < 20) & (img_HSV[:, :, 1] > 0.20) &
            (img_HSV[:, :, 1] < 70) &  ##
            (img_HSV[:, :, 2] >= 0) &  ##

            # LAB
            (img_LAB[:, :, 1] < 60) & (img_LAB[:, :, 1] > 0) &
            (img_LAB[:, :, 2] > 0.99) &

            # PERSONAL
            ((img_LAB[:, :, 1] -
              (0.009 * img_LAB[:, :, 2]**2)) >= 0) & (np.abs(
                  (img_LAB[:, :, 1] - img_LAB[:, :, 2])) < 12)] = 1

        if self.dilate:
            structuring_elem = selem.disk(self.dilation_size)
            new_mask_dilated = dilation(color.rgb2gray(new_mask),
                                        structuring_elem)
            if plot:
                fig, ax = plt.subplots(1, 3, figsize=(10, 5))
                ax[0].imshow(img)
                ax[1].imshow(new_mask)
                ax[2].imshow(new_mask_dilated, cmap=plt.get_cmap('gray'))
                plt.show()

            return color.rgb2gray(new_mask_dilated)

        if plot:
            fig, ax = plt.subplots(1, 2, figsize=(10, 5))
            ax[0].imshow(img)
            ax[1].imshow(new_mask)
            plt.show()

        return color.rgb2gray(new_mask)
Ejemplo n.º 22
0
from skimage.feature import local_binary_pattern, greycomatrix, greycoprops
from scipy.spatial import distance
from sklearn.cluster import KMeans, MiniBatchKMeans
from sklearn import metrics

origin_dir = "./img/"
dest_dir = "./results/"

for file in list(os.scandir(origin_dir))[2:3]:
    input_img = img_as_float(imread(file.path))

    #ESPAÇOS DE CORES E MEDIANA
    img = equalize_hist(input_img)[:, :, 0]  # enhance Contrast
    img2 = equalize_hist(input_img)[:, :, 1]  # enhance Contrast
    img_hsvS = rgb2hsv(input_img)[:, :, 1]
    img_median = median(img, selem=disk(7))

    # SUPERPIXEL
    imgTeste = img_as_ubyte(input_img)
    segments_slic = slic(imgTeste, n_segments=4000, compactness=10, sigma=1)
    sp = mark_boundaries(imgTeste, segments_slic)
    figure("super")
    imshow(sp)

    # image_label_overlay = label2rgb(segments_slic, image=input_img)
    # figure("uper")
    # imshow(image_label_overlay)

    region = regionprops(segments_slic, intensity_image=None, cache=True)

    lista = []
Ejemplo n.º 23
0
def features_protrusion(rna_coord, cell_mask, nuc_mask, ndim, voxel_size_yx,
                        check_input=True):
    """Compute protrusion related features.

    Parameters
    ----------
    rna_coord : np.ndarray, np.int64
        Coordinates of the detected RNAs with zyx or yx coordinates in the
        first 3 or 2 columns.
    cell_mask : np.ndarray, bool
        Surface of the cell with shape (y, x).
    nuc_mask : np.ndarray, bool
        Surface of the nucleus with shape (y, x).
    ndim : int
        Number of spatial dimensions to consider.
    voxel_size_yx : int or float
        Size of a voxel on the yx plan, in nanometer.
    check_input : bool
        Check input validity.

    Returns
    -------
    index_rna_protrusion : float
        Number of RNAs detected in a protrusion and normalized by the expected
        number of RNAs under random distribution.
    proportion_rna_protrusion : float
        Proportion of RNAs detected in a protrusion.
    protrusion_area : float
        Protrusion area (in pixels).

    """
    # TODO fin a better feature for the protrusion (idea: dilate region from
    #  centroid and stop when a majority of new pixels do not belong to the
    #  cell).

    # check parameters
    stack.check_parameter(check_input=bool)
    if check_input:
        stack.check_parameter(ndim=int,
                              voxel_size_yx=(int, float))
        if ndim not in [2, 3]:
            raise ValueError("'ndim' should be 2 or 3, not {0}.".format(ndim))
        stack.check_array(rna_coord, ndim=2, dtype=np.int64)
        stack.check_array(cell_mask, ndim=2, dtype=bool)
        stack.check_array(nuc_mask, ndim=2, dtype=bool)

    # get number of rna and cell area
    nb_rna = len(rna_coord)
    cell_area = cell_mask.sum()

    # apply opening operator (3000 nanometers) and count the loss of RNAs
    size = int(3000 / voxel_size_yx)
    s = disk(size, dtype=bool)
    mask_cell_opened = binary_opening(cell_mask, selem=s)
    mask_cell_opened[nuc_mask] = True
    protrusion_area = cell_area - mask_cell_opened.sum()

    # case where we do not detect any
    if nb_rna == 0:
        features = (1., 0., protrusion_area)
        return features

    if protrusion_area > 0:
        expected_rna_protrusion = nb_rna * protrusion_area / cell_area
        mask_rna = mask_cell_opened[rna_coord[:, ndim - 2],
                                    rna_coord[:, ndim - 1]]
        rna_after_opening = rna_coord[mask_rna]
        nb_rna_protrusion = nb_rna - len(rna_after_opening)
        index_rna_protrusion = nb_rna_protrusion / expected_rna_protrusion
        proportion_rna_protrusion = nb_rna_protrusion / nb_rna

        features = (index_rna_protrusion,
                    proportion_rna_protrusion,
                    protrusion_area)
    else:
        features = (1., 0., 0.)

    return features
Ejemplo n.º 24
0
.. [1] http://en.wikipedia.org/wiki/Otsu's_method

"""
import matplotlib.pyplot as plt

from skimage import data
from skimage.morphology.selem import disk
import skimage.filter.rank as rank
from skimage.filter import threshold_otsu


p8 = data.page()

radius = 10
selem = disk(radius)

loc_otsu = rank.otsu(p8, selem)
t_glob_otsu = threshold_otsu(p8)
glob_otsu = p8 >= t_glob_otsu


plt.figure()
plt.subplot(2, 2, 1)
plt.imshow(p8, cmap=plt.cm.gray)
plt.xlabel('original')
plt.colorbar()
plt.subplot(2, 2, 2)
plt.imshow(loc_otsu, cmap=plt.cm.gray)
plt.xlabel('local Otsu ($radius=%d$)' % radius)
plt.colorbar()
Ejemplo n.º 25
0
def nuclei_seg(img,
               threshold=None
               ):  # refine large blobs with regional thresholding
    '''
    implementation of the H&E stained histology image nuclei segmentation method described in
    [Peikari et al., 2016] and [Peikari et al., 2017]

    :param img: np.array, [MxNx3] uint8, input RGB image
    :param threshold: array-like, [2] float, pre-computed thresholds
    :return: final_mask: np.array, [MxNx3] int16, segmentation mask
    th_1, th_2: float, thresholds

    references:
    [1] Peikari, M., Salama, S., Nofech‐Mozes, S., & Martel, A. L. (2017).
    Automatic cellularity assessment from post‐treated breast surgical specimens.
    Cytometry Part A, 91(11), 1078-1087.

    [2] Peikari, M., & Martel, A. L. (2016, March). Automatic cell detection and segmentation from H and E
    stained pathology slides using colorspace decorrelation stretching. In Medical Imaging 2016: Digital Pathology
    (Vol. 9791, p. 979114). International Society for Optics and Photonics.
    '''
    im_nmzd = htk.preprocessing.color_normalization.reinhard(
        img, mean_ref, std_ref)
    img_ds = decorrstretch(im_nmzd)
    img_lab = htk.preprocessing.color_conversion.rgb_to_lab(img_ds)
    img_lab = 0.25 * img_lab[:, :, 0] + 0.5 * img_lab[:, :,
                                                      1] + 0.25 * img_lab[:, :,
                                                                          2]
    if threshold is None:
        th = eng.multithresh(matlab.double(img_lab.tolist()), 2)
        th_1 = np.sort(th)[0][0]
        th_2 = np.sort(th)[0][1]
    else:
        th_1 = threshold[0]
        th_2 = threshold[1]

    mask = (img_lab < th_1)
    mask = binary_fill_holes(mask)
    mask = binary_opening(mask, selem.disk(3))

    # correct for mis-filled holes
    mask_holes = (mask & (img_lab > th_2))
    mask_holes = (htk.segmentation.label.area_open(
        label(mask_holes, connectivity=1), 40) > 0)
    mask_holes = (binary_dilation(mask_holes, selem.disk(2)))
    mask[mask_holes] = False
    mask_conn = label(mask, connectivity=1)

    # refine large blobs
    area = np.array([[_.label, _.area] for _ in regionprops(mask_conn)])
    overlap_label = area[area[:, 1] > 300, 0]
    overlap_mask = np.isin(mask_conn, overlap_label)
    dt = distance_transform_edt(overlap_mask)
    local_maxi = peak_local_max(dt,
                                labels=mask_conn,
                                min_distance=4,
                                indices=False)
    markers = label(local_maxi)
    overlap_seg = watershed(-dt, markers, mask=overlap_mask)
    mask_conn[overlap_seg > 0] = overlap_seg[overlap_seg > 0] + mask_conn.max()
    final_mask = htk.segmentation.label.condense(mask_conn)

    # refine large blobs by regional threshold
    area = np.array([[
        _.label,
        _.area,
    ] for _ in regionprops(final_mask)])
    overlap_label = area[area[:, 1] > 300, 0]
    overlap_mask = np.isin(final_mask, overlap_label)
    final_mask[overlap_mask] = 0
    tmp_th = eng.multithresh(matlab.double([img_lab[overlap_mask].tolist()]),
                             2)
    th_3 = np.sort(tmp_th)[0][1]
    overlap_mask = overlap_mask & (img_lab < th_3)
    overlap_mask = binary_opening(overlap_mask, selem.disk(3))

    dt = distance_transform_edt(overlap_mask)
    local_maxi = peak_local_max(dt,
                                labels=overlap_mask,
                                min_distance=4,
                                indices=False)
    markers = label(local_maxi)
    overlap_seg = watershed(-dt, markers, mask=overlap_mask)
    final_mask[
        overlap_seg > 0] = overlap_seg[overlap_seg > 0] + final_mask.max()

    # remove boundary regions
    for _1 in regionprops(final_mask):
        min_row, min_col, max_row, max_col = _1.bbox
        if min_row <= 0 or min_col <= 0 or max_row >= img.shape[
                0] or max_col >= img.shape[1]:
            final_mask[final_mask == _1.label] = 0
    final_mask = htk.segmentation.label.condense(final_mask)
    final_mask = _label_fill_holes(final_mask)

    final_mask = htk.segmentation.label.area_open(final_mask,
                                                  40).astype('int16')

    return final_mask, th_1, th_2
Ejemplo n.º 26
0
def remove_segmented_nuc(image, nuc_mask, size_nuclei=2000):
    """Remove the nuclei we have already segmented in an image.

    1) We start from the segmented nuclei with a light dilation. The missed
    nuclei and the background are set to 0 and removed from the original image.
    2) We reconstruct the missing nuclei by small dilation. As we used the
    original image to set the maximum allowed value at each pixel, the
    background pixels remain unchanged. However, pixels from the missing
    nuclei are partially reconstructed by the dilation. The reconstructed
    image only differs from the original one where the nuclei have been missed.
    3) We subtract the reconstructed image from the original one.
    4) From the few missing nuclei kept and restored, we build a binary mask
    (dilation, small object removal).
    5) We apply this mask to the original image to get the original pixel
    intensity of the missing nuclei.
    6) We remove pixels with a too low intensity.

    Parameters
    ----------
    image : np.ndarray, np.uint
        Original nuclei image with shape (y, x).
    nuc_mask : np.ndarray,
        Result of the segmentation (with instance differentiation or not).
    size_nuclei : int
        Threshold above which we detect a nuclei.

    Returns
    -------
    image_without_nuc : np.ndarray
        Image with shape (y, x) and the same dtype of the original image.
        Nuclei previously detected in the mask are removed.

    """
    # check parameters
    stack.check_array(image, ndim=2, dtype=[np.uint8, np.uint16])
    stack.check_array(nuc_mask, ndim=2, dtype=bool)
    stack.check_parameter(size_nuclei=int)

    # store original dtype
    original_dtype = image.dtype

    # dilate the mask
    mask_dilated = stack.dilation_filter(image, "disk", 10)

    # remove the unsegmented nuclei from the original image
    diff = image.copy()
    diff[mask_dilated == 0] = 0

    # reconstruct the missing nuclei by dilation
    s = disk(1).astype(original_dtype)
    image_reconstructed = reconstruction(diff, image, selem=s)
    image_reconstructed = image_reconstructed.astype(original_dtype)

    # substract the reconstructed image from the original one
    image_filtered = image.copy()
    image_filtered -= image_reconstructed

    # build the binary mask for the missing nuclei
    missing_mask = image_filtered > 0
    missing_mask = clean_segmentation(missing_mask,
                                      small_object_size=size_nuclei,
                                      fill_holes=True)
    missing_mask = stack.dilation_filter(missing_mask, "disk", 20)

    # TODO improve the thresholds
    # get the original pixel intensity of the unsegmented nuclei
    unsegmented_nuclei = image.copy()
    unsegmented_nuclei[missing_mask == 0] = 0
    if original_dtype == np.uint8:
        unsegmented_nuclei[unsegmented_nuclei < 40] = 0
    else:
        unsegmented_nuclei[unsegmented_nuclei < 10000] = 0

    return unsegmented_nuclei
Ejemplo n.º 27
0
def toy_voronoi_labels_affinities(
        width_, height_, radius, opening_radius, deform_sigma, deform_points,
        intensity_prob,
        noise_sigma
    ):
    # we will create bigger images such that we can crop out regions,
    # that look good
    
    offset = 2 * radius
    height = height_ + 2 * offset
    width = width_ + 2 * offset
    
    shape = (height, width)
    labels = np.zeros(shape, dtype=np.uint16)
    sketch = np.zeros_like(labels, dtype=float)
    
    # r is the distance between two center points, so we need to multiply by 2
    centers = poisson_disc_samples(width=width, height=height, r=radius * 2)
    
    # append far points to centers to complete voronoi regions
    x_max = width + 1
    y_max = height + 1
    centers = centers + [(-1, -1), (-1, y_max), (x_max, -1), (x_max, y_max)]
    
    vor = Voronoi(centers)
    
    # create selem with provided radius to apply clsoing
    selem = disk(opening_radius)
    for i, region in enumerate(vor.regions):
        if -1 in region or len(region) == 0:
            continue
        
        polygon = [vor.vertices[i] for i in region]
        mask = polygon2mask(shape, polygon)
        
        # close polygon mask with provided selem and radius
        mask = binary_opening(mask, selem)
        
        # enumerate starts at 0, but 0 is background
        labels[mask] = i + 1
        
        edt = distance_transform_edt(mask)
        edt = edt / edt.max()
        
        tmp_intensity = np.random.uniform(*intensity_prob)
        sketch[mask] = edt[mask] * tmp_intensity
        
    sketch = scipy.ndimage.gaussian_filter(sketch, radius / 4)
        
    [labels, sketch] = elasticdeform.deform_random_grid(
        [labels, sketch], sigma=deform_sigma, points=deform_points,
        # labels must be interpolated by nearest neighbor
        order=[0, 3],
        crop=(
            slice(offset, offset + height_ + 1),
            slice(offset, offset + width_ + 1)
        )
    )
    
    # labels = labels[offset:-offset + 1, offset:-offset + 1]
    # sketch = sketch[offset:-offset + 1, offset:-offset + 1]
    
    noise = sketch + np.random.normal(0, noise_sigma, size=sketch.shape)
    
    affinities = get_affinities(labels)
    
    return labels[:-1, :-1], sketch[:-1, :-1], noise[:-1, :-1], affinities
Ejemplo n.º 28
0
        'segmentation&classification/corr/y_pred_corr_with_label.npy')

    # estimation for val
    clf_map_val = []
    malignant_map_val = []
    for i, j in zip(val_seg, y_pred_val_with_label):
        tmp_map = np.zeros(i.shape + (3, ), dtype='uint8')
        tmp_map[np.isin(i, j[j[:, 3] == 0, 2])] = [255, 0, 0]
        tmp_map[np.isin(i, j[j[:, 3] == 1, 2])] = [0, 0, 255]
        tmp_map[np.isin(i, j[j[:, 3] == 2, 2])] = [0, 255, 0]
        clf_map_val.append(tmp_map)
        malignant_map_val.append(np.isin(i, j[j[:, 3] == 0, 2]))
    clf_map_val = np.array(clf_map_val)
    malignant_map_val = np.array(malignant_map_val)
    malignant_map_val = np.array(
        [binary_dilation(j, selem.disk(11)) for j in malignant_map_val])
    cellularity_val = np.array(
        [np.sum(j) / (j.shape[0] * j.shape[1]) for j in malignant_map_val])
    if not os.path.exists('segmentation&classification/val/mapping'):
        os.mkdir('segmentation&classification/val/mapping')
    for i, j in enumerate(clf_map_val):
        skimage.io.imsave(
            'segmentation&classification/val/mapping/{:03d}.tif'.format(i), j)

    # estimation for corr
    clf_map_corr = []
    malignant_map_corr = []
    for i, j in zip(corr_seg, y_pred_corr_with_label):
        tmp_map = np.zeros(i.shape + (3, ), dtype='uint8')
        tmp_map[np.isin(i, j[j[:, 3] == 0, 2])] = [255, 0, 0]
        tmp_map[np.isin(i, j[j[:, 3] == 1, 2])] = [0, 0, 255]
Ejemplo n.º 29
0
ndvi = sentinel2_data_cube.ndvi()

scl = connection.load_collection("TERRASCOPE_S2_TOC_V2", bands=["SCL"]).filter_bbox(**bbox)
classification = scl.band("SCL")


#in openEO, 1 means mask (remove pixel) 0 means keep pixel

SCL_MASK_VALUES = [0, 1, 3, 8, 9, 10, 11]
#keep useful pixels, so set to 1 (remove) if smaller than threshold

#first erode, then dilate: removes noise, in this case small areas marked as cloud?
scl_mask = ~ ((classification == 0) | (classification == 1) | (classification == 3) | (classification == 8) | (classification == 9) | (classification == 10) | (classification == 11))
#scl_mask = ((classification == 3) | (classification == 8) | (classification == 9) )
#this is erosion: clouds (1's) get smaller
scl_mask = scl_mask.apply_kernel(selem.disk(13))
#output of 2D convolution is non-binary, make it binary again, AND invert
scl_mask = scl_mask < 0.01
#now do dilation
scl_mask = scl_mask.apply_kernel(selem.disk(13))
scl_mask = scl_mask.add_dimension(name="bands",label="scl",type="bands")

def test_mask():
    scl_mask.filter_temporal("2018-05-06","2018-05-06").download("mask.tiff",format="GTIFF")

masked = ndvi.mask(scl_mask)

#I'm using pytest methods here: PyCharm allows these methods to be started individually, which is more convenient
# otherwise my script would be doing multiple downloads on each test, or I would have to comment out these lines

#takes a few seconds to download
Ejemplo n.º 30
0
    tocc = 1.0 * (occgrid > 0.5)
    occgrid[occgrid > 0.5] = 0
    print("Map loaded")
else:
    print('Map not found')
    exit()

plt.figure(1)
plt.imshow(tocc + occgrid)
plt.show()

# Object Dilation

dilation = 4.5
zmap = np.uint8(tocc > 0.5)
disk = selem.disk(dilation)
zmapd = binary_dilation(input=zmap, structure=disk)
plt.figure(2)
plt.imshow(zmapd)
plt.show()

# Get the rute

origen = (8, 8)
num1 = random.randint(30, 90)
num2 = random.randint(30, 90)
meta = (num1, num2)

#if zmapd[meta[0]][meta[1]] != 0:
#    continue
Ejemplo n.º 31
0
def morph_grad(img):
    gr = gradient(img, disk(1))
    return gr.astype(np.float32) / 256
Ejemplo n.º 32
0
def Volume_Label():
    """
    Creates binary labels from .stl files, that are sliced at height locations
    given by the position of the slices in the corresponding volume.nii file.
    It Saves at "filenamelabel" the binary labels of the selected anatomy.
    Returns:

    """
    setDirVariables()

    ## Options
    # b_display = 0
    # compare_Matlab_Python = 0

    # Output size

    outSize = [128, 128, 128]
    templateSize = str(outSize[0]) + '_' + str(outSize[1]) + '_' + str(
        outSize[2])

    # Sets
    InStlSet = 'stl'
    InDCMmSet = 'reshape_knee_'
    InDCMmSetdicom = 'knee'

    fileTemplate = InDCMmSet + templateSize
    anatomy = 'tibia'  # 'femur', 'patella', 'fibula'
    position = 'prox'  # 'dist', '', ''
    InSurfSet = 'ct_' + anatomy + '_'
    outSet = position + anatomy

    os.chdir(mainInputDataDirectoryLoc)

    fp = open('case.txt', 'r+')
    casePatient = fp.read()
    casePatient = int(casePatient)
    fp.close()
    print('Patient no. {}'.format(casePatient))

    # Read excel file to get patients' codes
    xlsName = os.path.join(mainInputDataDirectoryLoc, 'Case_statistics.xlsx')
    # name = pandas.ExcelFile(xlsName)
    name = xlrd.open_workbook(xlsName)
    sheet = name.sheet_by_index(0)
    rows = sheet.nrows
    study = [sheet.cell_value(i, 0) for i in range(1, rows)]
    patientCode = study[casePatient - 1]

    ## Read volume nii
    mainPatientDirectory = 'Patient{:04d}'.format(casePatient)
    mainInputPatientDirectoryLoc = mainInputDataDirectoryLoc + '/preprocessedData/' + mainPatientDirectory + '/'
    mainInputPatientDirectoryNAS = mainInputDataDirectoryNAS + '/OriginalData/' + patientCode
    mainInputDicomDirectory = mainInputPatientDirectoryNAS + '/dicom/'
    if os.path.isdir(mainInputDicomDirectory + '/ct/'):
        mainInputDicomDirectory = mainInputDicomDirectory + '/ct/' + InDCMmSetdicom + '/'
    else:
        mainInputDicomDirectory = mainInputDicomDirectory + InDCMmSetdicom + '/'

    os.chdir(mainInputPatientDirectoryLoc)

    niiFilename = 'volumeCT_' + fileTemplate + '_{:04d}.nii'.format(
        casePatient)
    VolumeCT = loadNiiVolume(niiFilename, mainInputDicomDirectory)
    ## Normalize
    VolumeCT = normVolumeScan(VolumeCT)

    # Read stl and display
    mainInputStlDirectory = mainInputPatientDirectoryNAS + '/' + InStlSet + '/'
    os.chdir(mainInputStlDirectory)
    filename = InSurfSet + study[casePatient - 1] + '.stl'
    my_mesh1 = trimesh.load(filename)

    os.chdir(mainCodeDirectory)

    # Build  binary volume of the reference surface corresponding to the CT volume
    VolumeSurf = VolumeCT
    VolumeSurf.volumeData = np.zeros(VolumeSurf.volumeData.shape, dtype=int)

    heights = []
    for i in range(VolumeSurf.volumeDim[2]):
        heights.append(
            float(VolumeSurf.volumeOffset[2]) + i * VolumeSurf.voxelSize[2])

    contours = mesh2vol(my_mesh1, heights, VolumeSurf.volumeOffset,
                        VolumeSurf.voxelSize, VolumeSurf.volumeDim)
    indicesX = []
    indicesY = []

    for ip in range(VolumeSurf.volumeDim[2]):

        if contours[ip].shape[0] != 0:

            val = contours[ip][:, 0] - VolumeSurf.volumeOffset[0]
            val = val / (VolumeSurf.volumeDim[0] * VolumeSurf.voxelSize[0])
            val = np.round(val * VolumeSurf.volumeDim[0], 0)
            valX = val.astype(int)

            val = contours[ip][:, 1] - VolumeSurf.volumeOffset[1]
            val = val / (VolumeSurf.volumeDim[1] * VolumeSurf.voxelSize[1])
            val = np.round(val * VolumeSurf.volumeDim[0], 0)
            valY = val.astype(int)

            val_index = np.zeros((valX.shape[0], 2))
            val_index[:, 0] = valX
            val_index[:, 1] = valY
            val_index = np.unique(val_index, axis=0).astype(int)

            indicesX.append(val_index[:, 0])
            indicesY.append(val_index[:, 1])

            for i, j in zip(valY, valX):
                VolumeSurf.volumeData[i - 1, j - 1, ip] = 1
        else:
            indicesX.append([])
            indicesY.append([])

    VolumeSurfLabeled = VolumeSurf
    counter1 = 0
    counter2 = 0
    # fill in the image each contour
    for ip in range(VolumeSurfLabeled.volumeDim[2]):

        if contours[ip].shape[0] != 0:

            non_zero_start = np.count_nonzero(VolumeSurf.volumeData[:, :, ip])

            ######## REGION FILL
            binaryImage = binary_fill_holes(VolumeSurf.volumeData[:, :, ip])
            binaryImage = binaryImage > 1 / 255
            ######### CLOSING
            kernel = np.ones((5, 5), np.uint8)
            binaryImage = binary_closing(binaryImage, kernel)
            ######### FILL HOLES AGAIN
            binaryImage = binary_fill_holes(binaryImage)

            non_zero_end = np.count_nonzero(binaryImage)

            ######### ALTERNATIVE PROCESSING FOR NON CLOSED CONTOURS
            if non_zero_end < non_zero_start * 4:
                strel = disk(2)
                binaryImage = binary_dilation(VolumeSurf.volumeData[:, :, ip],
                                              strel)
                binaryImage = binary_dilation(binaryImage, strel)
                binaryImage = binary_fill_holes(binaryImage)
                binaryImage = binary_erosion(binaryImage, strel)
                binaryImage = binary_erosion(binaryImage, strel)
                counter1 = counter1 + 1

                non_zero_end2 = np.count_nonzero(binaryImage)

                ######### ALTERNATIVE PROCESSING FOR STILL-NON-CLOSED CONTOURS
                if non_zero_end2 < non_zero_start * 4:
                    strel = disk(3)
                    binaryImage = binary_dilation(
                        VolumeSurf.volumeData[:, :, ip], strel)
                    binaryImage = binary_dilation(binaryImage, strel)
                    binaryImage = binary_fill_holes(binaryImage)
                    binaryImage = binary_erosion(binaryImage, strel)
                    binaryImage = binary_erosion(binaryImage, strel)
                    counter2 = counter2 + 1

            VolumeSurfLabeled.volumeData[:, :, ip] = binaryImage

            dMin = VolumeSurfLabeled.volumeData.min()
            D = VolumeSurfLabeled.volumeData + abs(dMin)
            D = D / D.max() * 255

    print('Alternative processing no 1: {} \n Alternative proessing no 2: {}'.
          format(counter1, counter2))

    ###### PLOT AND SCROLL ACROSS SLICES
    #if b_display == 1:
    #    fig, ax = plt.subplots(1, 1)
    #    tracker = IndexTracker(ax, D)
    #    fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
    #    plt.show()
    #
    #if compare_Matlab_Python == 1:
    #    name_dir = outSet + 'Label'
    #    mainLabelDirectory = os.path.join(mainPatientDirectory, '{}'.format(name_dir))
    #    os.chdir(mainLabelDirectory)
    #    mean_dice = dice_coeff(VolumeSurfLabeled.volumeData, outSet)
    #    print(mean_dice)

    # Make nii file label
    volumeData = VolumeSurfLabeled.volumeData.astype(np.short)
    volumeData = np.transpose(volumeData, [1, 0, 2])
    voxelSize = VolumeSurfLabeled.voxelSize
    volumeOffset = VolumeSurfLabeled.volumeOffset

    affine = np.eye(4)
    niiVolumeLabel = nib.Nifti1Image(volumeData, affine)
    niiVolumeLabel.header.set_slope_inter(VolumeSurfLabeled.rescaleSlope,
                                          VolumeSurfLabeled.rescaleIntercept)
    niiVolumeLabel.header.set_qform(affine, 1)
    niiVolumeLabel.header.set_zooms(voxelSize)
    niiVolumeLabel.header['qoffset_x'] = volumeOffset[0]
    niiVolumeLabel.header['qoffset_y'] = volumeOffset[1]
    niiVolumeLabel.header['qoffset_z'] = volumeOffset[2]

    os.chdir(mainInputPatientDirectoryLoc)

    # Save nii
    filenameLabel = 'volumeLabel_' + outSet + '_' + templateSize + '_{:04d}_py.nii'.format(
        casePatient)
    nib.nifti1.save(niiVolumeLabel, filenameLabel)

    os.chdir(mainCodeDirectory)
Ejemplo n.º 33
0
def features_foci(rna_coord_out, distance_cyt, distance_nuc, mask_cyt_out):
    # case where no mRNAs outside the nucleus are detected
    if len(rna_coord_out) == 0:
        features = [0.] * 35 * 2
        features += [1., 0., 0.] * 4
        features += [1., 0., 1., 0., 1., 0.]
        features += [1., 0., 1., 0., 1., 0.]
        return features

    features = []
    for foci_radius in [50, 150, 250, 350, 450, 550, 650]:
        for min_foci_rna in [3, 4, 5, 6, 7]:
            clustered_spots = detection.cluster_spots(
                spots=rna_coord_out[:, :3],
                resolution_z=300,
                resolution_yx=103,
                radius=foci_radius,
                nb_min_spots=min_foci_rna)
            foci = detection.extract_foci(clustered_spots=clustered_spots)
            nb_foci = len(foci)
            nb_spots_in_foci = np.sum(foci[:, 3])
            proportion_rna_foci = nb_spots_in_foci / len(rna_coord_out)

            features += [nb_foci, proportion_rna_foci]

    # case where no default foci are detected
    rna_coord_out_foci = rna_coord_out[rna_coord_out[:, 3] != -1, :]
    if len(rna_coord_out_foci) == 0:
        features += [1., 0., 0.] * 4
        features += [1., 0., 1., 0., 1., 0.]
        features += [1., 0., 1., 0., 1., 0.]
        return features

    # get regular foci id
    l_id_foci = list(set(rna_coord_out_foci[:, 3]))

    # count mRNAs in successive 5 pixels foci neighbors
    nb_rna_out = len(rna_coord_out)
    cell_out_area = mask_cyt_out.sum()
    mask_foci_neighbor_cumulated = np.zeros_like(mask_cyt_out)
    eps = stack.get_eps_float32()

    # we count mRNAs in the neighbors 0-5 pixels around the foci, 5-10 pixels,
    # 10-15 pixels, and 15-20 pixels
    for radius in range(5, 21, 5):
        s = disk(radius).astype(bool)
        mask_foci_neighbor = np.zeros_like(mask_cyt_out)

        # for each foci, get a mask of its neighbor and merge them
        for i in l_id_foci:
            rna_foci_i = rna_coord_out_foci[rna_coord_out_foci[:, 3] == i, :3]
            foci = np.mean(rna_foci_i, axis=0)
            foci = np.round(foci).astype(np.int64)
            row, col = foci[1], foci[2]
            mask_neighbor = np.zeros_like(mask_cyt_out)
            min_row = max(row - radius, 0)
            min_row_s = min_row - (row - radius)
            max_row = min(row + radius + 1, mask_neighbor.shape[0])
            max_row_s = s.shape[0] - ((row + radius + 1) - max_row)
            min_col = max(col - radius, 0)
            min_col_s = min_col - (col - radius)
            max_col = min(col + radius + 1, mask_neighbor.shape[1])
            max_col_s = s.shape[1] - ((col + radius + 1) - max_col)
            new_s = s[min_row_s:max_row_s, min_col_s:max_col_s]
            mask_neighbor[min_row:max_row, min_col:max_col] = new_s
            mask_foci_neighbor |= mask_cyt_out & mask_neighbor

        # remove neighbor mask from previous radius
        mask_foci_neighbor[mask_foci_neighbor_cumulated] = False
        mask_foci_neighbor_cumulated |= mask_foci_neighbor

        # count mRNAs in such a region
        mask_rna = mask_foci_neighbor[rna_coord_out[:, 1], rna_coord_out[:, 2]]
        nb_rna_foci_neighbor = len(rna_coord_out[mask_rna])
        area_foci_neighbor = mask_foci_neighbor.sum()
        factor = nb_rna_out * max(area_foci_neighbor, 1) / cell_out_area
        index_rna_foci_neighbor = (nb_rna_foci_neighbor + eps) / factor
        log2_index_rna_foci_neighbor = np.log2(index_rna_foci_neighbor)
        proportion_rna_foci_neighbor = nb_rna_foci_neighbor / nb_rna_out

        features += [
            index_rna_foci_neighbor, log2_index_rna_foci_neighbor,
            proportion_rna_foci_neighbor
        ]

    # get foci coordinates
    foci_coord = []
    for i in l_id_foci:
        rna_foci_i = rna_coord_out_foci[rna_coord_out_foci[:, 3] == i, :3]
        foci = np.mean(rna_foci_i, axis=0)
        foci = np.round(foci).astype(np.int64)
        foci_coord.append(foci.reshape(1, 3))
    foci_coord = np.array(foci_coord, dtype=np.int64)
    foci_coord = np.squeeze(foci_coord, axis=1)
    foci_coord_2d = foci_coord[:, 1:3]

    # compute statistics from distance to cytoplasm
    distance_foci_cyt = distance_cyt[foci_coord_2d[:, 0], foci_coord_2d[:, 1]]
    factor = np.mean(distance_cyt[mask_cyt_out])
    index_foci_mean_distance_cyt = (np.mean(distance_foci_cyt) + eps) / factor
    log2_index_foci_mean_distance_cyt = np.log2(index_foci_mean_distance_cyt)
    factor = np.median(distance_cyt[mask_cyt_out])
    index_foci_med_distance_cyt = (np.median(distance_foci_cyt) + eps) / factor
    log2_index_foci_med_distance_cyt = np.log2(index_foci_med_distance_cyt)
    factor = np.std(distance_cyt[mask_cyt_out])
    index_foci_std_distance_cyt = (np.std(distance_foci_cyt) + eps) / factor
    log2_index_foci_std_distance_cyt = np.log2(index_foci_std_distance_cyt)

    features += [
        index_foci_mean_distance_cyt, log2_index_foci_mean_distance_cyt,
        index_foci_med_distance_cyt, log2_index_foci_med_distance_cyt,
        index_foci_std_distance_cyt, log2_index_foci_std_distance_cyt
    ]

    # compute statistics from distance to nucleus
    distance_foci_nuc = distance_nuc[foci_coord_2d[:, 0], foci_coord_2d[:, 1]]
    factor = np.mean(distance_nuc[mask_cyt_out])
    index_foci_mean_distance_nuc = (np.mean(distance_foci_nuc) + eps) / factor
    log2_index_foci_mean_distance_nuc = np.log2(index_foci_mean_distance_nuc)
    factor = np.median(distance_nuc[mask_cyt_out])
    index_foci_med_distance_nuc = (np.median(distance_foci_nuc) + eps) / factor
    log2_index_foci_med_distance_nuc = np.log2(index_foci_med_distance_nuc)
    factor = np.std(distance_nuc[mask_cyt_out])
    index_foci_std_distance_nuc = (np.std(distance_foci_nuc) + eps) / factor
    log2_index_foci_std_distance_nuc = np.log2(index_foci_std_distance_nuc)

    features += [
        index_foci_mean_distance_nuc, log2_index_foci_mean_distance_nuc,
        index_foci_med_distance_nuc, log2_index_foci_med_distance_nuc,
        index_foci_std_distance_nuc, log2_index_foci_std_distance_nuc
    ]

    return features
Ejemplo n.º 34
0
def Volume_Label():
    setDirVariables()

    ## Options
    b_display = 0
    cubic = 0
    compare_Matlab_Python = 0

    # Output size
    if cubic == 1:
        outSize = [200, 200, 131]
    else:
        outSize = [128, 128, 128]
    templateSize = str(outSize[0]) + '_' + str(outSize[1]) + '_' + str(
        outSize[2])

    # Sets
    if cubic == 0:
        InDCMmSet = 'reshape_knee_'
    else:
        InDCMmSet = 'cubic_vox_knee_'
    InDCMmSetdicom = 'knee'

    fileTemplate = InDCMmSet + templateSize
    anatomy = 'tibia'  # 'tibia'
    position = 'prox'  # 'prox'
    InSurfSet = 'ct_' + anatomy + '_'
    outSet = position + anatomy

    os.chdir(mainInputDataDirectory)

    fp = open('case.txt', 'r+')
    casePatient = fp.read()
    casePatient = int(casePatient)
    casePatient = 3
    fp.close()
    print('Patient no. {}'.format(casePatient))

    xlsName = os.path.join(mainInputDataDirectory, 'Preop Data.xlsx')
    name = pandas.ExcelFile(xlsName)
    name = xlrd.open_workbook(xlsName)
    sheet = name.sheet_by_index(0)
    rows = sheet.nrows
    study = [sheet.cell_value(i, 0) for i in range(1, rows)]

    os.chdir(mainCodeDirectory)

    ## Read volume nii
    mainPatientDirectory = 'Patient{:03d}'.format(casePatient)
    mainPatientDirectory = mainInputDataDirectory + '/' + mainPatientDirectory + '/'
    mainInputDicomDirectory = mainPatientDirectory + '/' + InDCMmSetdicom + '/'

    os.chdir(mainPatientDirectory)

    niiFilename = 'volumeCT_' + fileTemplate + '_{:03d}.nii'.format(
        casePatient)
    VolumeCT = loadNiiVolume(niiFilename, mainInputDicomDirectory)
    ## Normalize
    VolumeCT = normVolumeScan(VolumeCT)

    # Read stl and display
    filename = InSurfSet + study[casePatient - 1] + '.stl'
    os.chdir(mainPatientDirectory)
    my_mesh1 = trimesh.load(filename)
    my_mesh = mesh.Mesh.from_file(filename)

    os.chdir(mainCodeDirectory)

    # Build  binary volume of the reference surface corresponding to the CT volume
    VolumeSurf = VolumeCT
    VolumeSurf.volumeData = np.zeros(VolumeSurf.volumeData.shape, dtype=int)

    heights = []
    for i in range(VolumeSurf.volumeDim[2]):
        heights.append(
            float(VolumeSurf.volumeOffset[2]) + i * VolumeSurf.voxelSize[2])

    contours = mesh2vol(my_mesh1, heights, VolumeSurf.volumeOffset,
                        VolumeSurf.voxelSize, VolumeSurf.volumeDim)
    indicesX = []
    indicesY = []

    for ip in range(VolumeSurf.volumeDim[2]):

        if contours[ip].shape[0] != 0:

            val = contours[ip][:, 0] - VolumeSurf.volumeOffset[0]
            val = val / (VolumeSurf.volumeDim[0] * VolumeSurf.voxelSize[0])
            val = np.round(val * VolumeSurf.volumeDim[0], 0)
            valX = val.astype(int)

            val = contours[ip][:, 1] - VolumeSurf.volumeOffset[1]
            val = val / (VolumeSurf.volumeDim[1] * VolumeSurf.voxelSize[1])
            val = np.round(val * VolumeSurf.volumeDim[0], 0)
            valY = val.astype(int)

            val_index = np.zeros((valX.shape[0], 2))
            val_index[:, 0] = valX
            val_index[:, 1] = valY
            val_index = np.unique(val_index, axis=0).astype(int)

            indicesX.append(val_index[:, 0])
            indicesY.append(val_index[:, 1])

            for i, j in zip(valY, valX):
                VolumeSurf.volumeData[i - 1, j - 1, ip] = 1
        else:
            indicesX.append([])
            indicesY.append([])

    VolumeSurfLabeled = VolumeSurf
    counter = 0
    # fill in the image each contour
    for ip in range(VolumeSurfLabeled.volumeDim[2]):

        if contours[ip].shape[0] != 0:

            non_zero_start = np.count_nonzero(VolumeSurf.volumeData[:, :, ip])

            ######## REGION FILL
            binaryImage = binary_fill_holes(VolumeSurf.volumeData[:, :, ip])
            binaryImage = binaryImage > 1 / 255
            ######### CLOSING
            kernel = np.ones((5, 5), np.uint8)
            binaryImage = binary_closing(binaryImage, kernel)
            ######### FILL HOLES AGAIN
            binaryImage = binary_fill_holes(binaryImage)

            non_zero_end = np.count_nonzero(binaryImage)

            ######### ALTERNATIVE PROCESSING FOR NON CLOSED CONTOURS
            if non_zero_end < non_zero_start * 4:
                strel = disk(2)
                binaryImage = binary_dilation(VolumeSurf.volumeData[:, :, ip],
                                              strel)
                binaryImage = binary_dilation(binaryImage, strel)
                binaryImage = binary_fill_holes(binaryImage)
                binaryImage = binary_erosion(binaryImage, strel)
                binaryImage = binary_erosion(binaryImage, strel)
                counter = counter + 1

            VolumeSurfLabeled.volumeData[:, :, ip] = binaryImage

            dMin = VolumeSurfLabeled.volumeData.min()
            D = VolumeSurfLabeled.volumeData + abs(dMin)
            D = D / D.max() * 255

    print(counter)

    ###### PLOT AND SCROLL ACROSS SLICES
    if b_display == 1:
        fig, ax = plt.subplots(1, 1)
        tracker = IndexTracker(ax, D)
        fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
        plt.show()

    if compare_Matlab_Python == 1:
        name_dir = outSet + 'Label'
        mainLabelDirectory = os.path.join(mainPatientDirectory,
                                          '{}'.format(name_dir))
        os.chdir(mainLabelDirectory)
        mean_dice = dice_coeff(VolumeSurfLabeled.volumeData, outSet)
        print(mean_dice)

    # Make nii file label
    volumeData = VolumeSurfLabeled.volumeData.astype(np.short)
    volumeData = np.transpose(volumeData, [1, 0, 2])
    voxelSize = VolumeSurfLabeled.voxelSize
    volumeOffset = VolumeSurfLabeled.volumeOffset

    affine = np.eye(4)
    niiVolumeLabel = nib.Nifti1Image(volumeData, affine)
    niiVolumeLabel.header.set_slope_inter(VolumeSurfLabeled.rescaleSlope,
                                          VolumeSurfLabeled.rescaleIntercept)
    niiVolumeLabel.header.set_qform(affine, 1)
    niiVolumeLabel.header.set_zooms(voxelSize)
    niiVolumeLabel.header['qoffset_x'] = volumeOffset[0]
    niiVolumeLabel.header['qoffset_y'] = volumeOffset[1]
    niiVolumeLabel.header['qoffset_z'] = volumeOffset[2]

    os.chdir(mainPatientDirectory)

    # Save nii
    filenameLabel = 'volumeLabel_' + outSet + '_' + templateSize + '_{:03d}.nii'.format(
        casePatient)
    #nib.nifti1.save(niiVolumeLabel, filenameLabel)

    os.chdir(mainCodeDirectory)
Ejemplo n.º 35
0
def create_buffer_mask(og_mask, foreground_threshold=0, buffer_additional=0):
    '''
    Function to add an equal-area buffer to regions in a binary image. Foreground threshold is used if input binary image had been resampled with bicubic or quadratic and thus has multiple greyscale levels. 127 would be a reasonable number for foreground_threshold in this case.
    Inputs:
        OG_mask                 binary mask with background = 0
        foreground_threshold    maximum value to treat as background (rest become foreground)
        buffer_additional       additional pixels to buffer (+/-) to modify equal-area default
    '''

    og_mask[og_mask > foreground_threshold] = 1
    labeled = measure.label(og_mask, background=0, connectivity=2)
    if np.all(og_mask == 1):
        mask = np.full(labeled.shape, True)
    elif np.all(og_mask == 0):
        mask = np.full(labeled.shape, False)
    else:
        regions = measure.regionprops(labeled)
        mask = np.full(labeled.shape, False)
        copy = np.full(labeled.shape, False)
        for x, region in enumerate(regions):
            old_radius = region.equivalent_diameter / 2
            old_area = np.pi * old_radius**2
            new_area = 2 * old_area
            new_radius = np.sqrt(new_area / np.pi)

            buffer = new_radius - old_radius + buffer_additional

            coords = region.coords
            i = coords[:, 0]
            j = coords[:, 1]

            copy[i, j] = True

            dist = int(np.ceil(buffer))

            bbox_coords = region.bbox  #(min_row, min_col, max_row, max_col)
            if bbox_coords[0] - dist >= 0:
                bbox_i_min = bbox_coords[0] - dist
            else:
                bbox_i_min = 0
            if bbox_coords[1] - dist >= 0:
                bbox_j_min = bbox_coords[1] - dist
            else:
                bbox_j_min = 0
            if bbox_coords[2] + dist <= copy.shape[0]:
                bbox_i_max = bbox_coords[2] + dist
            else:
                bbox_i_max = copy.shape[0]
            if bbox_coords[3] + dist <= copy.shape[1]:
                bbox_j_max = bbox_coords[3] + dist
            else:
                bbox_j_max = copy.shape[1]

            #for i in range(0, int(np.ceil(buffer))):
            copy_x = copy[bbox_i_min:bbox_i_max, bbox_j_min:bbox_j_max]
            if dist > dilation_radius_step_sz * 2:
                dist_tmp = dilation_radius_step_sz
                dist_remain = dist  # init
                while (dist_tmp > 0) & (dist_remain > 0):
                    strelem = selem.disk(dist_tmp)
                    copy_x = binary_dilation(copy_x, selem=strelem)
                    dist_remain = dist_remain - dist_tmp  # after this iter
                    dist_tmp = np.min(
                        [dist_remain - dist_tmp,
                         dilation_radius_step_sz])  # for next iter

            else:
                # strelem = np.ones((dist*2+1,dist*2+1)) # box
                strelem = selem.disk(dist)  # disk
                copy_x = binary_dilation(copy_x, selem=strelem)
            copy[bbox_i_min:bbox_i_max, bbox_j_min:bbox_j_max] = copy_x
            #bounds = find_boundaries(pekel_copy)
            #pekel_copy[bounds] = 1

            mask = mask | copy

    mask[mask > 0] = 1

    return mask
Ejemplo n.º 36
0
.. note: local threshold is much slower than global one.

.. [1] http://en.wikipedia.org/wiki/Otsu's_method

"""
import matplotlib.pyplot as plt

from skimage import data
from skimage.morphology.selem import disk
import skimage.filter.rank as rank
from skimage.filter import threshold_otsu

p8 = data.page()

radius = 10
selem = disk(radius)

loc_otsu = rank.otsu(p8, selem)
t_glob_otsu = threshold_otsu(p8)
glob_otsu = p8 >= t_glob_otsu

plt.figure()
plt.subplot(2, 2, 1)
plt.imshow(p8, cmap=plt.cm.gray)
plt.xlabel('original')
plt.colorbar()
plt.subplot(2, 2, 2)
plt.imshow(loc_otsu, cmap=plt.cm.gray)
plt.xlabel('local Otsu ($radius=%d$)' % radius)
plt.colorbar()
plt.subplot(2, 2, 3)