示例#1
0
def flood_rgb(image, starting_coord):
    image = image.copy()
    width = len(image)
    height = len(image[0])
    # Sadly, I need to use this 'alternate color' approach because I can't get flood working with an RGB image, so I need to make several calls to flood on each color channel, using
    # either black or white as an invalidation marker (white if the actual sample colour is black, else black).
    alternate_col = [1, 1, 1] if (image[starting_coord[0]][starting_coord[1]]
                                  == [0, 0, 0]).all() else [0, 0, 0]

    r_flood = flood(image, (starting_coord[0], starting_coord[1], 0),
                    connectivity=1)
    for x in range(width):
        for y in range(height):
            if not r_flood[x, y, 0]:
                image[x, y] = alternate_col
    g_flood = flood(image, (starting_coord[0], starting_coord[1], 1),
                    connectivity=1)
    for x in range(width):
        for y in range(height):
            if not g_flood[x, y, 1]:
                image[x, y] = alternate_col
    b_flood = flood(image, (starting_coord[0], starting_coord[1], 2),
                    connectivity=1)

    all_flood = numpy.empty([width, height], bool)

    for x in arange(width):
        for y in arange(height):
            all_flood[x][y] = r_flood[x, y, 0] and g_flood[x, y,
                                                           1] and b_flood[x, y,
                                                                          2]

    return all_flood
def difference_area_perimeters(base_propagation, perimeter1_cells,
                               perimeter2_cells, flood_initial_cell):
    gd1 = np.zeros(base_propagation.prop_data.data.shape)
    gd2 = np.zeros(base_propagation.prop_data.data.shape)
    for cell, time in perimeter1_cells.items():
        gd1.data[cell] = 1
    for cell, time in perimeter2_cells.items():
        gd2.data[cell] = 1
    flood_initial_cell = (flood_initial_cell[1],
                          base_propagation.prop_data.data.shape[0] -
                          flood_initial_cell[0])
    surface1 = flood(gd1, flood_initial_cell, connectivity=1)
    surface2 = flood(gd2, flood_initial_cell, connectivity=1)
    area1 = np.count_nonzero(
        surface1
    ) * base_propagation.prop_data.cell_width * base_propagation.prop_data.cell_height
    area2 = np.count_nonzero(
        surface2
    ) * base_propagation.prop_data.cell_width * base_propagation.prop_data.cell_height
    difference_surface = flood(gd1, flood_initial_cell,
                               connectivity=1) ^ flood(
                                   gd2, flood_initial_cell, connectivity=1)
    difference_area = np.count_nonzero(
        difference_surface
    ) * base_propagation.prop_data.cell_width * base_propagation.prop_data.cell_height
    return difference_surface, difference_area, area1, area2
示例#3
0
    def memb_mask(self, frame, roi_size=10):
        """ Membrane region detection.
        Outside edge - >= 2sd noise
        Inside edge - >= cytoplasm mean intensity

       img - imput z-stack frame;
       roi_center - list of int [x, y], coordinates of center of the cytoplasmic ROI for cytoplasm mean intensity calculation;
       roi_size - int, cytoplasmic ROI side size in px (ROI is a square area);
       noise_size - int, size in px of region for noise sd calculation (square area with start in 0,0 coordinates);
       sd_low - float, hysteresis algorithm lower threshold for outside cell edge detection,
                > 2sd of noise (percentage of maximum frame intensity);
       mean_low - float, hysteresis algorithm lower threshold for inside cell edge detection,
                > cytoplasmic ROI mean intensity (percentage of maximum frame intensity);
       gen_high - float,  general upper threshold for hysteresis algorithm (percentage of maximum frame intensity);
       sigma - int, sd for Gaussian filter.

        """
        # THIS IS TEMPORARY METHOD, FOR ONE CELL AT IMAGE ONLY!
        sd_mask, frame_sd = self.__create_sd_mask(frame)
        roi_mask, frame_roi = self.__create_roi_mask(frame)
        logging.info(
            f'Noise SD={round(frame_sd, 3)}, ROI mean intensity={round(frame_roi, 3)}\n'
        )

        # filling external space and create cytoplasmic mask
        cytoplasm_mask = roi_mask + segmentation.flood(roi_mask, (0, 0))
        if np.all(cytoplasm_mask):
            logging.fatal(
                'Cytoplasm mask is NOT closed, CAN`T create correct membrane mask!'
            )

        membrane_mask = ma.masked_where(~cytoplasm_mask, sd_mask)

        return [sd_mask, roi_mask, cytoplasm_mask, membrane_mask]
def fit_gaussian_on_histogram_peak(x: "np.ndarray[float]",
                                   y: "np.ndarray[float]", peak_idx: int):
    """
    procedure of fitting scaled gaussian with least-squares optimizer.
    :param peak_idx: index of y near the peak that is being interpolated.
    """
    # get init estimates
    a_init = y[peak_idx]
    mu_init = x[peak_idx]
    gthm = y > (a_init / 2)  # gthm -- greater than half maximum
    gthm = np.where(
        sks.flood(gthm.astype(int),
                  peak_idx))[0]  # for some reason does not work with bools
    min_hm_x, max_hm_x = x[gthm[[0, -1]]]
    sigma_init = (
        max_hm_x - min_hm_x
    ) / 2.355  # https://en.wikipedia.org/wiki/Full_width_at_half_maximum
    init_params = np.array([a_init, mu_init, sigma_init])
    # select 2*sigma range
    idx = np.where((x > mu_init - sigma_init * 2)
                   & (x < mu_init + sigma_init * 2))
    x = x[idx]
    y = y[idx]
    # fit
    err = lambda params, x, y: y - gaussian(x, *params)
    fit_params, _ = sco.leastsq(err, init_params, args=(x, y))
    return fit_params
示例#5
0
    def flood_remove_region(self, position, tolerance):
        """
        Remove from the current mask a flood region at the given position with
        the given tolerance.

        Args:
            position: The position to start the flood fill (x, y)
            tolerance: The tolerance for pixels to be included

        Returns:
            None

        Postconditions:
            The _mask will be updated with the new region
        """
        from skimage.segmentation import flood

        position = int(position[0]), int(position[1])

        # If we are still editing the tolerance, we need to go back to the old
        # mask.
        if position == self._old_flood_remove_position:
            self.mask = np.copy(self._old_mask)
        else:
            self._old_mask = np.copy(self._mask)

        remove_mask = flood(self._patch, position, tolerance=tolerance)

        self._mask[remove_mask] = 0

        self._overlay_mask()

        self._old_flood_remove_tolerance = tolerance
        self._old_flood_remove_position = position
