def reconstruct_clear(binary_img, size=None, show_result=False):
    if size is None:
        eroded_img = ndimage.binary_erosion(binary_img)
        reconstruct_img = ndimage.binary_propagation(eroded_img,
                                                     mask=binary_img)
        tmp = np.logical_not(reconstruct_img)
        eroded_tmp = ndimage.binary_erosion(tmp)
        reconstruct_final = np.logical_not(
            ndimage.binary_propagation(eroded_tmp, mask=tmp))
    else:
        eroded_img = ndimage.binary_erosion(binary_img,
                                            structure=np.ones((size, size)))
        reconstruct_img = ndimage.binary_propagation(eroded_img,
                                                     structure=np.ones(
                                                         (size, size)),
                                                     mask=binary_img)
        tmp = np.logical_not(reconstruct_img)
        eroded_tmp = ndimage.binary_erosion(tmp,
                                            structure=np.ones((size, size)))
        reconstruct_final = np.logical_not(
            ndimage.binary_propagation(eroded_tmp,
                                       structure=np.ones((size, size)),
                                       mask=tmp))
    if show_result:
        show_images_and_hists([binary_img, reconstruct_final],
                              titles=['Input', 'Clear'],
                              colorbar=True)
    return reconstruct_final
Example #2
0
def removeNoise(binary_img, iterations=2):
    """Remove noise in binary image."""
    eroded_img = ndimage.binary_erosion(binary_img, iterations=iterations)
    reconstruct_img = ndimage.binary_propagation(eroded_img, mask=binary_img)
    tmp = np.logical_not(reconstruct_img)
    eroded_tmp = ndimage.binary_erosion(tmp, iterations=iterations)
    reconstruct_final = np.logical_not(ndimage.binary_propagation(eroded_tmp, mask=tmp))
    return np.where(np.isnan(binary_img), np.nan, reconstruct_final )
def get_denoise_segments(im, **kwargs):

    erode_im = scind.binary_erosion(im, **kwargs)
    reconstruct_im = scind.binary_propagation(erode_im, mask=im)
    tmp = np.logical_not(reconstruct_im)
    erode_tmp = scind.binary_erosion(tmp, **kwargs)
    reconstruct_final = np.logical_not(
        scind.binary_propagation(erode_tmp, mask=tmp))

    return reconstruct_final
def _preprocess(labels):

    label_values, inv_idx = np.unique(labels, return_inverse=True)

    if not (label_values == 0).any():
        warn(
            'Random walker only segments unlabeled areas, where '
            'labels == 0. No zero valued areas in labels were '
            'found. Returning provided labels.',
            stacklevel=2)

        return labels, None, None, None, None

    # If some labeled pixels are isolated inside pruned zones, prune them
    # as well and keep the labels for the final output

    null_mask = labels == 0
    pos_mask = labels > 0
    mask = labels >= 0

    fill = ndi.binary_propagation(null_mask, mask=mask)
    isolated = np.logical_and(pos_mask, np.logical_not(fill))

    pos_mask[isolated] = False

    # If the array has pruned zones, be sure that no isolated pixels
    # exist between pruned zones (they could not be determined)
    if label_values[0] < 0 or np.any(isolated):
        isolated = np.logical_and(
            np.logical_not(ndi.binary_propagation(pos_mask, mask=mask)),
            null_mask)

        labels[isolated] = -1
        if np.all(isolated[null_mask]):
            warn(
                'All unlabeled pixels are isolated, they could not be '
                'determined by the random walker algorithm.',
                stacklevel=2)
            return labels, None, None, None, None

        mask[isolated] = False
        mask = np.atleast_3d(mask)
    else:
        mask = None

    # Reorder label values to have consecutive integers (no gaps)
    zero_idx = np.searchsorted(label_values, 0)
    labels = np.atleast_3d(inv_idx.reshape(labels.shape) - zero_idx)

    nlabels = label_values[zero_idx + 1:].shape[0]

    inds_isolated_seeds = np.nonzero(isolated)
    isolated_values = labels[inds_isolated_seeds]

    return labels, nlabels, mask, inds_isolated_seeds, isolated_values
Example #5
0
def fill_small_radius_holes(mask, max_radius):
    """Fill holes in the mask that are up to max_radius (in terms of the number
    of dilation iterations required to fill them).

    Returns a new mask with the small holes filled."""
    outside = ndimage.binary_propagation(numpy.zeros_like(mask),
                                         mask=~mask,
                                         border_value=1)
    holes = ~(mask | outside)
    large_hole_centers = ndimage.binary_erosion(holes,
                                                iterations=max_radius + 1)
    large_holes = ndimage.binary_propagation(large_hole_centers, mask=holes)
    small_holes = holes ^ large_holes
    return mask | small_holes
Example #6
0
def create_mask(fn_appa, fn_appa_mask, thr=200):
    from scipy import ndimage

    iteration_erosion = 1
    iteration_dilation = 2

    img = nib.load(fn_appa)
    dat = img.get_data()
    if len(dat.shape) == 3:
        shape = dat.shape + (1, )
    else:
        shape = dat.shape
    mask = np.zeros(shape, dtype=np.int8)
    mask[dat > thr] = 1
    mask_clean = np.zeros(shape, dtype=np.int8)

    for i in range(shape[3]):
        mask_i = mask[:, :, :, i]

        if iteration_dilation > 0:
            inverse_i = np.logical_not(mask_i)
            inverse_clean_i = ndimage.binary_erosion(inverse_i)
            for j in range(iteration_dilation - 1):
                inverse_clean_i = ndimage.binary_erosion(inverse_clean_i)
            for j in range(iteration_dilation):
                inverse_clean_i = ndimage.binary_propagation(inverse_clean_i,
                                                             mask=inverse_i)
            mask_clean_i = np.logical_not(inverse_clean_i)
        else:
            mask_clean_i = mask_i.copy()

        if iteration_erosion > 0:
            for j in range(iteration_erosion):
                mask_clean_i = ndimage.binary_erosion(mask_clean_i)
            for j in range(iteration_erosion):
                mask_clean_i = ndimage.binary_propagation(mask_clean_i,
                                                          mask=mask_i)

        mask_clean[:, :, :, i] = mask_clean_i
    del mask_i, mask
    hdr = img.get_header()
    hdr.set_data_dtype(np.int8)

    if len(dat.shape) == 3:
        mask_clean = mask_clean[:, :, :, 0]
    img_mask = nib.Nifti1Image(mask_clean, img.get_affine(), hdr)
    nib.save(img_mask, fn_appa_mask)
    del mask_clean, img_mask, dat, img
Example #7
0
    def findMirror(self, frame):
        '''
        Tries to find the borders of the black center circle

        :param frame: (h, w) array (int16 grayscale matrix)
        :returns: Rect object of mirror bounds in frame
        '''
        # pick center luminance
        iRow = int(frame.shape[0]/2) # y
        iCol = int(frame.shape[1]/2) # x
        pad = self.mirrorPickSize//2 # half with/height
        pickArea = frame[iRow-pad:iRow+pad, iCol-pad:iCol+pad]

        # mask luminance in frame for picked value
        matchMask = np.logical_and(
            frame > pickArea.min()-self.mirrorTolerance, 
            frame < pickArea.max()+self.mirrorTolerance)

        # prepare flooding
        toFlood = np.full(frame.shape, False)
        toFlood[iRow, iCol] = True
        # get center isle
        mirrorMask = ndimage.binary_propagation(toFlood, mask=matchMask)

        # get dimensions of isle
        iMask = np.argwhere(mirrorMask)
        xMin, xMax = np.min(iMask[:, 1]), np.max(iMask[:, 1])
        yMin, yMax = np.min(iMask[:, 0]), np.max(iMask[:, 0])
        
        return Rect(xMin, xMax, yMin, yMax)
def reduce_noise(mask):
    '''
    Function to reduce noise using morphological operations.
    INPUT:
        mask - (numpy) mask noise reduction to be applied to
    RETURNS:
        reconstruct_final - (numpy) mask with reduced noise
    '''
    eroded_mask = ndi.binary_erosion(mask)
    reconstruct_mask = ndi.binary_propagation(eroded_mask, mask=mask)
    tmp = np.logical_not(reconstruct_mask)
    eroded_tmp = ndi.binary_erosion(tmp)
    reconstruct_final = np.logical_not(
        ndi.binary_propagation(eroded_tmp, mask=tmp))

    return reconstruct_final
Example #9
0
def remove_small_radius_objects(mask, max_radius):
    """Remove objects from the mask up to max_radius (in terms of number of erosion
    iterations required to remove the object.)

    Returns a new mask with the small objects removed."""
    eroded = ndimage.binary_erosion(mask, iterations=max_radius)
    return ndimage.binary_propagation(eroded, mask=mask)
Example #10
0
	def test_binary_propagation_operation_sparse_input_struct_zeros(self):
		struct = np.zeros((3,3,3))
		print("\n test_binary_propagation_operation_sparse_input_struct_zeros...")		
		v_output = vc.binary_propagation(input_svar, structure=struct,make_float32=False)		
		d_output = ndimage.binary_propagation(input_svar, structure=struct)			
		msgs = "test_binary_propagation_operation_sparse_input_struct_zeros"
		self.assertTrue((d_output==v_output).all(), msg=msgs)
Example #11
0
	def output_mask(self, y, x, image, tolerance=0.1):
		output = np.zeros_like(image)
		input_mask = np.zeros_like(image)
		input_mask[y,x] = 1
		tolerance *= np.max(image)
		greater = np.greater_equal(image, image[y,x] - tolerance)
		less = np.less_equal(image, image[y,x] + tolerance)
		return binary_propagation(input = input_mask, mask = greater*less)
Example #12
0
def removeNoise_oneSide(binary_img):
    """Remove noise in binary image. Only pixels that are 0 are removed. Pixels of value 1 are all preserved. (used for cloud masks) """
    #eroded_img = ndimage.binary_erosion(binary_img, iterations=3)
    #reconstruct_img = ndimage.binary_propagation(eroded_img, mask=binary_img)
    tmp = np.logical_not(binary_img)
    eroded_tmp = ndimage.binary_erosion(tmp, iterations=5)
    reconstruct_final = np.logical_not(ndimage.binary_propagation(eroded_tmp, mask=tmp))
    return np.where(np.isnan(binary_img), np.nan, reconstruct_final )
Example #13
0
def remove_edge_objects(mask):
    """Remove objects from the mask that are in contact with the edge.

    Returns a new mask with the edge objects removed."""
    edge_objects = ndimage.binary_propagation(numpy.zeros_like(mask),
                                              mask=mask,
                                              border_value=1)
    return mask & ~edge_objects
Example #14
0
def bs():
    uid = request.form.get('uid', str(int(time.time())))
    img_id = request.form.get('id')
    img_loc = 'static/flickr/%s.jpg' % (img_id)
    img = Image.open(img_loc)
    bg = img

    cap = Image.open('static/bg/%s.jpg' % uid)
    cap2 = Image.open('static/both/%s.jpg' % uid)

    bgs = bg.size
    ins = cap2.size
    rh = ins[0] * 1.0 / (bgs[0] * 0.6)
    rw = ins[1] * 1.0 / (bgs[1] * 0.6)
    size = int(round(ins[0] / rh)), int(round(ins[1] / rw))


    diff = difference(cap, cap2)
    diff = diff.filter(ImageFilter.MedianFilter(5))

    rgb2L = (
        1, 1, 1, 1)
    diff = diff.convert("L", rgb2L)

    diff = numpy.array(diff)


    diff = diff > 100
    diff = diff.astype(numpy.int)
    diff = ndimage.binary_fill_holes(diff).astype(int)

    eroded_square = ndimage.binary_erosion(diff, structure=numpy.ones((20,20)))
    diff = ndimage.binary_propagation(eroded_square, mask=diff)

    # eroded_square = ndimage.binary_erosion(diff, structure=numpy.ones((20,20)))
    # diff = ndimage.binary_propagation(eroded_square, mask=diff)

    diff = diff * 255

    diff = Image.fromarray(diff)
    diff = diff.convert('1')

    box = diff.getbbox()
    diff = diff.crop(box)
    cap2 = cap2.crop(box)


    cap2.thumbnail(size, Image.ANTIALIAS)
    diff.thumbnail(size, Image.ANTIALIAS)

    psize = cap2.size

    bg.paste(cap2, ((bgs[0] / 2) - (psize[0] / 2),
            int(bgs[1]) - (psize[1])), diff)

    bs_img = '%s.jpg' % uid
    bg.save(os.path.join('static', 'composite', bs_img))
    return jsonify(url='static/composite/%s.jpg' % uid)
Example #15
0
def find_drop_trails(i_frame, file_name, curr_plate_BGR, curr_plate_BW,
                     prev_plate_BGR, prev_plate_BW, prev_peak_profile,
                     prev_peak_histogram, prev_peak_landscape,
                     prev_drop_trail_masks, video_dir, pixel_to_mm_ratio_x):
    # Calculate column profiles on the plate
    curr_local_max, curr_peaks, curr_peak_profile = find_peaks(curr_plate_BW)

    diff_peak_profile = ndimage.median_filter(np.maximum(
        0, prev_peak_profile - curr_peak_profile),
                                              size=(1, 17))
    max_peak_diff_idx = [
        np.where(
            diff_peak_profile[i_p, :] == max(diff_peak_profile[i_p, :]))[0]
        for i_p in range(4)
    ]
    curr_peak_histogram = Counter(curr_peaks[curr_peaks > 0].flatten())
    min_diff_peak_profile = 50
    if all([diff_peak_profile[i_p, max_peak_diff_idx[i_p][0]] < 175 for i_p in range(4)]) or \
            (img_is_flat(curr_peak_histogram) and img_is_flat(prev_peak_histogram)):
        # We should not detect anything in images that when the maximum cummulative peak difference per column is low
        # or when both current and previous images are flat (so before drops start accumulating)
        curr_drop_footprints = np.zeros((1, curr_peak_profile.shape[1]))
    else:
        # prev_peak_median = np.median(prev_peak_profile)
        # curr_drop_footprints = np.logical_and(diff_peak_profile > prev_peak_profile / 3,
        #                              prev_peak_profile > prev_peak_median / 3).astype(np.int32)
        curr_drop_footprints = np.max(np.logical_and(
            diff_peak_profile >= 0.75 * prev_peak_profile,
            diff_peak_profile >= min_diff_peak_profile),
                                      axis=0)
        # Get rid of thin spikes
        curr_drop_footprints = widen_drop_trail_footprints(
            ndimage.median_filter(curr_drop_footprints, size=3),
            curr_peak_profile, diff_peak_profile, min_diff_peak_profile)
    # Create a mask of forbidden areas
    curr_relaxed_drop_footprints = ndimage.binary_propagation(
        curr_drop_footprints.reshape(1, -1),
        mask=(diff_peak_profile[0, :] < min_diff_peak_profile / 2).reshape(
            1, -1))
    forbidden_mask = np.ones_like(curr_plate_BW)
    forbidden_mask[:, np.where(curr_relaxed_drop_footprints > 0)] = 0
    # Interpolate trail landscape based on the detected peaks
    curr_peak_landscape = propagate_peaks(curr_peaks)
    # Build droplet trail mask starting from the footprint on the bottom
    curr_drop_trail_mask = create_trail_mask_from_drop_footprint(
        curr_peak_landscape.copy(), forbidden_mask, curr_drop_footprints,
        prev_drop_trail_masks, curr_plate_BW, prev_plate_BW)

    # Visualize results
    stop_flag, drop_data = visualize_img_and_drop_profiles(
        i_frame, file_name, curr_plate_BGR,
        prev_plate_BGR, curr_peaks, curr_peak_landscape,
        curr_drop_footprints.flatten(), curr_drop_trail_mask,
        curr_peak_profile, prev_peak_profile, diff_peak_profile,
        curr_local_max, max_peak_diff_idx, video_dir, pixel_to_mm_ratio_x)

    return stop_flag, curr_drop_trail_mask, curr_peak_profile, curr_peak_histogram, curr_peak_landscape, drop_data
Example #16
0
 def transform(self, x, y=None):
     final = []
     for image in x:
         image.reshape(28, 28)
         open_square = img.binary_opening(image)
         eroded_square = img.binary_erosion(image)
         reconstruction = img.binary_propagation(eroded_square, mask=image)
         final.append(reconstruction.flatten())
     return final
Example #17
0
def hysteresis_threshold(array, low_threshold, high_threshold, structure=None):
    """Create a mask that is True for regions in the input array which are
    entirely larger than low_threshold and which contain at least one element
    larger than high_threshold."""
    high_mask = array > high_threshold
    low_mask = array > low_threshold
    return ndimage.binary_propagation(high_mask,
                                      mask=low_mask,
                                      structure=structure)
Example #18
0
def refine_worm(image, initial_area, candidate_edges):
    # find strong worm edges (roughly equivalent to the edges found by find_initial_worm,
    # which are in candidate_edges): smooth the image, do canny edge-finding, and
    # then keep only those edges near candidate_edges
    smooth_image = restoration.denoise_tv_bregman(image, 140).astype(numpy.float32)
    smoothed, gradient, sobel = canny.prepare_canny(smooth_image, 8, initial_area)
    local_maxima = canny.canny_local_maxima(gradient, sobel)
    candidate_edge_region = ndimage.binary_dilation(candidate_edges, iterations=4)
    strong_edges = local_maxima & candidate_edge_region

    # Now threshold the image to find dark blobs as our initial worm region
    # First, find areas in the initial region unlikely to be worm pixels
    mean, std = mcd.robust_mean_std(smooth_image[initial_area][::4], 0.85)
    non_worm = (smooth_image > mean - std) & initial_area
    # now fit a smoothly varying polynomial to the non-worm pixels in the initial
    # region of interest, and subtract that from the actual image to generate
    # an image with a flat illumination field
    background = polyfit.fit_polynomial(smooth_image, mask=non_worm, degree=2)
    minus_bg = smooth_image - background
    # now recalculate a threshold from the background-subtracted pixels
    mean, std = mcd.robust_mean_std(minus_bg[initial_area][::4], 0.85)
    initial_worm = (minus_bg < mean - std) & initial_area
    # Add any pixels near the strong edges to our candidate worm position
    initial_worm |= ndimage.binary_dilation(strong_edges, iterations=3)
    initial_worm = mask.fill_small_radius_holes(initial_worm, 5)

    # Now grow/shrink the initial_worm region so that as many of the strong
    # edges from the canny filter are in contact with the region edges as possible.
    ac = active_contour.EdgeClaimingAdvection(initial_worm, strong_edges,
        max_region_mask=initial_area)
    stopper = active_contour.StoppingCondition(ac, max_iterations=100)
    while stopper.should_continue():
        ac.advect(iters=1)
        ac.smooth(iters=1, depth=2)
    worm_mask = mask.fill_small_radius_holes(ac.mask, 7)

    # Now, get edges from the image at a finer scale
    smoothed, gradient, sobel = canny.prepare_canny(smooth_image, 0.3, initial_area)
    local_maxima = canny.canny_local_maxima(gradient, sobel)
    strong_sum = strong_edges.sum()
    highp = 100 * (1 - 1.5*strong_sum/local_maxima.sum())
    lowp = max(100 * (1 - 3*strong_sum/local_maxima.sum()), 0)
    low_worm, high_worm = numpy.percentile(gradient[local_maxima], [lowp, highp])
    fine_edges = canny.canny_hysteresis(local_maxima, gradient, low_worm, high_worm)

    # Expand out the identified worm area to include any of these finer edges
    closed_edges = ndimage.binary_closing(fine_edges, structure=S)
    worm = ndimage.binary_propagation(worm_mask, mask=worm_mask|closed_edges, structure=S)
    worm = ndimage.binary_closing(worm, structure=S, iterations=2)
    worm = mask.fill_small_radius_holes(worm, 5)
    worm = ndimage.binary_opening(worm)
    worm = mask.get_largest_object(worm)
    # Last, smooth the shape a bit to reduce sharp corners, but not too much to
    # sand off the tail
    ac = active_contour.CurvatureMorphology(worm, max_region_mask=initial_area)
    ac.smooth(depth=2, iters=2)
    return strong_edges, ac.mask