示例#6
0
def seed_fill_img(neuron_img: np.ndarray, clicks: List[tuple]):
    """Using specified seed points, create a filter with a flood fill style
    
    Arguments:
        neuron_mask {np.ndarray} -- Image of the neuron. Single channel, so shape is (y, x)
        clicks {List[tuple]} -- All clicks in the form (y, x, sigma)

    Raises:
        TypeError: Raised when neuron_img is not two-dimensional (only a single channel )
    
    Returns:
        np.ndarray -- Combined mask of clicked regions
    """
    if not len(neuron_img.shape) == 2:
        raise TypeError(
            f"neuron_img has to be two-dimensional, passed shape is {neuron_img.shape}"
        )
    master_mask = np.zeros_like(neuron_img).astype(np.int)

    for click in clicks:
        tmp_mask = neuron_img > click[3] * neuron_img.std()
        # at the time of writing flood needs floats to be float64
        tmp_mask = flood(tmp_mask.astype(np.float64),
                         (int(click[0] + 0.5), int(click[1] + 0.5)))
        master_mask[tmp_mask] = click[2]

    return master_mask
示例#7
0
    def flood(self, e):
        image = self.pixmap().toImage()
        b = image.bits()
        b.setsize(512 * 512 * 4)
        arr = np.frombuffer(b, np.uint8).reshape((512, 512, 4))
        arr = arr.astype(np.int32)
        arr = np.flip(arr, axis=2)

        i = self.color_index + 1
        arr_test = arr[:,:,i]-((arr[:,:,1]+ arr[:,:,2]+ arr[:,:,3])/3)
        #arr test is not greyscale
        
        i = 2 - self.color_index
        #painted_arr is BGRA
        painted_arr = np.zeros_like(arr,dtype=np.uint8)
        painted_arr[:,:,i][arr_test!=0] = 255
        #this makes the drawn images the same as pen color

        painted_arr[:,:,i] = 255*flood(painted_arr[:,:,i],(e.y(),e.x()))
        #sets alpha from ith channel
        painted_arr[:,:,3] = painted_arr[:,:,i]

        #BGRA
        qi = QImage(painted_arr.data, painted_arr.shape[1], painted_arr.shape[0], 4*painted_arr.shape[1], QImage.Format_ARGB32_Premultiplied)
        pixmap = QPixmap(qi)
        
        painter = QPainter(self.pixmap())
        painter.setOpacity(0.5)

        painter.drawPixmap(0,0,pixmap)
        painter.end()
        self.update()
        
        #self.array saves RGB values
        self.array += np.flip(painted_arr[:,:,:3], axis=2)
def fd_extract(X_train, n_features=3, tolerance=0.2):
    print('Fourier Descriptor based extraction has been started...')

    descriptors = []
    for x in X_train:
        img = rgb2gray(x['bbox_img'])

        w_h, h_h = img.shape[0] // 2, img.shape[1] // 2

        res = flood(img, (w_h, h_h), tolerance=tolerance)
        cont = find_contours(res, 0)

        if len(cont) > 0:
            sing_cont = [np.complex(n[0], n[1]) for n in cont[0]]
            fd = fft(sing_cont)

            if len(fd) >= n_features + 2:
                fd_ref = abs(fd[1])
                fd_inv = []
                for j in range(n_features):
                    fd_inv.append(abs(fd[j + 2]) / fd_ref)
                descriptors.append(fd_inv)
            else:
                descriptors.append([32.1] * n_features)
        else:
            descriptors.append([32.1] * n_features)

    print('Fourier Descriptor based extraction is done')
    return np.matrix(descriptors)
示例#9
0
def get_provinces(province_mask, min_province_pixels, connectivity=1):
    province_masks = []
    province_origins = []
    undetermined_mask = numpy.zeros(province_mask.shape, dtype=bool)
    undetermined_pixels_found = False

    for x in range(province_mask.shape[0]):
        for y in range(province_mask.shape[1]):
            if province_mask[x][y] and ~undetermined_mask[x][y]:
                flooded_pixels = flood(province_mask, (x, y),
                                       connectivity=connectivity)

                if numpy.count_nonzero(flooded_pixels) < min_province_pixels:
                    undetermined_pixels_found = True
                    # If the discovered area was too small, mark it on the undetermined map (this will be re-evaluated later, allowing for diagonal pixel connections next time).
                    undetermined_mask = numpy.logical_or(
                        undetermined_mask, flooded_pixels)
                else:
                    # Remove the mask of the discovered province (found via flooding) from the province_mask, preventing it from being re-added by future iterations.
                    province_mask = numpy.logical_and(province_mask,
                                                      ~flooded_pixels)
                    province_masks.append(flooded_pixels)
                    province_origins.append([x, y])

    if not undetermined_pixels_found:
        undetermined_mask = None

    return province_masks, province_origins, undetermined_mask
示例#10
0
def get_state_mask(state_guide, state_color):
    # Get a mask of all pixels of the border key color.
    # Running two_d_array == value produces a 'mask' where only individual pixels are compared, but we want to know about cases where all three pixels are equal.
    # logical_and does this sort of thing, apparently.
    border_mask = logical_and.reduce(state_guide == state_color, axis=-1)

    x_min, y_min, x_max, y_max = find_bounds(border_mask)
    guide_view = state_guide[y_min:y_max + 1, x_min:x_max + 1]

    # Crop the border_mask too.
    border_mask = border_mask[y_min:y_max + 1, x_min:x_max + 1]

    # Create a copy of the border mask with a new layer of false pixels all around the edge.
    state_mask = border_mask.copy()
    state_mask = numpy.insert(state_mask, 0, False, axis=0)
    state_mask = numpy.insert(state_mask, 0, False, axis=1)
    state_mask = numpy.insert(state_mask, state_mask.shape[0], False, axis=0)
    state_mask = numpy.insert(state_mask, state_mask.shape[1], False, axis=1)

    # Get a mask of all pixels outside the state's borders, by performing a flood from the top-left pixel on the expanded mask we've made.
    # Then invert the mask. All true values on the mask signify a point on or within the state's borders.
    state_mask = ~flood(state_mask, (0, 0), connectivity=1)

    # Crop the state_mask back to the bounds of the relevant pixels.
    state_mask = numpy.delete(state_mask, state_mask.shape[0] - 1, 0)
    state_mask = numpy.delete(state_mask, state_mask.shape[1] - 1, 1)
    state_mask = numpy.delete(state_mask, 0, 0)
    state_mask = numpy.delete(state_mask, 0, 1)

    state_mask = state_mask & logical_or.reduce(guide_view != ignore_col,
                                                axis=-1)

    return state_mask, border_mask, x_min, y_min, x_max, y_max