Example #19
0
    def _compute_fill_task(
        self, task: FloodFillTask
    ) -> Optional[Tuple[Chunk[b8], List[FloodFillTask]]]:
        """
        Create a fill mask for a chunk with a source mask
        :param task: fill task
        :return: A tuple of the resulting fill mask for this chunk and tasks for the neighboring chunks to fill
        """

        # Do nothing when out of bounds
        if self.is_out_of_bounds(task.index):
            return None

        # Get mask
        mask_chunk: Chunk[b8] = self.mask.ensure_chunk_at_index(task.index,
                                                                insert=False)

        # Method cache (prevent lookup in loop)
        __face_flip = ChunkFace.flip
        __face_slice = ChunkFace.slice

        if mask_chunk.is_filled():
            if mask_chunk.value:
                return (Chunk(task.index, mask_chunk.size, b8,
                              b8_False).set_fill(b8_True), [
                                  FloodFillTask(i, face=__face_flip(f))
                                  for f, i in ChunkGrid.iter_neighbors_indices(
                                      mask_chunk.index) if f != task.face
                              ])
            else:
                return Chunk(task.index, mask_chunk.size, b8, b8_False), []

        task_image: np.ndarray = task.image(mask_chunk.array_shape)
        assert task_image.shape == mask_chunk.array_shape
        if not task_image.any():
            # return Chunk(task.index, chunk.size, dtype=np_bool8).set_fill(False), []
            return None
        else:
            mask = mask_chunk.to_array()
            # Enforce that only "free" fields in mask are filled
            img = task_image & mask
            result = ndimage.binary_propagation(img, mask=mask).astype(b8)

            # Create tasks where propagation is possible
            tasks = []
            for f, i in ChunkGrid.iter_neighbors_indices(mask_chunk.index):
                face_slice = result[__face_slice(f)]
                if face_slice.all():
                    if f != task.face:
                        tasks.append(FloodFillTask(i, face=__face_flip(f)))
                elif face_slice.any():
                    tmp = np.full(mask_chunk.shape, b8_False, dtype=b8)
                    tmp[__face_slice(__face_flip(f))] = face_slice
                    tasks.append(FloodFillTask(i, image=tmp))
            return Chunk(task.index, mask_chunk.size, b8,
                         b8_False).set_array(result).cleanup(), tasks
	def __test_binary_propagation_operation(self,input_var):		
		print("\n binary_propagation Voxel testing...")
		start_time = t.time()
		v_output = vc.binary_propagation(input_var,structure=structure,no_of_blocks=PL[0],fakeghost=PL[1],make_float32=False)
		print("binary_propagation Voxel testing time taken: ",(t.time() - start_time)," sec")
		#print("\n binary_propagation Default testing...")
		start_time = t.time()
		d_output = ndimage.binary_propagation(input_var,structure=structure)
		print("binary_propagation Default testing time taken: ",(t.time() - start_time)," sec")		
		msgs = "binary_propagation_operation_FAIL_with parameters: ",PL
		self.assertTrue((d_output==v_output).all(), msg=msgs)
def _check_isolated_seeds(labels):
    """
    Prune isolated seed pixels to prevent labeling errors, and
    return coordinates and label values of isolated seeds, so
    that it is possible to put labels back in random walker output.
    """
    fill = ndi.binary_propagation(labels == 0, mask=(labels >= 0))
    isolated = np.logical_and(labels > 0, np.logical_not(fill))
    inds = np.nonzero(isolated)
    values = labels[inds]
    labels[inds] = -1
    return inds, values
def _check_isolated_seeds(labels):
    """
    Prune isolated seed pixels to prevent labeling errors, and
    return coordinates and label values of isolated seeds, so
    that it is possible to put labels back in random walker output.
    """
    fill = ndi.binary_propagation(labels == 0, mask=(labels >= 0))
    isolated = np.logical_and(labels > 0, np.logical_not(fill))
    inds = np.nonzero(isolated)
    values = labels[inds]
    labels[inds] = -1
    return inds, values
Example #23
0
def removeNoise(array, its=10):
    """
    :rtype: object
    """

    PILified = PILconvert(array)

    eroded = ndimage.binary_erosion(PILified, iterations=its)
    reconstruction = np.array(ndimage.binary_propagation(eroded,
                                                         mask=PILified),
                              dtype="uint8")

    return reconstruction
Example #24
0
def fill_small_area_holes(mask, max_area):
    """Fill holes in the mask that are up to 'max area' (in terms of pixel-wise
    area).

    Returns a new mask with the small holes filled."""
    outside = ndimage.binary_propagation(numpy.zeros_like(mask),
                                         mask=~mask,
                                         border_value=1)
    holes = ~(mask | outside)
    labels, region_indices, areas = get_areas(holes)
    kill_labels = areas <= max_area
    kill_labels = numpy.concatenate(([0], kill_labels))
    small_holes = kill_labels[labels]
    return mask | small_holes
def labels_check(labels):
    labels = np.copy(labels)
    label_values = np.unique(labels)
    # Reorder label values to have consecutive integers (no gaps)
    if np.any(np.diff(label_values) != 1):
        mask = labels >= 0
        labels[mask] = rank_order(labels[mask])[0].astype(labels.dtype)
    labels = labels.astype(np.int32)
    if np.any(labels < 0):
        filled = ndi.binary_propagation(labels > 0, mask=labels >= 0)
        labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1
        del filled
    labels = np.atleast_3d(labels)
    return labels
Example #26
0
def widen_drop_trail_footprints(drop_footprint, peak_profile,
                                diff_peak_profile, min_diff_peak_profile):
    drop_labels, n_labels = ndimage.label(drop_footprint)
    new_footprint = drop_footprint.copy()
    for i_p in range(4):
        for i_label in range(1, 1 + n_labels):
            label_idx = np.where(drop_labels == i_label)
            expansion_areas = np.logical_and(
                peak_profile[i_p, :] <= np.median(
                    peak_profile[i_p, :][label_idx]),
                diff_peak_profile[i_p, :] >= min_diff_peak_profile)
            expanded_footprint = ndimage.binary_propagation(
                drop_labels == i_label, mask=expansion_areas)
            new_footprint |= expanded_footprint
    return new_footprint.astype(np.uint8)