示例#11
0
def hystMemb(img,
             roi_center,
             roi_size=30,
             noise_size=20,
             low_diff=40,
             gen_high=0.8,
             sigma=3):
    """ Function for membrane region detection with hysteresis threshold algorithm.
    Outdide edge - >= 2sd noise
    Inside edge - >= cytoplasm mean intensity

    Require hystLow function for lower hysteresis threshold calculations.

    img - imput z-stack frame;
    roi_center - list of int [x, y], coordinates of center of the cytoplasmic ROI for cytoplasm mean intensity calculation;
    roi_size - int, cutoplasmic ROI side size in px (ROI is a square area);
    noise_size - int, size in px of region for noise sd calculation (square area witf start in 0,0 coordinates);
    sd_low - float, hysteresis algorithm lower threshold for outside cell edge detection,
             > 2sd of noise (percentage of maximum frame intensity);
    mean_low - float, hysteresis algorithm lower threshold for inside cell edge detection,
             > cytoplasmic ROI mean intensity (percentage of maximum frame intensity);
    gen_high - float,  general upper threshold for hysteresis algorithm (percentage of maximum frame intensity);
    sigma - int, sd for gaussian filter.

    Returts membrane region boolean mask for input frame.

    """
    img = backCon(img, dim=2)
    img_gauss = filters.gaussian(img, sigma=sigma)

    noise_sd = np.std(img[:noise_size, :noise_size])
    logging.info('Frame noise SD={:.3f}'.format(noise_sd))

    roi_mean = np.mean(img[roi_center[0] - roi_size//2:roi_center[0] + roi_size//2, \
                           roi_center[1] - roi_size//2:roi_center[1] + roi_size//2])  # cutoplasmic ROI mean celculation
    logging.info('Cytoplasm ROI mean intensity {:.3f}'.format(roi_mean))

    low_val = hystLow(img,
                      img_gauss,
                      sd=noise_sd,
                      mean=roi_mean,
                      diff=low_diff,
                      gen_high=gen_high)

    mask_2sd = filters.apply_hysteresis_threshold(
        img_gauss,
        low=low_val['2sd'] * np.max(img_gauss),
        high=gen_high * np.max(img_gauss))
    mask_roi_mean = filters.apply_hysteresis_threshold(
        img_gauss,
        low=low_val['mean'] * np.max(img_gauss),
        high=gen_high * np.max(img_gauss))
    # filling external space and create cytoplasmic mask
    mask_cytoplasm = mask_roi_mean + segmentation.flood(mask_roi_mean, (0, 0))

    return mask_2sd, mask_roi_mean, ma.masked_where(~mask_cytoplasm, mask_2sd)
示例#12
0
    def _make_cell_map(self):
        #### Get the cell map according to this ####
        #
        # Pre: Requires both a Nucleus and Membrane map
        # Post: Sets a 'cell_map' in the 'segmentation_images'

        segmentation_images = self.get_data('segmentation_images').set_index(
            'segmentation_label')
        nucid = segmentation_images.loc['Nucleus', 'image_id']
        memid = segmentation_images.loc['Membrane', 'image_id']
        nuc = self.get_image(nucid)
        mem = self.get_image(memid)
        mids = map_image_ids(mem)
        coords = list(zip(mids['x'], mids['y']))
        center = median_id_coordinates(nuc, coords)
        im = mem.copy()
        im2 = mem.copy()
        orig = pd.DataFrame(mem.copy())

        for i, cell_index in enumerate(center.index):
            coord = (center.loc[cell_index]['x'], center.loc[cell_index]['y'])
            mask = flood(im2, (coord[1], coord[0]),
                         connectivity=1,
                         tolerance=0)
            if mask.sum().sum() >= 2000: continue
            im2[mask] = cell_index

        v = map_image_ids(im2, remove_zero=False)
        zeros = v.loc[v['id'] == 0]
        zeros = list(zip(zeros['x'], zeros['y']))
        start = v.loc[v['id'] != 0]
        start = list(zip(start['x'], start['y']))

        c1 = map_image_ids(im2).reset_index().rename(
            columns={'id': 'cell_index_1'})
        c2 = map_image_ids(im2).reset_index().rename(
            columns={'id': 'cell_index_2'})
        overlap = c1.merge(c2, on=['x',
                                   'y']).query('cell_index_1!=cell_index_2')
        if overlap.shape[0] > 0: raise ValueError("need to handle overlap")

        #print("DONE FILLING IN")
        cell_map_id = uuid4().hex
        self._images[cell_map_id] = im2.copy()
        increment = self.get_data('segmentation_images').index.max() + 1
        extra = pd.DataFrame(
            pd.Series(
                dict({
                    'db_id': increment,
                    'segmentation_label': 'cell_map',
                    'image_id': cell_map_id
                }))).T
        extra = pd.concat(
            [self.get_data('segmentation_images'),
             extra.set_index('db_id')])
        self.set_data('segmentation_images', extra)
def make_head_mask(image: "np.ndarray[float]",
                   brain_mask: "np.ndarray[bool]") -> "np.ndarray[bool]":
    """
    applies heuristic (thresholding and flooding) to obtain a mask of an animal head
    """
    x = skf.gaussian(image, sigma=2, truncate=2)
    x = np.where(x < 0.5, 1, 0)
    c = center_of_binary_image(brain_mask)
    mask = sks.flood(x, c)
    return mask & ~brain_mask
示例#14
0
def black_cut_fun(img_rgb):

    h,w,c = img_rgb.shape
    corner_pixel = np.mean(img_rgb[-1,-1]).astype(np.int)
    img_zero = corner_pixel * np.ones((h+80,w+80,c), dtype=img_rgb.dtype)
    img_zero[40:-40,40:-40,:] = img_rgb
    img_rgb = img_zero

    img_gray = (rgb2gray(img_rgb) * 255).astype(np.uint8)*1.5
    img_shape = img_gray.shape

    marker_set = ((5, 5), (5, img_shape[1] - 5), (img_shape[0] - 5, 5), (img_shape[0] - 5, img_shape[1] - 5))
    marker_color_set = []
    for marker_coords in marker_set:
        marker_color_set.append(img_gray[(marker_coords[0], marker_coords[1])])
    marker_color_set_std = np.std(marker_color_set)
    marker_color_std_tol = 15
    if marker_color_set_std >= marker_color_std_tol:
        raise Exception("CHANGE BORDER COLOR MODULE: failed to get consistent border color based on four markers.")

    border_mask = np.zeros(img_gray.shape, np.uint8)
    tol_min = 10
    for marker_coords in marker_set:
        curr_mask = flood(img_gray, marker_coords, tolerance = 5)
        border_mask = np.maximum(curr_mask, border_mask)
    fg_mask = 1 - border_mask
    fg_label = label(fg_mask)
    fg_prop = regionprops(fg_label)
    fg_prop.sort(key=lambda x:x.area,reverse=True)
    fg_mask = (fg_label == fg_prop[0].label)

    border_smoothing_size = 5
    disk_ele = disk(radius = border_smoothing_size)
    fg_mask = binary_closing(fg_mask, disk_ele)
    tmp_mask = 1 - fg_mask
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (50,  50))

    center, major_axis_length=_get_center_by_edge(tmp_mask)
    radius=_get_radius_by_mask_center(tmp_mask,center)
    h,w = img_shape
    s_h = max(0,int(center[0] - radius))
    s_w = max(0, int(center[1] - radius))
    bbox = (s_h, s_w, min(h-s_h,2 * radius), min(w-s_w,2 * radius))
    circle_mask=_get_circle_by_center_bbox(img_shape,(h//2,w//2),bbox,radius)

    if np.sum(fg_mask) > np.sum(circle_mask):
        result_mask = fg_mask
    else:
        result_mask = circle_mask
    mask = result_mask

    img = img_rgb * mask[:,:,np.newaxis]
    img = img[np.ix_(mask.any(1), mask.any(0))]
    return  radius , img
示例#15
0
文件: utils.py 项目: laitalaj/cvpce
def build_mask(img, tolerance=1e-2):
    _, h, w = img.shape
    corners = [(0, 0), (w - 1, 0), (0, h - 1), (w - 1, h - 1)]
    gray_image = ttf.rgb_to_grayscale(img).numpy()
    white_corners = [(x, y) for x, y in corners
                     if gray_image[0, y, x] >= 1 - tolerance]
    sobel_image = sobel(gray_image)[0]
    mask = np.full((h, w), False)
    for x, y in white_corners:
        if mask[y, x]: continue
        cfill = flood(sobel_image, (y, x), tolerance=tolerance)
        mask = mask | cfill
    return torch.tensor(mask)
 def onclick(self, event):
     """
     handle clicking to remove already added stuff
     """
     if event.button == 1:
         if event.xdata is not None and not self.lasso.active:
             # transpose x and y bc imshow transposes
             self.indices = flood(
                 self.class_mask,
                 (np.int(event.ydata), np.int(event.xdata)))
             self.updateArray()
     elif event.button == 3:
         self.panhandler.press(event)
示例#17
0
def divide_figures(pic):
    import numpy as np
    from skimage.segmentation import flood, flood_fill

    coords = np.array(np.where(pic != 0))
    ans = []
    while coords.shape[1] != 0:
        seed_point = tuple(coords[:, 0])
        ans.append(flood(pic, seed_point))
        pic = flood_fill(pic, seed_point, 0)

        coords = np.array(np.where(pic != 0))

    return ans
示例#18
0
    def flood(self, e):
        image = self.pixmap().toImage()
        b = image.bits()
        b.setsize(self.canvas_size * self.canvas_size * 4)
        arr = np.frombuffer(b, np.uint8).reshape(
            (self.canvas_size, self.canvas_size, 4))

        OGimage = self.OGpixmap.toImage()
        b = OGimage.bits()
        b.setsize(self.canvas_size * self.canvas_size * 4)
        OGim = np.frombuffer(b, np.uint8).reshape(
            (self.canvas_size, self.canvas_size, 4))
        OGim = np.flip(OGim, axis=2)

        arr = arr.astype(np.int32)
        arr = np.flip(arr, axis=2)

        arr_test = np.zeros_like(arr)
        arr_test[arr != OGim] = arr[arr != OGim]
        flat_arr = np.mean(arr_test[:, :, 1:], axis=2)
        flooded = flood(flat_arr, (e.y(), e.x()))

        color = self.colors[self.color_index]
        rgb = [int(color[3:5], 16), int(color[5:7], 16), int(color[7:], 16)]

        #paint_arr is ARGB
        paint_arr = np.zeros_like(arr, dtype=np.uint8)
        paint_arr[:, :, 0] = (flooded) * 255
        #sets alpha
        paint_arr[flooded, 1:] = rgb
        #fills wil pen colour

        #BGRA
        paint_arr = np.flip(paint_arr, axis=2).copy()

        qi = QImage(paint_arr.data, paint_arr.shape[1], paint_arr.shape[0],
                    4 * paint_arr.shape[1], QImage.Format_ARGB32_Premultiplied)
        pixmap = QPixmap(qi)

        painter = QPainter(self.pixmap())
        painter.setOpacity(0.5)
        painter.drawPixmap(0, 0, pixmap)
        painter.end()
        self.update()

        #self.array saves RGB values
        self.array += np.flip(paint_arr[:, :, :3], axis=2)
示例#19
0
def paint():
    """Return the picture with wall color changed."""

    file = request.files['image']  # Get image from request

    coord_x = int(request.form.get('coord_x'))  # Get X coordinate from request
    coord_y = int(request.form.get('coord_y'))  # Get Y coordinate from request

    hex = request.form.get('color')  # Get color from request
    hue, sat, val = hex_to_hsv(hex)  # Convert colot to HSV code

    img = io.imread(file)  # Open image

    img_hsv = color.rgb2hsv(img)  # Convert color channels
    img_gray = color.rgb2gray(img)  # Convert color channels

    # Sobel edge detection
    edge_sobel = sobel(img_gray)

    # Felzenszwalb’s image segmentation
    segments_fz = felzenszwalb(edge_sobel, scale=100, sigma=1, min_size=150)

    # Create a mask of flooded pixels
    mask = flood(segments_fz, (coord_y, coord_x), tolerance=0.5)

    # Set pixels of mask to new value for hue channel
    img_hsv[mask, 0] = hue

    # Set pixels of mask to new value for saturation channel
    img_hsv[mask, 1] = sat

    # Set pixels of mask to new value for value/brightness channel
    img_hsv[mask, 2] = val

    # Convert color channels
    img_final = color.hsv2rgb(img_hsv)

    # Create a byte object to save the image
    file_object = BytesIO()

    # Save image on the byte object
    io.imsave(file_object, img_final, plugin='pil')
    file_object.seek(0)

    return send_file(file_object, mimetype='image/jpeg')
    def check_if_contour_is_closed(self):

        coords = self.__hook_to_pixel()

        if not coords:
            return False

        object_area = self.__enlarge_window(coords[0], coords[1])

        original_num = self.__count_white_pixels_in_given_area(object_area[0],
                                                               object_area[1],
                                                               object_area[2],
                                                               object_area[3],
                                                               True)

        self.__img = flood(self.__img, (0, 0), connectivity=0)

        if self.__count_white_pixels_in_given_area(object_area[0], object_area[1], object_area[2], object_area[3],
                                                   False) > original_num:
            return True

        return False
示例#21
0
def get_fiber_track(
    registered_atlas_path,
    source_image_path,
    seed_point,
    output_path=None,
    normalising_factor=4,
    erosion_diameter=5,
):
    """
    gets segmentation image of optical fibers using the background channel
    and a seed-point, tested on 200um and 400um fibers

    :param erosion_selem:
    :param normalising_factor:
    :param output_path:
    :param registered_atlas_path:
    :param source_image_path:
    :param seed_point:
    :return:
    """
    brain_mask = brainio.load_any(str(registered_atlas_path)) != 0
    brain = brainio.load_any(str(source_image_path))

    brain_median_filtered = median(brain)
    otsu_threshold = threshold_multiotsu(brain_median_filtered)[0]
    brain_segmentation = (brain_median_filtered <
                          otsu_threshold / normalising_factor) * brain_mask

    segmentation_eroded = binary_erosion(brain_segmentation,
                                         selem=ball(erosion_diameter))
    segmentation_eroded_dilated = binary_dilation(segmentation_eroded)
    fiber_track_image = flood(segmentation_eroded_dilated.astype(np.int16),
                              seed_point)

    if output_path is not None:
        save_brain(fiber_track_image, source_image_path, output_path)
    else:
        return fiber_track_image
示例#22
0
def main():

    image_rgb = cv2.imread("1-039.jpg")
    image = cv2.cvtColor(image_rgb, cv2.COLOR_BGR2GRAY)
    '''
    rows = image.shape[0]
    cols = image.shape[1]
    print("length: ", len(image))
    print("Dimensions: ", image.shape)
    print("rows,cols: ", rows, cols)
    '''
    astranaut = data.astronaut()
    print(astranaut.shape)
    #image_show(astranaut)
    astranaut_gray = cv2.cvtColor(astranaut, cv2.COLOR_BGR2GRAY)
    #image_show(astranaut_gray)
    seed_point = (255, 255)
    flood_mask = seg.flood(image, seed_point, tolerance=0.1)
    fig, ax = image_show(image)
    ax.imshow(flood_mask, alpha=0.3)
    ax.plot(255, 255, 'bo')

    plt.show()
示例#23
0
def reconstruction(imagePath, outputPath):
    image = io.imread(imagePath)

    if (isGrayscale(imagePath)):
        image = gray2rgb(image)
    elif (isNotHsv(imagePath)):
        image = rgb2hsv(image)
    img_hsv = image
    img_hsv_copy = np.copy(img_hsv)

    imgSize = (image.shape)
    w = min(imgSize[0], 200)
    h = min(imgSize[1], 160)
    # flood function returns a mask of flooded pixels
    mask = flood(img_hsv[..., 0], (w - 1, h - 1), tolerance=0.016)
    # Set pixels of mask to new value for hue channel
    img_hsv[mask, 0] = 0.5
    # Post-processing in order to improve the result
    # Remove white pixels from flag, using saturation channel
    mask_postprocessed = np.logical_and(mask, img_hsv_copy[..., 1] > 0.4)
    # Remove thin structures with binary opening
    # mask_postprocessed = binary_opening(mask_postprocessed,
    #                                                np.ones((3, 3)))
    # Fill small holes with binary closing
    mask_postprocessed = binary_opening(mask_postprocessed, disk(20))
    img_hsv_copy[mask_postprocessed, 0] = 0.5
    # img_hsv_copy_uint8 = img_as_ubyte(img_hsv_copy)
    #is_hsv
    if (len(img_hsv_copy.shape) == 3 and img_hsv_copy.shape[2] == 3):
        output = hsv2rgb(img_hsv_copy)
    else:
        output = img_hsv_copy
    output_uint8 = img_as_ubyte(output)
    imsave('' + outputPath, output_uint8)
    # imsave('/home/marekk/workspace/tmp/1234.png', output_uint8)

    output_uint8
示例#24
0
    def createCrack(self, input_arr, x, y, tolerance, preview=True):
        """
        Given a inner blob point (x,y), the function use it as a seed for a paint butcket tool and create
        a correspondent blob hole
        """

        x_crop = x - self.bbox[1]
        y_crop = y - self.bbox[0]

        input_arr = gaussian(input_arr, 2)
        # input_arr = segmentation.inverse_gaussian_gradient(input_arr, alpha=1, sigma=1)

        blob_mask = self.getMask()

        crack_mask = flood(input_arr, (int(y_crop), int(x_crop)),
                           tolerance=tolerance).astype(int)
        cracked_blob = np.logical_and((blob_mask > 0), (crack_mask < 1))
        cracked_blob = cracked_blob.astype(int)

        if preview:
            return cracked_blob
        else:
            self.updateUsingMask(self.bbox, cracked_blob)
            return cracked_blob
示例#25
0
def process(pts=(10, 10)):
    filled = np.ones((scr.shape[1], scr.shape[2]))
    nscr = scr.copy()
    # scr[line[np.newaxis,:,:].repeat(4,axis=0)<0.75]=-1
    for i in range(4):
        filled_img = flood(scr[i, :, :], pts, tolerance=0.15)
        filled[~filled_img] = 0
    plt.close(2)
    figi, axi = plt.subplots(figsize=(10, 8))

    rnd = np.random.randn(4) * 0.5
    for t in range(4):
        nscr[t][filled[:] == 1] = rnd[t]
    out = get_recons(nscr)
    # nimg = img.copy()
    nimg[filled[:] == 1] = out[filled[:] == 1]
    nimg[:] = nimg[:] * line[:]

    io.imsave('saved.png', nimg)

    axi.imshow(nimg, cmap=plt.cm.gray)
    axi.set_title('Edited')
    axi.axis('off')
    figi.show()
示例#26
0
edges = binary_dilation(dog > thr, disk(3))

#rec = dilation(img0, disk(3))
rec = img0.copy()

print("Erasing objects...")
edge_labels, num_labels = ndi.label(edges)
for lbl in tqdm(range(num_labels)):
    edge_mask = edge_labels == lbl + 1
    edge_max = rec[edge_mask].max()
    edge_min = rec[edge_mask].min()

    lower = (rec <= edge_min) | edge_mask

    seed_point = tuple(np.transpose(np.nonzero(edge_mask))[0])
    flooded = flood(img_as_ubyte(lower), seed_point)
    rec[flooded] = edge_max

objs = rec > img0
objs = binary_dilation(objs, disk(3))

fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True)

axes[0, 0].imshow(img, cmap="gray")
axes[0, 1].imshow(dog)
axes[0, 2].imshow(dog > thr)
rec_ax = axes[1, 0].imshow(rec, cmap="gray")
obj_ax = axes[1, 1].imshow(objs, cmap="gray")
# axes[1, 2].imshow(, cmap="gray")
示例#27
0
##############################################################################
# Flood as mask
# -------------
#
# A sister function, `flood`, is available which returns a mask identifying
# the flood rather than modifying the image itself.  This is useful for
# segmentation purposes and more advanced analysis pipelines.
#
# Here we segment the nose of a cat.  However, multi-channel images are not
# supported by flood[_fill].  Instead we Sobel filter the red channel to
# enhance edges, then flood the nose with a tolerance.

cat = data.chelsea()
cat_sobel = filters.sobel(cat[..., 0])
cat_nose = flood(cat_sobel, (240, 265), tolerance=0.03)

fig, ax = plt.subplots(nrows=3, figsize=(10, 20))

ax[0].imshow(cat)
ax[0].set_title('Original')
ax[0].axis('off')

ax[1].imshow(cat_sobel)
ax[1].set_title('Sobel filtered')
ax[1].axis('off')

ax[2].imshow(cat)
ax[2].imshow(cat_nose, cmap=plt.cm.gray, alpha=0.3)
ax[2].plot(265, 240, 'wo')  # seed point
ax[2].set_title('Nose segmented with `flood`')
示例#28
0
            np.bincount(skinRegionYCrCb.flat)[1:]) + 1

        # get a starting point
        points_x, points_y = np.where(skinRegionYCrCb == 1)
        selected_x = points_x[np.argmax(points_x)]
        selected_y = points_y[np.argmax(points_x)]

        # flooding
        image = image.astype('int32')
        cat_sobel_x = filters.sobel(image, axis=0).astype(np.float32)
        cat_sobel_y = filters.sobel(image, axis=1).astype(np.float32)
        cat_sobel = cat_sobel_x * cat_sobel_x + cat_sobel_y * cat_sobel_y
        cat_sobel *= 255.0 / np.max(cat_sobel)
        cat_sobel = (cat_sobel[:, :, 0] + cat_sobel[:, :, 1] +
                     cat_sobel[:, :, 2]) / 3.0
        cat_nose = flood(cat_sobel, (selected_x - 8, selected_y),
                         tolerance=0.2)
        # postprocessing
        cat_nose = cat_nose.astype(np.uint8)
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
        cat_nose = cv2.erode(cat_nose, kernel, iterations=2)
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (4, 4))
        cat_nose = cv2.dilate(cat_nose, kernel, iterations=2)
        # cat_nose = cv2.GaussianBlur(cat_nose, (3, 3), 0)

        cat_nose = cat_nose.astype(np.int32)
        cat_nose = cat_nose * 255
        #

        cv2.imwrite(
            osp.join(OUTPUT_PATH,
                     '{}_{}_flood_mask.jpg'.format(item.split('.')[0],
示例#29
0
def label_images(metadata,settings):
    """
    Load satellite images and interactively label different classes (hard-coded)

    KV WRL 2019

    Arguments:
    -----------
    metadata: dict
        contains all the information about the satellite images that were downloaded
    settings: dict with the following keys
        'cloud_thresh': float
            value between 0 and 1 indicating the maximum cloud fraction in 
            the cropped image that is accepted    
        'cloud_mask_issue': boolean
            True if there is an issue with the cloud mask and sand pixels
            are erroneously being masked on the images
        'labels': dict
            list of label names (key) and label numbers (value) for each class
        'flood_fill': boolean
            True to use the flood_fill functionality when labelling sand pixels
        'tolerance': float
            tolerance value for flood fill when labelling the sand pixels
        'filepath_train': str
            directory in which to save the labelled data
        'inputs': dict
            input parameters (sitename, filepath, polygon, dates, sat_list)
                
    Returns:
    -----------
    Stores the labelled data in the specified directory

    """
    
    filepath_train = settings['filepath_train']
    # initialize figure
    fig,ax = plt.subplots(1,1,figsize=[17,10], tight_layout=True,sharex=True,
                          sharey=True)
    mng = plt.get_current_fig_manager()                                         
    mng.window.showMaximized()

    # loop through satellites
    for satname in metadata.keys():
        filepath = SDS_tools.get_filepath(settings['inputs'],satname)
        filenames = metadata[satname]['filenames']
        # loop through images
        for i in range(len(filenames)):
            # image filename
            fn = SDS_tools.get_filenames(filenames[i],filepath, satname)
            # read and preprocess image
            im_ms, georef, cloud_mask, im_extra, im_QA, im_nodata = SDS_preprocess.preprocess_single(fn, satname, settings['cloud_mask_issue'])

            # compute cloud_cover percentage (with no data pixels)
            cloud_cover_combined = np.divide(sum(sum(cloud_mask.astype(int))),
                                    (cloud_mask.shape[0]*cloud_mask.shape[1]))
            if cloud_cover_combined > 0.99: # if 99% of cloudy pixels in image skip
                continue

            # remove no data pixels from the cloud mask (for example L7 bands of no data should not be accounted for)
            cloud_mask_adv = np.logical_xor(cloud_mask, im_nodata)
            # compute updated cloud cover percentage (without no data pixels)
            cloud_cover = np.divide(sum(sum(cloud_mask_adv.astype(int))),
                                    (sum(sum((~im_nodata).astype(int)))))
            # skip image if cloud cover is above threshold
            if cloud_cover > settings['cloud_thresh'] or cloud_cover == 1:
                continue
            # get individual RGB image
            im_RGB = SDS_preprocess.rescale_image_intensity(im_ms[:,:,[2,1,0]], cloud_mask, 99.9)
            im_NDVI = SDS_tools.nd_index(im_ms[:,:,3], im_ms[:,:,2], cloud_mask)
            im_NDWI = SDS_tools.nd_index(im_ms[:,:,3], im_ms[:,:,1], cloud_mask)
            # initialise labels
            im_viz = im_RGB.copy()
            im_labels = np.zeros([im_RGB.shape[0],im_RGB.shape[1]])
            # show RGB image
            ax.axis('off')  
            ax.imshow(im_RGB)
            implot = ax.imshow(im_viz, alpha=0.6)            
            filename = filenames[i][:filenames[i].find('.')][:-4] 
            ax.set_title(filename)
           
            ##############################################################
            # select image to label
            ##############################################################           
            # set a key event to accept/reject the detections (see https://stackoverflow.com/a/15033071)
            # this variable needs to be immuatable so we can access it after the keypress event
            key_event = {}
            def press(event):
                # store what key was pressed in the dictionary
                key_event['pressed'] = event.key
            # let the user press a key, right arrow to keep the image, left arrow to skip it
            # to break the loop the user can press 'escape'
            while True:
                btn_keep = ax.text(1.1, 0.9, 'keep ⇨', size=12, ha="right", va="top",
                                    transform=ax.transAxes,
                                    bbox=dict(boxstyle="square", ec='k',fc='w'))
                btn_skip = ax.text(-0.1, 0.9, '⇦ skip', size=12, ha="left", va="top",
                                    transform=ax.transAxes,
                                    bbox=dict(boxstyle="square", ec='k',fc='w'))
                btn_esc = ax.text(0.5, 0, '<esc> to quit', size=12, ha="center", va="top",
                                    transform=ax.transAxes,
                                    bbox=dict(boxstyle="square", ec='k',fc='w'))
                fig.canvas.draw_idle()                         
                fig.canvas.mpl_connect('key_press_event', press)
                plt.waitforbuttonpress()
                # after button is pressed, remove the buttons
                btn_skip.remove()
                btn_keep.remove()
                btn_esc.remove()
                
                # keep/skip image according to the pressed key, 'escape' to break the loop
                if key_event.get('pressed') == 'right':
                    skip_image = False
                    break
                elif key_event.get('pressed') == 'left':
                    skip_image = True
                    break
                elif key_event.get('pressed') == 'escape':
                    plt.close()
                    raise StopIteration('User cancelled labelling images')
                else:
                    plt.waitforbuttonpress()
                    
            # if user decided to skip show the next image
            if skip_image:
                ax.clear()
                continue
            # otherwise label this image
            else:
                ##############################################################
                # digitize sandy pixels
                ##############################################################
                ax.set_title('Click on SAND pixels (flood fill activated, tolerance = %.2f)\nwhen finished press <Enter>'%settings['tolerance'])
                # create erase button, if you click there it delets the last selection
                btn_erase = ax.text(im_ms.shape[1], 0, 'Erase', size=20, ha='right', va='top',
                                    bbox=dict(boxstyle="square", ec='k',fc='w'))                
                fig.canvas.draw_idle()
                color_sand = settings['colors']['sand']
                sand_pixels = []
                while 1:
                    seed = ginput(n=1, timeout=0, show_clicks=True)
                    # if empty break the loop and go to next label
                    if len(seed) == 0:
                        break
                    else:
                        # round to pixel location
                        seed = np.round(seed[0]).astype(int)     
                    # if user clicks on erase, delete the last selection
                    if seed[0] > 0.95*im_ms.shape[1] and seed[1] < 0.05*im_ms.shape[0]:
                        if len(sand_pixels) > 0:
                            im_labels[sand_pixels[-1]] = 0
                            for k in range(im_viz.shape[2]):                              
                                im_viz[sand_pixels[-1],k] = im_RGB[sand_pixels[-1],k]
                            implot.set_data(im_viz)
                            fig.canvas.draw_idle() 
                            del sand_pixels[-1]
                            
                    # otherwise label the selected sand pixels
                    else:
                        # flood fill the NDVI and the NDWI
                        fill_NDVI = flood(im_NDVI, (seed[1],seed[0]), tolerance=settings['tolerance'])
                        fill_NDWI = flood(im_NDWI, (seed[1],seed[0]), tolerance=settings['tolerance'])
                        # compute the intersection of the two masks
                        fill_sand = np.logical_and(fill_NDVI, fill_NDWI)
                        im_labels[fill_sand] = settings['labels']['sand'] 
                        sand_pixels.append(fill_sand)
                        # show the labelled pixels
                        for k in range(im_viz.shape[2]):                              
                            im_viz[im_labels==settings['labels']['sand'],k] = color_sand[k]
                        implot.set_data(im_viz)
                        fig.canvas.draw_idle() 
                
                ##############################################################
                # digitize white-water pixels
                ##############################################################
                color_ww = settings['colors']['white-water']
                ax.set_title('Click on individual WHITE-WATER pixels (no flood fill)\nwhen finished press <Enter>')
                fig.canvas.draw_idle() 
                ww_pixels = []                        
                while 1:
                    seed = ginput(n=1, timeout=0, show_clicks=True)
                    # if empty break the loop and go to next label
                    if len(seed) == 0:
                        break
                    else:
                        # round to pixel location
                        seed = np.round(seed[0]).astype(int)     
                    # if user clicks on erase, delete the last labelled pixels
                    if seed[0] > 0.95*im_ms.shape[1] and seed[1] < 0.05*im_ms.shape[0]:
                        if len(ww_pixels) > 0:
                            im_labels[ww_pixels[-1][1],ww_pixels[-1][0]] = 0
                            for k in range(im_viz.shape[2]):
                                im_viz[ww_pixels[-1][1],ww_pixels[-1][0],k] = im_RGB[ww_pixels[-1][1],ww_pixels[-1][0],k]
                            implot.set_data(im_viz)
                            fig.canvas.draw_idle()
                            del ww_pixels[-1]
                    else:
                        im_labels[seed[1],seed[0]] = settings['labels']['white-water']  
                        for k in range(im_viz.shape[2]):                              
                            im_viz[seed[1],seed[0],k] = color_ww[k]
                        implot.set_data(im_viz)
                        fig.canvas.draw_idle()
                        ww_pixels.append(seed)
                        
                im_sand_ww = im_viz.copy()
                btn_erase.set(text='<Esc> to Erase', fontsize=12)
                
                ##############################################################
                # digitize water pixels (with lassos)
                ##############################################################
                color_water = settings['colors']['water']
                ax.set_title('Click and hold to draw lassos and select WATER pixels\nwhen finished press <Enter>')
                fig.canvas.draw_idle() 
                selector_water = SelectFromImage(ax, implot, color_water)
                key_event = {}
                while True:
                    fig.canvas.draw_idle()                         
                    fig.canvas.mpl_connect('key_press_event', press)
                    plt.waitforbuttonpress()
                    if key_event.get('pressed') == 'enter':
                        selector_water.disconnect()
                        break
                    elif key_event.get('pressed') == 'escape':
                        selector_water.array = im_sand_ww
                        implot.set_data(selector_water.array)
                        fig.canvas.draw_idle()                         
                        selector_water.implot = implot
                        selector_water.im_bool = np.zeros((selector_water.array.shape[0], selector_water.array.shape[1])) 
                        selector_water.ind=[]          
                # update im_viz and im_labels
                im_viz = selector_water.array
                selector_water.im_bool = selector_water.im_bool.astype(bool)
                im_labels[selector_water.im_bool] = settings['labels']['water']
                
                im_sand_ww_water = im_viz.copy()
                
                ##############################################################
                # digitize land pixels (with lassos)
                ##############################################################
                color_land = settings['colors']['other land features']
                ax.set_title('Click and hold to draw lassos and select OTHER LAND pixels\nwhen finished press <Enter>')
                fig.canvas.draw_idle() 
                selector_land = SelectFromImage(ax, implot, color_land)
                key_event = {}
                while True:
                    fig.canvas.draw_idle()                         
                    fig.canvas.mpl_connect('key_press_event', press)
                    plt.waitforbuttonpress()
                    if key_event.get('pressed') == 'enter':
                        selector_land.disconnect()
                        break
                    elif key_event.get('pressed') == 'escape':
                        selector_land.array = im_sand_ww_water
                        implot.set_data(selector_land.array)
                        fig.canvas.draw_idle()                         
                        selector_land.implot = implot
                        selector_land.im_bool = np.zeros((selector_land.array.shape[0], selector_land.array.shape[1])) 
                        selector_land.ind=[]
                # update im_viz and im_labels
                im_viz = selector_land.array
                selector_land.im_bool = selector_land.im_bool.astype(bool)
                im_labels[selector_land.im_bool] = settings['labels']['other land features']  
                
                # save labelled image
                ax.set_title(filename)
                fig.canvas.draw_idle()                         
                fp = os.path.join(filepath_train,settings['inputs']['sitename'])
                if not os.path.exists(fp):
                    os.makedirs(fp)
                fig.savefig(os.path.join(fp,filename+'.jpg'), dpi=150)
                ax.clear()
                # save labels and features
                features = dict([])
                for key in settings['labels'].keys():
                    im_bool = im_labels == settings['labels'][key]
                    features[key] = SDS_shoreline.calculate_features(im_ms, cloud_mask, im_bool)
                training_data = {'labels':im_labels, 'features':features, 'label_ids':settings['labels']}
                with open(os.path.join(fp, filename + '.pkl'), 'wb') as f:
                    pickle.dump(training_data,f)
                    
    # close figure when finished
    plt.close(fig)
示例#30
0
def hystLow(img,
            img_gauss,
            sd=0,
            mean=0,
            diff=40,
            init_low=0.05,
            gen_high=0.8,
            mode='memb'):
    """ Lower treshold calculations for hysteresis membrane detection function hystMemb.

    diff - int, difference (in px number) between hysteresis mask and img without greater values
    delta_diff - int, tolerance level (in px number) for diff value
    gen_high, sd, mean - see hystMemb

    mode - 'cell': only sd treshold calc, 'memb': both tresholds calc

    """
    if mode == 'memb':
        masks = {
            '2sd':
            ma.masked_greater_equal(img,
                                    2 * sd),  # values greater then 2 noise sd 
            'mean': ma.masked_greater(img, mean)
        }  # values greater then mean cytoplasm intensity
    elif mode == 'cell':
        masks = {'2sd': ma.masked_greater_equal(img, 2 * sd)}

    logging.info('masks: {}'.format(masks.keys()))

    low_val = {}
    control_diff = False
    for mask_name in masks:
        mask_img = masks[mask_name]

        logging.info(
            'Mask {} lower treshold fitting in progress'.format(mask_name))

        mask_hyst = filters.apply_hysteresis_threshold(
            img_gauss,
            low=init_low * np.max(img_gauss),
            high=gen_high * np.max(img_gauss))
        diff_mask = np.sum(ma.masked_where(~mask_hyst, mask_img) > 0)

        if diff_mask < diff:
            raise ValueError('Initial lower threshold is too low!')
        logging.info('Initial masks difference {}'.format(diff_mask))

        low = init_low

        i = 0
        control_diff = 1
        while diff_mask >= diff:
            mask_hyst = filters.apply_hysteresis_threshold(
                img_gauss,
                low=low * np.max(img_gauss),
                high=gen_high * np.max(img_gauss))
            diff_mask = np.sum(ma.masked_where(~mask_hyst, mask_img) > 0)

            low += 0.01

            i += 1
            # is cytoplasm mean mask at initial lower threshold value closed? prevent infinit cycle
            if i == 75:
                logging.fatal(
                    'Lower treshold for {} mask {:.2f}, control difference {}px'
                    .format(mask_name, low, control_diff))
                raise RuntimeError(
                    'Membrane in mean mask doesn`t detected at initial lower threshold value!'
                )

        # is cytoplasm mask at setted up difference value closed?
        if mask_name == 'mean':
            control_diff = np.all((segmentation.flood(mask_hyst,
                                                      (0, 0)) + mask_hyst))
            if control_diff == True:
                logging.fatal(
                    'Lower treshold for {} mask {:.2f}, masks difference {}px'.
                    format(mask_name, low, diff_mask))
                raise ValueError(
                    'Membrane in {} mask doesn`t closed, mebrane unlocated at this diff value (too low)!'
                    .format(mask_name))

        low_val.update({mask_name: low})
    logging.info('Lower tresholds {}\n'.format(low_val))

    return low_val