Example #27
0
	def __operationTask(self,input_var):
		'''
		perform respective moephological operation on input block.
        Parameters
        ----------
        input_var  	: type: 3d numpy array, ith block.		
		
        Returns
		-------
		output     : type: 3d array, output of operation, ith block array.
        '''
		
		
		D=self.__operationArgumentDic
		if self.__operation=="binary_closing":	
			return ndimage.binary_closing(input_var, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
		elif self.__operation=="binary_dilation":
			return ndimage.binary_dilation(input_var, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
		elif self.__operation=="binary_erosion":
			return ndimage.binary_erosion(input_var, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
		elif self.__operation=="binary_fill_holes": #the output might be different then scipy.ndimage  
			return ndimage.binary_fill_holes(input_var, structure=D["structure"],output=D["output"], origin=D["origin"])
		elif self.__operation=="binary_hit_or_miss":
			return ndimage.binary_hit_or_miss(input_var, structure1=D["structure1"],structure2=D["structure2"],output=D["output"], origin1=D["origin1"], origin2=D["origin2"])
		elif self.__operation=="binary_opening":
			return ndimage.binary_opening(input_var, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
		elif self.__operation=="binary_propagation":			
			return ndimage.binary_propagation(input_var, structure=D["structure"],output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"])
		elif self.__operation=="black_tophat":
			return ndimage.black_tophat(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="grey_dilation":
			return ndimage.grey_dilation(input_var, structure=D["structure"],size=D["size"], footprint=D["footprint"],output=D["output"], mode=D["mode"], cval=D["cval"], origin=D["origin"])			
		elif self.__operation=="grey_closing":
			return ndimage.grey_closing(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="grey_erosion":
			return ndimage.grey_erosion(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="grey_opening":
			return ndimage.grey_opening(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="morphological_gradient":
			return ndimage.morphological_gradient(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="morphological_laplace":
			return ndimage.morphological_laplace(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="white_tophat":
			return ndimage.white_tophat(input_var, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
		elif self.__operation=="multiply":
			return input_var*D["scalar"]		
		else:
			return input_var # no operation performed....
Example #28
0
def connectedComponents(arr, palette):
    components = np.zeros(arr.shape[0:2])
    numcomponents = 0
    for (i, color) in enumerate(palette):
        onecolor = m.pixelwiseArr(arr, lambda pix: (pix == color).all())[:,:,0] # all dimensions identical

        # remove specks
        erSize = 4;
        eroded = ndimage.binary_erosion(onecolor, structure=np.ones((erSize, erSize)))
        reconstructed = ndimage.binary_propagation(eroded, mask=onecolor)
        
        # find connected components
        (labels, numlabels) = ndimage.measurements.label(reconstructed)
        components = labels + m.pixelwiseArr(components, lambda x : 0 if x==0 else x+numlabels)
        numcomponents += numlabels
    return (components, numcomponents)
Example #29
0
def fill_small_area_holes(mask, max_area):
    """Fill holes in the mask that are up to 'max area' (in terms of pixel-wise
    area).

    See also ndimage.binary_fill_holes if you want to fill all holes regardless
    of size.

    Returns a new mask with the small holes filled."""
    mask = mask.astype(bool)
    outside = ndimage.binary_propagation(numpy.zeros_like(mask),
                                         mask=~mask,
                                         border_value=1)
    holes = ~(mask | outside)
    labels, region_indices, areas = get_areas(holes)
    kill_labels = areas <= max_area
    kill_labels = numpy.concatenate(([False], kill_labels))
    small_holes = kill_labels[labels]
    return mask | small_holes
Example #30
0
    def is_propagated(s, threshold, ind=0):
        mask = np.where(s.distance_map_im > threshold, 1, 0)
        propagation = ndimage.binary_propagation(input=s.input_im,
                                                 mask=mask).astype(np.int)

        if s.save_paraview:
            ps.io.to_vtk(mask,
                         path=f'mask_{ind}',
                         divide=False,
                         downsample=False,
                         voxel_size=s.voxel_size,
                         vox=False)
            ps.io.to_vtk(propagation,
                         path=f'propagation_{ind}',
                         divide=False,
                         downsample=False,
                         voxel_size=s.voxel_size,
                         vox=False)

        return bool(np.count_nonzero(propagation[np.nonzero(s.output_im)]))
Example #31
0
def connectedComponents(arr, palette):
    components = np.zeros(arr.shape[0:2])
    numcomponents = 0
    for (i, color) in enumerate(palette):
        onecolor = m.pixelwiseArr(
            arr, lambda pix:
            (pix == color).all())[:, :, 0]  # all dimensions identical

        # remove specks
        erSize = 4
        eroded = ndimage.binary_erosion(onecolor,
                                        structure=np.ones((erSize, erSize)))
        reconstructed = ndimage.binary_propagation(eroded, mask=onecolor)

        # find connected components
        (labels, numlabels) = ndimage.measurements.label(reconstructed)
        components = labels + m.pixelwiseArr(
            components, lambda x: 0 if x == 0 else x + numlabels)
        numcomponents += numlabels
    return (components, numcomponents)
Example #32
0
def binary_propagation(square):
    open_square = ndimage.binary_opening(square)
    eroded_square = ndimage.binary_erosion(square)
    reconstruction = ndimage.binary_propagation(eroded_square, mask=square)
    plt.figure(figsize=(9.5, 3))
    plt.subplot(131)
    plt.imshow(square, cmap=plt.cm.hot, interpolation='nearest')
    plt.axis('off')
    plt.subplot(132)
    plt.imshow(open_square, cmap=plt.cm.hot, interpolation='nearest')
    plt.axis('off')
    plt.subplot(133)
    plt.imshow(reconstruction, cmap=plt.cm.hot, interpolation='nearest')
    plt.axis('off')
    plt.subplots_adjust(wspace=0,
                        hspace=0.02,
                        top=0.99,
                        bottom=0.01,
                        left=0.01,
                        right=0.99)
    plt.show()
Example #33
0
def binary_propagation(img, params):
    if params['structure_shape'] == 'rectangle':
        structure = np.ones(
            (params['structure_size_y'], params['structure_size_x']),
            dtype=bool)
    elif params['structure_shape'] == 'ellipse':
        a = params['structure_size_x'] / 2
        b = params['structure_size_y'] / 2
        x, y = np.mgrid[-ceil(a):ceil(a) + 1, -ceil(b):ceil(b) + 1]
        structure = (x / a)**2 + (y / b)**2 < 1

    origin = (params['origin_x'], params['origin_y'])
    border_value = params['border_value']

    return ndimage.binary_propagation(img,
                                      structure=structure,
                                      output=None,
                                      origin=origin,
                                      mask=None,
                                      border_value=border_value).astype(
                                          img.dtype)
def operationTask(input):
	D=operationArgumentDic
	#self.M.add_mem()#.....................................................................................................
	
	if operation=="binary_closing":	
		return ndimage.binary_closing(input, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
	elif operation=="binary_dilation":
		return ndimage.binary_dilation(input, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
	elif operation=="binary_erosion":
		return ndimage.binary_erosion(input, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
	elif operation=="binary_fill_holes":
		return ndimage.binary_fill_holes(input, structure=D["structure"],output=D["output"], origin=D["origin"])
	elif operation=="binary_hit_or_miss":
		return ndimage.binary_hit_or_miss(input, structure1=D["structure1"],structure2=D["structure2"],output=D["output"], origin1=D["origin1"], origin2=D["origin2"])
	elif operation=="binary_opening":
		return ndimage.binary_opening(input, structure=D["structure"], iterations=D["iterations"], output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"], brute_force=D["brute_force"])
	elif operation=="binary_propagation":			
		return ndimage.binary_propagation(input, structure=D["structure"],output=D["output"], origin=D["origin"], mask=D["mask"], border_value=D["border_value"])
	elif operation=="black_tophat":
		return ndimage.black_tophat(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="grey_dilation":
		return ndimage.grey_dilation(input, structure=D["structure"],size=D["size"], footprint=D["footprint"],output=D["output"], mode=D["mode"], cval=D["cval"], origin=D["origin"])
	elif operation=="grey_closing":
		return ndimage.grey_closing(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="grey_erosion":
		return ndimage.grey_erosion(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="grey_opening":
		return ndimage.grey_opening(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="morphological_gradient":
		return ndimage.morphological_gradient(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="morphological_laplace":
		return ndimage.morphological_laplace(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="white_tophat":
		return ndimage.white_tophat(input, structure=D["structure"], size=D["size"], footprint=D["footprint"],  output=D["output"], origin=D["origin"],mode=D["mode"], cval=D["cval"])
	elif operation=="intMultiply":
		return input*D["scalar"]
	
	else:
		return input
def random_walker(data, labels, beta=130, mode='cg_mg', tol=1.e-3, copy=True):
    """
        Segmentation with random walker algorithm by Leo Grady, 
        given some data and an array of labels (the more labeled 
        pixels, the less unknowns and the faster the resolution)

        Parameters
        ----------

        data : array_like
            Image to be segmented in regions. `data` can be two- or
            three-dimensional.

        labels : array of ints
            Array of seed markers labeled with different integers
            for different phases. Negative labels correspond to inactive
            pixels that do not diffuse (they are removed from the graph).

        beta : float
            Penalization coefficient for the random walker motion
            (the greater `beta`, the more difficult the diffusion).

        mode : {'bf', 'cg_mg', 'cg'}
            Mode for solving the linear system in the random walker 
            algorithm. 

            - 'bf' (brute force): an LU factorization of the Laplacian
            is computed. This is fast for small images (<256x256), but
            very slow (due to the memory cost) and memory-consuming for
            big images.

            - 'cg' (conjugate gradient): the linear system is solved
            iteratively using the Conjugate Gradient method from
            scipy.sparse.linalg. This is less memory-consuming than the
            brute force method for large images, but it is quite slow.

            - 'cg_mg' (conjugate gradient with multigrid preconditioner):
            a preconditioner is computed using a multigrid solver, then 
            the solution is computed with the Conjugate Gradient method. 
            This mode requires that the pyamg module 
            (http://code.google.com/p/pyamg/) is installed.

        tol : tolerance to achieve when solving the linear system

        copy : bool
            If copy is False, the `labels` array will be overwritten with
            the result of the segmentation. Use copy=False if you want to 
            save on memory.

        Returns
        -------

        output : ndarray of ints
            Array in which each pixel has been attributed the label number
            that reached the pixel first by diffusion.

        Notes
        -----

        The algorithm was first proposed in *Random walks for image 
        segmentation*, Leo Grady, IEEE Trans Pattern Anal Mach Intell. 
        2006 Nov;28(11):1768-83.

        Examples
        --------

        >>> a = np.zeros((10, 10)) + 0.2*np.random.random((10, 10))
        >>> a[5:8, 5:8] += 1
        >>> b = np.zeros_like(a)
        >>> b[3,3] = 1 #Marker for first phase
        >>> b[6,6] = 2 #Marker for second phase
        >>> random_walker(a, b)
        array([[ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.]])

    """
    # We work with 3-D arrays
    data = np.atleast_3d(data)
    if copy:
        labels = np.copy(labels)
    labels = labels.astype(np.int)
    # If the array has pruned zones, be sure that no isolated pixels
    # exist between pruned zones (they could not be determined)
    if np.any(labels<0):
        filled = ndimage.binary_propagation(labels>0, mask=labels>=0)
        labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1
        del filled
    labels = np.atleast_3d(labels)
    if np.any(labels < 0):
        lap_sparse = _build_laplacian(data, mask=labels >= 0, beta=beta)
    else:
        lap_sparse = _build_laplacian(data, beta=beta)
    lap_sparse, B = _buildAB(lap_sparse, labels)
    # We solve the linear system
    # lap_sparse X = B
    # where X[i, j] is the probability that a marker of label i arrives 
    # first at pixel j by diffusion
    if mode == 'cg':
        X = _solve_cg(lap_sparse, B, tol=tol)
    if mode == 'cg_mg':
        X = _solve_cg_mg(lap_sparse, B, tol=tol)
    if mode == 'bf':
        X = _solve_bf(lap_sparse, B)
    X = _clean_labels_ar(X + 1, labels)
    data = np.squeeze(data)
    return X.reshape(data.shape)
Example #36
0
File: canny.py Project: zplab/zplib
def canny_hysteresis(local_maxima, magnitude, low_threshold, high_threshold):
    # Hysteresis threshold
    high_mask = local_maxima & (magnitude >= high_threshold)
    low_mask = local_maxima & (magnitude >= low_threshold)
    s = numpy.ones((3,3), dtype=bool)
    return ndimage.binary_propagation(high_mask, mask=low_mask, structure=s)
def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True,
                  multichannel=False, return_full_prob=False, spacing=None):
    """Random walker algorithm for segmentation from markers.

    Random walker algorithm is implemented for gray-level or multichannel
    images.

    Parameters
    ----------
    data : array_like
        Image to be segmented in phases. Gray-level `data` can be two- or
        three-dimensional; multichannel data can be three- or four-
        dimensional (multichannel=True) with the highest dimension denoting
        channels. Data spacing is assumed isotropic unless the `spacing`
        keyword argument is used.
    labels : array of ints, of same shape as `data` without channels dimension
        Array of seed markers labeled with different positive integers
        for different phases. Zero-labeled pixels are unlabeled pixels.
        Negative labels correspond to inactive pixels that are not taken
        into account (they are removed from the graph). If labels are not
        consecutive integers, the labels array will be transformed so that
        labels are consecutive. In the multichannel case, `labels` should have
        the same shape as a single channel of `data`, i.e. without the final
        dimension denoting channels.
    beta : float, optional
        Penalization coefficient for the random walker motion
        (the greater `beta`, the more difficult the diffusion).
    mode : string, available options {'cg_mg', 'cg', 'bf'}
        Mode for solving the linear system in the random walker algorithm.
        If no preference given, automatically attempt to use the fastest
        option available ('cg_mg' from pyamg >> 'cg' with UMFPACK > 'bf').

        - 'bf' (brute force): an LU factorization of the Laplacian is
          computed. This is fast for small images (<1024x1024), but very slow
          and memory-intensive for large images (e.g., 3-D volumes).
        - 'cg' (conjugate gradient): the linear system is solved iteratively
          using the Conjugate Gradient method from scipy.sparse.linalg. This is
          less memory-consuming than the brute force method for large images,
          but it is quite slow.
        - 'cg_mg' (conjugate gradient with multigrid preconditioner): a
          preconditioner is computed using a multigrid solver, then the
          solution is computed with the Conjugate Gradient method.  This mode
          requires that the pyamg module (http://pyamg.github.io/) is
          installed. For images of size > 512x512, this is the recommended
          (fastest) mode.

    tol : float, optional
        tolerance to achieve when solving the linear system, in
        cg' and 'cg_mg' modes.
    copy : bool, optional
        If copy is False, the `labels` array will be overwritten with
        the result of the segmentation. Use copy=False if you want to
        save on memory.
    multichannel : bool, optional
        If True, input data is parsed as multichannel data (see 'data' above
        for proper input format in this case).
    return_full_prob : bool, optional
        If True, the probability that a pixel belongs to each of the labels
        will be returned, instead of only the most likely label.
    spacing : iterable of floats, optional
        Spacing between voxels in each spatial dimension. If `None`, then
        the spacing between pixels/voxels in each dimension is assumed 1.

    Returns
    -------
    output : ndarray
        * If `return_full_prob` is False, array of ints of same shape as
          `data`, in which each pixel has been labeled according to the marker
          that reached the pixel first by anisotropic diffusion.
        * If `return_full_prob` is True, array of floats of shape
          `(nlabels, data.shape)`. `output[label_nb, i, j]` is the probability
          that label `label_nb` reaches the pixel `(i, j)` first.

    See also
    --------
    skimage.morphology.watershed: watershed segmentation
        A segmentation algorithm based on mathematical morphology
        and "flooding" of regions from markers.

    Notes
    -----
    Multichannel inputs are scaled with all channel data combined. Ensure all
    channels are separately normalized prior to running this algorithm.

    The `spacing` argument is specifically for anisotropic datasets, where
    data points are spaced differently in one or more spatial dimensions.
    Anisotropic data is commonly encountered in medical imaging.

    The algorithm was first proposed in [1]_.

    The algorithm solves the diffusion equation at infinite times for
    sources placed on markers of each phase in turn. A pixel is labeled with
    the phase that has the greatest probability to diffuse first to the pixel.

    The diffusion equation is solved by minimizing x.T L x for each phase,
    where L is the Laplacian of the weighted graph of the image, and x is
    the probability that a marker of the given phase arrives first at a pixel
    by diffusion (x=1 on markers of the phase, x=0 on the other markers, and
    the other coefficients are looked for). Each pixel is attributed the label
    for which it has a maximal value of x. The Laplacian L of the image
    is defined as:

       - L_ii = d_i, the number of neighbors of pixel i (the degree of i)
       - L_ij = -w_ij if i and j are adjacent pixels

    The weight w_ij is a decreasing function of the norm of the local gradient.
    This ensures that diffusion is easier between pixels of similar values.

    When the Laplacian is decomposed into blocks of marked and unmarked
    pixels::

        L = M B.T
            B A

    with first indices corresponding to marked pixels, and then to unmarked
    pixels, minimizing x.T L x for one phase amount to solving::

        A x = - B x_m

    where x_m = 1 on markers of the given phase, and 0 on other markers.
    This linear system is solved in the algorithm using a direct method for
    small images, and an iterative method for larger images.

    References
    ----------
    .. [1] Leo Grady, Random walks for image segmentation, IEEE Trans Pattern
        Anal Mach Intell. 2006 Nov;28(11):1768-83.
        :DOI:`10.1109/TPAMI.2006.233`.

    Examples
    --------
    >>> np.random.seed(0)
    >>> a = np.zeros((10, 10)) + 0.2 * np.random.rand(10, 10)
    >>> a[5:8, 5:8] += 1
    >>> b = np.zeros_like(a)
    >>> b[3, 3] = 1  # Marker for first phase
    >>> b[6, 6] = 2  # Marker for second phase
    >>> random_walker(a, b)
    array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
           [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
           [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)

    """
    # Parse input data
    if mode is None:
        if amg_loaded:
            mode = 'cg_mg'
        elif UmfpackContext is not None:
            mode = 'cg'
        else:
            mode = 'bf'
    elif mode not in ('cg_mg', 'cg', 'bf'):
        raise ValueError("{mode} is not a valid mode. Valid modes are 'cg_mg',"
                         " 'cg' and 'bf'".format(mode=mode))

    if UmfpackContext is None and mode == 'cg':
        warn('"cg" mode will be used, but it may be slower than '
             '"bf" because SciPy was built without UMFPACK. Consider'
             ' rebuilding SciPy with UMFPACK; this will greatly '
             'accelerate the conjugate gradient ("cg") solver. '
             'You may also install pyamg and run the random_walker '
             'function in "cg_mg" mode (see docstring).')

    if (labels != 0).all():
        warn('Random walker only segments unlabeled areas, where '
             'labels == 0. No zero valued areas in labels were '
             'found. Returning provided labels.')

        return _unchanged_labels(labels, return_full_prob)

    # This algorithm expects 4-D arrays of floats, where the first three
    # dimensions are spatial and the final denotes channels. 2-D images have
    # a singleton placeholder dimension added for the third spatial dimension,
    # and single channel images likewise have a singleton added for channels.
    # The following block ensures valid input and coerces it to the correct
    # form.
    if not multichannel:
        if data.ndim not in (2, 3):
            raise ValueError('For non-multichannel input, data must be of '
                             'dimension 2 or 3.')
        dims = data.shape  # To reshape final labeled result
        data = np.atleast_3d(img_as_float(data))[..., np.newaxis]
    else:
        if data.ndim not in (3, 4):
            raise ValueError('For multichannel input, data must have 3 or 4 '
                             'dimensions.')
        dims = data[..., 0].shape  # To reshape final labeled result
        data = img_as_float(data)
        if data.ndim == 3:  # 2D multispectral, needs singleton in 3rd axis
            data = data[:, :, np.newaxis, :]

    # Spacing kwarg checks
    if spacing is None:
        spacing = np.asarray((1.,) * 3)
    elif len(spacing) == len(dims):
        if len(spacing) == 2:  # Need a dummy spacing for singleton 3rd dim
            spacing = np.r_[spacing, 1.]
        else:                  # Convert to array
            spacing = np.asarray(spacing)
    else:
        raise ValueError('Input argument `spacing` incorrect, should be an '
                         'iterable with one number per spatial dimension.')

    if copy:
        labels = np.copy(labels)
    label_values = np.unique(labels)

    # If some labeled pixels are isolated inside pruned zones, prune them
    # as well and keep the labels for the final output
    inds_isolated_seeds, isolated_values = _check_isolated_seeds(labels)

    # Reorder label values to have consecutive integers (no gaps)
    if np.any(np.diff(label_values) != 1):
        mask = labels >= 0
        labels[mask] = rank_order(labels[mask])[0].astype(labels.dtype)
    labels = labels.astype(np.int32)

    # If the array has pruned zones, be sure that no isolated pixels
    # exist between pruned zones (they could not be determined)
    if np.any(labels < 0):
        filled = ndi.binary_propagation(labels > 0, mask=labels >= 0)
        labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1
        del filled
    labels = np.atleast_3d(labels)

    # No unlabeled pixel, so nothing to do
    if (labels == 0).sum() == 0:
        labels = np.squeeze(labels)
        labels[inds_isolated_seeds] = isolated_values
        warn('Random walker only segments unlabeled areas, where '
             'labels == 0. No zero valued areas in labels were '
             'found. Returning provided labels.')
        return _unchanged_labels(labels, return_full_prob)

    if np.any(labels < 0):
        lap_sparse = _build_laplacian(data, spacing, mask=labels >= 0,
                                      beta=beta, multichannel=multichannel)
    else:
        lap_sparse = _build_laplacian(data, spacing, beta=beta,
                                      multichannel=multichannel)
    lap_sparse, B = _buildAB(lap_sparse, labels)

    # We solve the linear system
    # lap_sparse X = B
    # where X[i, j] is the probability that a marker of label i arrives
    # first at pixel j by anisotropic diffusion.
    if mode == 'cg':
        X = _solve_cg(lap_sparse, B, tol=tol,
                      return_full_prob=return_full_prob)
    if mode == 'cg_mg':
        if not amg_loaded:
            warn("""pyamg (http://pyamg.github.io/)) is needed to use
                this mode, but is not installed. The 'cg' mode will be used
                instead.""")
            X = _solve_cg(lap_sparse, B, tol=tol,
                          return_full_prob=return_full_prob)
        else:
            X = _solve_cg_mg(lap_sparse, B, tol=tol,
                             return_full_prob=return_full_prob)
    if mode == 'bf':
        X = _solve_bf(lap_sparse, B,
                      return_full_prob=return_full_prob)

    # Clean up results
    if return_full_prob:
        labels = labels.astype(np.float)
        # Put back labels of isolated seeds
        if len(isolated_values) > 0:
            labels[inds_isolated_seeds] = isolated_values
        X = np.array([_clean_labels_ar(Xline, labels, copy=True).reshape(dims)
                      for Xline in X])
        for i in range(1, int(labels.max()) + 1):
            mask_i = np.squeeze(labels == i)
            X[:, mask_i] = 0
            X[i - 1, mask_i] = 1
    else:
        X = _clean_labels_ar(X + 1, labels).reshape(dims)
        # Put back labels of isolated seeds
        X[inds_isolated_seeds] = isolated_values
    return X
plt.subplot(142)
plt.imshow(open_img[:l, :l], cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(143)
plt.imshow(close_img[:l, :l], cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(144)
plt.imshow(mask[:l, :l], cmap=plt.cm.gray)
plt.contour(close_img[:l, :l], [0.5], linewidths=2, colors='r')
plt.axis('off')

plt.subplots_adjust(wspace=0.02, hspace=0.3, top=1, bottom=0.1, left=0, right=1)

# Better than opening and closing: use reconstruction
eroded_img = ndimage.binary_erosion(binary_img)
reconstruct_img = ndimage.binary_propagation(eroded_img, mask=binary_img)
tmp = np.logical_not(reconstruct_img)
eroded_tmp = ndimage.binary_erosion(tmp)
reconstruct_final = np.logical_not(ndimage.binary_propagation(eroded_tmp, mask=tmp))

"""
plt.subplot(141)
plt.imshow(binary_img[:l, :l], cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(142)
plt.imshow(eroded_img[:l, :l], cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(143)
plt.imshow(reconstruct_img[:l, :l], cmap=plt.cm.gray)
plt.axis('off')
plt.subplot(144)
def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True,
                  multichannel=False, return_full_prob=False, spacing=None):
    """Random walker algorithm for segmentation from markers.

    Random walker algorithm is implemented for gray-level or multichannel
    images.

    Parameters
    ----------
    data : array_like
        Image to be segmented in phases. Gray-level `data` can be two- or
        three-dimensional; multichannel data can be three- or four-
        dimensional (multichannel=True) with the highest dimension denoting
        channels. Data spacing is assumed isotropic unless the `spacing` 
        keyword argument is used.
    labels : array of ints, of same shape as `data` without channels dimension
        Array of seed markers labeled with different positive integers
        for different phases. Zero-labeled pixels are unlabeled pixels.
        Negative labels correspond to inactive pixels that are not taken
        into account (they are removed from the graph). If labels are not
        consecutive integers, the labels array will be transformed so that
        labels are consecutive. In the multichannel case, `labels` should have
        the same shape as a single channel of `data`, i.e. without the final
        dimension denoting channels.
    beta : float
        Penalization coefficient for the random walker motion
        (the greater `beta`, the more difficult the diffusion).
    mode : {'bf', 'cg_mg', 'cg'} (default: 'bf')
        Mode for solving the linear system in the random walker
        algorithm.

        - 'bf' (brute force, default): an LU factorization of the Laplacian is
          computed. This is fast for small images (<1024x1024), but very slow
          (due to the memory cost) and memory-consuming for big images (in 3-D
          for example).
        - 'cg' (conjugate gradient): the linear system is solved iteratively
          using the Conjugate Gradient method from scipy.sparse.linalg. This is
          less memory-consuming than the brute force method for large images,
          but it is quite slow.
        - 'cg_mg' (conjugate gradient with multigrid preconditioner): a
          preconditioner is computed using a multigrid solver, then the
          solution is computed with the Conjugate Gradient method.  This mode
          requires that the pyamg module (http://pyamg.org/) is
          installed. For images of size > 512x512, this is the recommended
          (fastest) mode.

    tol : float
        tolerance to achieve when solving the linear system, in
        cg' and 'cg_mg' modes.
    copy : bool
        If copy is False, the `labels` array will be overwritten with
        the result of the segmentation. Use copy=False if you want to
        save on memory.
    multichannel : bool, default False
        If True, input data is parsed as multichannel data (see 'data' above
        for proper input format in this case)
    return_full_prob : bool, default False
        If True, the probability that a pixel belongs to each of the labels
        will be returned, instead of only the most likely label.
    spacing : iterable of floats
        Spacing between voxels in each spatial dimension. If `None`, then
        the spacing between pixels/voxels in each dimension is assumed 1.

    Returns
    -------
    output : ndarray
        * If `return_full_prob` is False, array of ints of same shape as
          `data`, in which each pixel has been labeled according to the marker
          that reached the pixel first by anisotropic diffusion.
        * If `return_full_prob` is True, array of floats of shape
          `(nlabels, data.shape)`. `output[label_nb, i, j]` is the probability
          that label `label_nb` reaches the pixel `(i, j)` first.

    See also
    --------
    skimage.morphology.watershed: watershed segmentation
        A segmentation algorithm based on mathematical morphology
        and "flooding" of regions from markers.

    Notes
    -----
    Multichannel inputs are scaled with all channel data combined. Ensure all
    channels are separately normalized prior to running this algorithm.

    The `spacing` argument is specifically for anisotropic datasets, where
    data points are spaced differently in one or more spatial dimensions.
    Anisotropic data is commonly encountered in medical imaging.

    The algorithm was first proposed in *Random walks for image
    segmentation*, Leo Grady, IEEE Trans Pattern Anal Mach Intell.
    2006 Nov;28(11):1768-83.

    The algorithm solves the diffusion equation at infinite times for
    sources placed on markers of each phase in turn. A pixel is labeled with
    the phase that has the greatest probability to diffuse first to the pixel.

    The diffusion equation is solved by minimizing x.T L x for each phase,
    where L is the Laplacian of the weighted graph of the image, and x is
    the probability that a marker of the given phase arrives first at a pixel
    by diffusion (x=1 on markers of the phase, x=0 on the other markers, and
    the other coefficients are looked for). Each pixel is attributed the label
    for which it has a maximal value of x. The Laplacian L of the image
    is defined as:

       - L_ii = d_i, the number of neighbors of pixel i (the degree of i)
       - L_ij = -w_ij if i and j are adjacent pixels

    The weight w_ij is a decreasing function of the norm of the local gradient.
    This ensures that diffusion is easier between pixels of similar values.

    When the Laplacian is decomposed into blocks of marked and unmarked
    pixels::

        L = M B.T
            B A

    with first indices corresponding to marked pixels, and then to unmarked
    pixels, minimizing x.T L x for one phase amount to solving::

        A x = - B x_m

    where x_m = 1 on markers of the given phase, and 0 on other markers.
    This linear system is solved in the algorithm using a direct method for
    small images, and an iterative method for larger images.

    Examples
    --------
    >>> a = np.zeros((10, 10)) + 0.2*np.random.random((10, 10))
    >>> a[5:8, 5:8] += 1
    >>> b = np.zeros_like(a)
    >>> b[3,3] = 1 #Marker for first phase
    >>> b[6,6] = 2 #Marker for second phase
    >>> random_walker(a, b)
    array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
           [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
           [1, 1, 1, 1, 1, 2, 2, 2, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)

    """

    if mode is None:
        if amg_loaded:
            mode = 'cg_mg'
        elif UmfpackContext is not None:
            mode = 'cg'
        else:
            mode = 'bf'

    if UmfpackContext is None and mode == 'cg':
        warnings.warn('SciPy was built without UMFPACK. Consider rebuilding '
                      'SciPy with UMFPACK, this will greatly speed up the '
                      'random walker functions. You may also install pyamg '
                      'and run the random walker function in cg_mg mode '
                      '(see the docstrings)')

    # Spacing kwarg checks
    if spacing is None:
        spacing = (1., 1., 1.)
    elif len(spacing) == 3:
        pass
    else:
        raise ValueError('Input argument `spacing` incorrect, should be an '
                         'iterable of length 3.')

    # Parse input data
    if not multichannel:
        # We work with 4-D arrays of floats
        assert data.ndim > 1 and data.ndim < 4, 'For non-multichannel input, \
                                                 data must be of dimension 2 \
                                                 or 3.'
        dims = data.shape
        data = np.atleast_3d(img_as_float(data))[..., np.newaxis]
    else:
        dims = data[..., 0].shape
        assert multichannel and data.ndim > 2, 'For multichannel input, data \
                                                must have >= 3 dimensions.'
        data = img_as_float(data)
        if data.ndim == 3:
            data = data[..., np.newaxis].transpose((0, 1, 3, 2))

    if copy:
        labels = np.copy(labels)
    label_values = np.unique(labels)
    # Reorder label values to have consecutive integers (no gaps)
    if np.any(np.diff(label_values) != 1):
        mask = labels >= 0
        labels[mask] = rank_order(labels[mask])[0].astype(labels.dtype)
    labels = labels.astype(np.int32)
    # If the array has pruned zones, be sure that no isolated pixels
    # exist between pruned zones (they could not be determined)
    if np.any(labels < 0):
        filled = ndimage.binary_propagation(labels > 0, mask=labels >= 0)
        labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1
        del filled
    labels = np.atleast_3d(labels)
    if np.any(labels < 0):
        lap_sparse = _build_laplacian(data, spacing, mask=labels >= 0,
                                      beta=beta, multichannel=multichannel)
    else:
        lap_sparse = _build_laplacian(data, spacing, beta=beta,
                                      multichannel=multichannel)
    lap_sparse, B = _buildAB(lap_sparse, labels)
    # We solve the linear system
    # lap_sparse X = B
    # where X[i, j] is the probability that a marker of label i arrives
    # first at pixel j by anisotropic diffusion.
    if mode == 'cg':
        X = _solve_cg(lap_sparse, B, tol=tol,
                      return_full_prob=return_full_prob)
    if mode == 'cg_mg':
        if not amg_loaded:
            warnings.warn(
                """pyamg (http://pyamg.org/)) is needed to use
                this mode, but is not installed. The 'cg' mode will be used
                instead.""")
            X = _solve_cg(lap_sparse, B, tol=tol,
                          return_full_prob=return_full_prob)
        else:
            X = _solve_cg_mg(lap_sparse, B, tol=tol,
                             return_full_prob=return_full_prob)
    if mode == 'bf':
        X = _solve_bf(lap_sparse, B,
                      return_full_prob=return_full_prob)
    # Clean up results
    if return_full_prob:
        labels = labels.astype(np.float)
        X = np.array([_clean_labels_ar(Xline, labels,
                     copy=True).reshape(dims) for Xline in X])
        for i in range(1, int(labels.max()) + 1):
            mask_i = np.squeeze(labels == i)
            X[:, mask_i] = 0
            X[i - 1, mask_i] = 1
    else:
        X = _clean_labels_ar(X + 1, labels).reshape(dims)
    return X
def noise_reduction(img, file_name):
    colum_median = np.median(img, axis=0)
    row_median = np.median(img, axis=1)

    media_factor = 1.2

    for x in xrange(0, img.shape[0]):
        for y in xrange(0,img.shape[1]):
            if img[x][y] < colum_median[y]/media_factor and img[x][y] < row_median[x]/media_factor:
                img[x][y] = 255
            else:
                img[x][y] = 0


    eroded_img = ndimage.binary_erosion(img)
    reconstruct_img = ndimage.binary_propagation(eroded_img, mask=img)
    tmp = np.logical_not(reconstruct_img)
    eroded_tmp = ndimage.binary_erosion(tmp)
    reconstruct_final = np.logical_not(ndimage.binary_propagation(eroded_tmp, mask=tmp))
    # eroded_tmp.show()


    labeled, num_features  = ndimage.measurements.label(reconstruct_final.astype(np.int))
    area = ndimage.measurements.sum(reconstruct_final, labeled, index=np.arange(1, labeled.max() + 1))

    # valid_area_count = 0
    # area_threshould = 500

    # for x in xrange(0,num_features):
    #     if area[x] > area_threshould:
    #         valid_area_count += 1

    labels = ndimage.measurements.find_objects(labeled, max_label= num_features)


    segment_dir = "." + "/Features"+file_name.strip(".png") + "/"
    print segment_dir
    if not os.path.exists(segment_dir):
        os.makedirs(segment_dir)

    plot_count = 0
    vector_length = 10
    area_permutation = area.argsort()[::-1]

    record = open(segment_dir + os.path.basename(file_name).strip(".png") + ".txt", "w")
    for x in xrange(0, vector_length):
        # plt.subplot(1, valid_area_count, plot_count+1)
        if x < len(area_permutation):
            (y_1, y_2, step_1) = labels[area_permutation[x]][0].indices(reconstruct_final.shape[0])
            (x_1, x_2, step_2) = labels[area_permutation[x]][1].indices(reconstruct_final.shape[1])

            # Cut features into pieces and save as png files
            # img_file = segment_dir + os.path.basename(file_name).strip(".png") + "_segment_" + str(plot_count) + ".png"
            # misc.imsave(img_file, reconstruct_final[labels[area_permutation[x]]])
            record.write(str(x_1) + "," + str(y_1) + "," + str(x_2) +"," + str(y_2) + "\n")
        else:
            record.write("0" + "," + "0" + "," + "0" +"," + "0" + "\n")

            # toinvert = Image.open(img_file)
            # inverted = ImageOps.invert(toinvert)
            # inverted.save(img_file)

            plot_count += 1
def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True):
    """
    Random walker algorithm for segmentation from markers.

    Parameters
    ----------

    data : array_like
        Image to be segmented in phases. `data` can be two- or
        three-dimensional.

    labels : array of ints, of same shape as `data`
        Array of seed markers labeled with different positive integers
        for different phases. Zero-labeled pixels are unlabeled pixels.
        Negative labels correspond to inactive pixels that are not taken
        into account (they are removed from the graph).

    beta : float
        Penalization coefficient for the random walker motion
        (the greater `beta`, the more difficult the diffusion).

    mode : {'bf', 'cg_mg', 'cg'} (default: 'bf')
        Mode for solving the linear system in the random walker
        algorithm.

        - 'bf' (brute force, default): an LU factorization of the Laplacian is
          computed. This is fast for small images (<1024x1024), but very slow
          (due to the memory cost) and memory-consuming for big images (in 3-D
          for example).

        - 'cg' (conjugate gradient): the linear system is solved iteratively
          using the Conjugate Gradient method from scipy.sparse.linalg. This is
          less memory-consuming than the brute force method for large images,
          but it is quite slow.

        - 'cg_mg' (conjugate gradient with multigrid preconditioner): a
          preconditioner is computed using a multigrid solver, then the
          solution is computed with the Conjugate Gradient method.  This mode
          requires that the pyamg module (http://code.google.com/p/pyamg/) is
          installed. For images of size > 512x512, this is the recommended
          (fastest) mode.

    tol : float
        tolerance to achieve when solving the linear system, in
        cg' and 'cg_mg' modes.

    copy : bool
        If copy is False, the `labels` array will be overwritten with
        the result of the segmentation. Use copy=False if you want to
        save on memory.

    Returns
    -------

    output : ndarray of ints
        Array in which each pixel has been labeled according to the marker
        that reached the pixel first by anisotropic diffusion.

    See also
    --------

    skimage.morphology.watershed: watershed segmentation
        A segmentation algorithm based on mathematical morphology
        and "flooding" of regions from markers.

    Notes
    -----

    The algorithm was first proposed in *Random walks for image
    segmentation*, Leo Grady, IEEE Trans Pattern Anal Mach Intell.
    2006 Nov;28(11):1768-83.

    The algorithm solves the diffusion equation at infinite times for
    sources placed on markers of each phase in turn. A pixel is labeled with
    the phase that has the greatest probability to diffuse first to the pixel.

    The diffusion equation is solved by minimizing x.T L x for each phase,
    where L is the Laplacian of the weighted graph of the image, and x is
    the probability that a marker of the given phase arrives first at a pixel
    by diffusion (x=1 on markers of the phase, x=0 on the other markers, and
    the other coefficients are looked for). Each pixel is attributed the label
    for which it has a maximal value of x. The Laplacian L of the image
    is defined as:

       - L_ii = d_i, the number of neighbors of pixel i (the degree of i)
       - L_ij = -w_ij if i and j are adjacent pixels

    The weight w_ij is a decreasing function of the norm of the local gradient.
    This ensures that diffusion is easier between pixels of similar values.

    When the Laplacian is decomposed into blocks of marked and unmarked pixels::

        L = M B.T
            B A

    with first indices corresponding to marked pixels, and then to unmarked
    pixels, minimizing x.T L x for one phase amount to solving::

        A x = - B x_m

    where x_m=1 on markers of the given phase, and 0 on other markers.
    This linear system is solved in the algorithm using a direct method for
    small images, and an iterative method for larger images.

    Examples
    --------

    >>> a = np.zeros((10, 10)) + 0.2*np.random.random((10, 10))
    >>> a[5:8, 5:8] += 1
    >>> b = np.zeros_like(a)
    >>> b[3,3] = 1 #Marker for first phase
    >>> b[6,6] = 2 #Marker for second phase
    >>> random_walker(a, b)
    array([[ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
            [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.]])

    """
    # We work with 3-D arrays
    data = np.atleast_3d(data)
    if copy:
        labels = np.copy(labels)
    labels = labels.astype(np.intp)
    # If the array has pruned zones, be sure that no isolated pixels
    # exist between pruned zones (they could not be determined)
    if np.any(labels < 0):
        filled = ndimage.binary_propagation(labels > 0, mask=labels >= 0)
        labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1
        del filled
    labels = np.atleast_3d(labels)
    if np.any(labels < 0):
        lap_sparse = _build_laplacian(data, mask=labels >= 0, beta=beta)
    else:
        lap_sparse = _build_laplacian(data, beta=beta)
    lap_sparse, B = _buildAB(lap_sparse, labels)
    # We solve the linear system
    # lap_sparse X = B
    # where X[i, j] is the probability that a marker of label i arrives
    # first at pixel j by anisotropic diffusion.
    if mode == 'cg':
        X = _solve_cg(lap_sparse, B, tol=tol)
    if mode == 'cg_mg':
        if not amg_loaded:
            warnings.warn(
            """pyamg (http://code.google.com/p/pyamg/)) is needed to use
            this mode, but is not installed. The 'cg' mode will be used
            instead.""")
            X = _solve_cg(lap_sparse, B, tol=tol)
        else:
            X = _solve_cg_mg(lap_sparse, B, tol=tol)
    if mode == 'bf':
        X = _solve_bf(lap_sparse, B)
    X = _clean_labels_ar(X + 1, labels)
    data = np.squeeze(data)
    return X.reshape(data.shape)
"""

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt

square = np.zeros((32, 32))
square[10:-10, 10:-10] = 1
np.random.seed(2)
x, y = (32 * np.random.random((2, 20))).astype(np.int)
square[x, y] = 1

open_square = ndimage.binary_opening(square)

eroded_square = ndimage.binary_erosion(square)
reconstruction = ndimage.binary_propagation(eroded_square, mask=square)

plt.figure(figsize=(9.5, 3))
plt.subplot(131)
plt.imshow(square, cmap=plt.cm.gray, interpolation="nearest")
plt.axis("off")
plt.subplot(132)
plt.imshow(open_square, cmap=plt.cm.gray, interpolation="nearest")
plt.axis("off")
plt.subplot(133)
plt.imshow(reconstruction, cmap=plt.cm.gray, interpolation="nearest")
plt.axis("off")

plt.subplots_adjust(wspace=0, hspace=0.02, top=0.99, bottom=0.01, left=0.01, right=0.99)
plt.show()
def noise_reduction(img):
	colum_median = np.median(img, axis=0)
	row_median = np.median(img, axis=1)

	media_factor = 2

	for x in xrange(0, img.shape[0]):
		for y in xrange(0,img.shape[1]):
			if img[x][y] < colum_median[y]/media_factor and img[x][y] < row_median[x]/media_factor:
				img[x][y] = 255
			else:
				img[x][y] = 0

	misc.imsave("Median_clipped.png", img)
	toinvert = Image.open('Median_clipped.png')
	inverted = ImageOps.invert(toinvert)
	inverted.save("Median_clipped.png")


	eroded_img = ndimage.binary_erosion(img)
	reconstruct_img = ndimage.binary_propagation(eroded_img, mask=img)
	tmp = np.logical_not(reconstruct_img)
	eroded_tmp = ndimage.binary_erosion(tmp)
	reconstruct_final = np.logical_not(ndimage.binary_propagation(eroded_tmp, mask=tmp))

	misc.imsave("Eroded_and_propagated.png", reconstruct_final)
	toinvert = Image.open('Eroded_and_propagated.png')
	inverted = ImageOps.invert(toinvert)
	inverted.save("Eroded_and_propagated.png")

	labeled, num_features  = ndimage.measurements.label(reconstruct_final.astype(np.int))

	area = ndimage.measurements.sum(reconstruct_final, labeled, index=np.arange(1, labeled.max() + 1))

	valid_area_count = 0
	area_threshould = 500

	for x in xrange(0,num_features):
		if area[x] > area_threshould:
			valid_area_count += 1

	labels = ndimage.measurements.find_objects(labeled, max_label= num_features)

	# fig = plt.figure(figsize=(10, 4), dpi=100)

	cropped = Image.open("Cropped.png").convert('RGB')
	draw = ImageDraw.Draw(cropped)

	plot_count = 0
	for x in xrange(0, num_features):
		if plot_count == valid_area_count:
			break
		plt.subplot(1, valid_area_count, plot_count+1)
		if area[x] > area_threshould:
			(y_1, y_2, step_1) = labels[x][0].indices(reconstruct_final.shape[0])
			(x_1, x_2, step_2) = labels[x][1].indices(reconstruct_final.shape[1])
			draw.rectangle([x_1, y_1, x_2, y_2], outline = "yellow")
			# plt.imshow(reconstruct_final[labels[x]], cmap = cm.Greys)
			# plt.axis('off')
			plot_count += 1

	# plt.show()
	cropped.show()
	misc.imsave("labled.png", cropped)
Example #44
0
def _random_walker(data, labels, beta=130, tol=1.0e-3, copy=True, spacing=None):
    """Random walker algorithm for segmentation from markers.

    Parameters
    ----------
    data : array_like
        Image to be segmented in phases. Data spacing is assumed isotropic unless
        the `spacing` keyword argument is used.
    labels : array of ints, of same shape as `data` without channels dimension
        Array of seed markers labeled with different positive integers
        for different phases. Zero-labeled pixels are unlabeled pixels.
        Negative labels correspond to inactive pixels that are not taken
        into account (they are removed from the graph). If labels are not
        consecutive integers, the labels array will be transformed so that
        labels are consecutive.
    beta : float
        Penalization coefficient for the random walker motion
        (the greater `beta`, the more difficult the diffusion).
    tol : float
        tolerance to achieve when solving the linear system, in
        cg' mode.
    copy : bool
        If copy is False, the `labels` array will be overwritten with
        the result of the segmentation. Use copy=False if you want to
        save on memory.
    spacing : iterable of floats
        Spacing between voxels in each spatial dimension. If `None`, then
        the spacing between pixels/voxels in each dimension is assumed 1.

    Returns
    -------
    output : ndarray
        * An array of ints of same shape as `data`, in which each pixel has
          been labeled according to the marker that reached the pixel first
          by anisotropic diffusion.

    Notes
    -----
    The `spacing` argument is specifically for anisotropic datasets, where
    data points are spaced differently in one or more spatial dimensions.
    Anisotropic data is commonly encountered in medical imaging.

    The algorithm was first proposed in *Random walks for image
    segmentation*, Leo Grady, IEEE Trans Pattern Anal Mach Intell.
    2006 Nov;28(11):1768-83.

    The algorithm solves the diffusion equation at infinite times for
    sources placed on markers of each phase in turn. A pixel is labeled with
    the phase that has the greatest probability to diffuse first to the pixel.

    The diffusion equation is solved by minimizing x.T L x for each phase,
    where L is the Laplacian of the weighted graph of the image, and x is
    the probability that a marker of the given phase arrives first at a pixel
    by diffusion (x=1 on markers of the phase, x=0 on the other markers, and
    the other coefficients are looked for). Each pixel is attributed the label
    for which it has a maximal value of x. The Laplacian L of the image
    is defined as:

       - L_ii = d_i, the number of neighbors of pixel i (the degree of i)
       - L_ij = -w_ij if i and j are adjacent pixels

    The weight w_ij is a decreasing function of the norm of the local gradient.
    This ensures that diffusion is easier between pixels of similar values.

    When the Laplacian is decomposed into blocks of marked and unmarked
    pixels::

        L = M B.T
            B A

    with first indices corresponding to marked pixels, and then to unmarked
    pixels, minimizing x.T L x for one phase amount to solving::

        A x = - B x_m

    where x_m = 1 on markers of the given phase, and 0 on other markers.
    This linear system is solved in the algorithm using a direct method for
    small images, and an iterative method for larger images.

    """
    if (labels != 0).all():
        warnings.warn(
            "Random walker only segments unlabeled areas, where "
            "labels == 0. No zero valued areas in labels were "
            "found. Returning provided labels."
        )
        out_labels = labels
        return out_labels

    # We take multichannel as always False since we are not strictly using
    # for image processing as such with RGB values.
    multichannel = False
    if not multichannel:
        if data.ndim < 2 or data.ndim > 3:
            raise ValueError("For non-multichannel input, data must be of " "dimension 2 or 3.")
        dims = data.shape  # To reshape final labeled result
        data = np.atleast_3d(as_float_array(data))[..., np.newaxis]

    # Spacing kwarg checks
    if spacing is None:
        spacing = np.asarray((1.0,) * 3)
    elif len(spacing) == len(dims):
        if len(spacing) == 2:  # Need a dummy spacing for singleton 3rd dim
            spacing = np.r_[spacing, 1.0]
        else:  # Convert to array
            spacing = np.asarray(spacing)
    else:
        raise ValueError(
            "Input argument `spacing` incorrect, should be an " "iterable with one number per spatial dimension."
        )

    if copy:
        labels = np.copy(labels)
    label_values = np.unique(labels)

    # Reorder label values to have consecutive integers (no gaps)
    if np.any(np.diff(label_values) != 1):
        mask = labels >= 0
        labels[mask] = np.searchsorted(np.unique(labels[mask]), labels[mask])[0].astype(labels.dtype)
    labels = labels.astype(np.int32)

    # If the array has pruned zones, be sure that no isolated pixels
    # exist between pruned zones (they could not be determined)
    if np.any(labels < 0):
        filled = ndi.binary_propagation(labels > 0, mask=labels >= 0)
        labels[np.logical_and(np.logical_not(filled), labels == 0)] = -1
        del filled
    labels = np.atleast_3d(labels)
    if np.any(labels < 0):
        lap_sparse = _build_laplacian(data, spacing, mask=labels >= 0, beta=beta)
    else:
        lap_sparse = _build_laplacian(data, spacing, beta=beta)

    lap_sparse, B = _buildAB(lap_sparse, labels)

    # We solve the linear system
    # lap_sparse X = B
    # where X[i, j] is the probability that a marker of label i arrives
    # first at pixel j by anisotropic diffusion.
    X = _solve_cg(lap_sparse, B, tol=tol)

    # Clean up results
    X = _clean_labels_ar(X + 1, labels).reshape(dims)
    return X