cytometer/utils.py
def rough_foreground_mask(filename, downsample_factor=8.0, dilation_size=25,
                          component_size_threshold=1e6, hole_size_treshold=8000, std_k=1.0,
                          return_im=False, enhance_contrast=None, clear_border=[0, 0, 0, 0],
                          ignore_white_threshold=None, ignore_black_threshold=None, ignore_violet_border=None):
    """
    Rough segmentation of large segmentation objects in a microscope image with a format that can be read
    by OpenSlice. The objects are darker than the background.

    The function works by first estimating the colour of the background as the mode of all colours. This assumes
    that background pixels are the most numerous and relatively consistent in colour.

    Foreground pixels are selected as those that are one standard deviation darker than the background mode. Then,
    morphological operators are applied to dilate and connect those pixels. Selected objects are those connected
    components larger than a given threashold (1e5 pixels by default).

    :param Input histology, in one of the following formats:
      * filename: Path and filename of the microscope image. This file must be in a format understood by OpenSlice.
      * im: PIL.TiffImagePlugin.TiffImageFile. This is the object you obtain with PIL.Image.open('file.tif').
    :param downsample_factor: (def 8) For speed, the image will be loaded at this downsampled resolution. This
    downsample factor must exist in the multilevel pyramid in the file.
    :param dilation_size: (def 25) Thresholded foreground pixels will be dilated with a (dilation_size, dilation_size)
    kernel.
    :param component_size_threshold: (def 1e5) Minimum number of pixels to consider a connected component as a
    foreground object.
    :param std_k: (def 1.0) Constant to set the threshold for initial segmentation of foreground pixels.
    foreground = image < colour_mode - std_k * colour_std
    :param return_im: (def False) Whether to return also the downsampled image in filename.
    :param enhance_contrast: (def 1.0) Scalar with the contrast enhancement factor, from PIL.ImageEnhance.Contrast().
    This allows to internally enhance the image contrast before segmenting the foreground. Note that the returned image
    is not enhanced.
    enhance_contrast=0.0 returns a gray image with no contrast. enhance_contrast=1.0 returns the original image.
    enhance_contrast<1.0 decreases the contrast. enhance_contrast>1.0 increases the contrast.
    :param clear_border: (def [0, 0, 0, 0]) Wipe out a border of width clear_border=[left, right, top, bottom] pixels.
    This can be used e.g. to workaround a bug in openslide where if any location coordinate is 0, read_region() returns
    a black image, by using clear_border=[1, 0, 1, 0].
    :param ignore_white_threshold: (def None) Scalar. If not None, pixels with colour
    (ignore_white_threshold, ignore_white_threshold, ignore_white_threshold) or whiter will be ignored in terms of
    computing the background mode. For example, ignore_white_threshold=253 will ignore colours (253, 253, 253),
    (253, 253, 254), (253, 254, 254), etc, (255, 255, 255).
    :param ignore_black_threshold: (def None) Scalar. If not None, pixels with colour
    (ignore_black_threshold, ignore_black_threshold, ignore_black_threshold) or blacker will be ignored in terms of
    computing the background mode. For example, ignore_black_threshold=3 will ignore colours (3, 3, 3) and blacker.
    :param ignore_violet_border: (def False) In some slides, there's a violet border around the pinkish background that
    will be included in the coarse mask. If ignore_violet_border=x, pixels with R channel < ignore_violet_border will be
    ignored for the segmentation. E.g. ignore_white_threshold=0 will ignore pixels with colour (0, ..., ...) after
    contrast enhancement.
    :return:
    seg: downsampled segmentation mask.
    [im_downsampled]: if return_im=True, this is the downsampled image in filename. This is the image without contrast
    enhancement or masking applied to it.
    """

    if isinstance(filename, six.string_types):  # filename provided

        # load file
        im = openslide.OpenSlide(filename)

        # level that corresponds to the downsample factor
        downsample_level = np.argmin(np.abs(np.array(im.level_downsamples) - downsample_factor))
        if im.level_downsamples[downsample_level] != downsample_factor:
            warnings.warn('File does not contain level with downsample factor ' + str(downsample_factor)
                          + '.\nAvailable levels: ' + str(im.level_downsamples))

        # actual downsample factor available in the image
        downsample_factor = im.level_downsamples[downsample_level]

        # get downsampled image
        im_downsampled = im.read_region(location=(0, 0), level=downsample_level, size=im.level_dimensions[downsample_level])
        im_downsampled = np.array(im_downsampled)
        im_downsampled = im_downsampled[:, :, 0:3]

    elif isinstance(filename, TiffImagePlugin.TiffImageFile):  # TIFF object provided

        # get downsampled image
        downsampled_size = tuple(np.round(np.array(filename.size) / downsample_factor).astype(np.int32))
        im_downsampled = filename.resize(downsampled_size, resample=Image.BILINEAR)
        im_downsampled = np.array(im_downsampled)

    elif isinstance(filename, np.ndarray):

        # get downsampled image
        downsampled_size = tuple(np.round(np.array(filename.shape[0:2]) / downsample_factor).astype(np.int32))
        im_downsampled = resize(filename, downsampled_size, resample=Image.BILINEAR)

    else:

        raise ValueError('Input histology has an unknown format')

    # copy of the downsampled data for the output
    im_downsampled_bak = im_downsampled.copy()

    if DEBUG:
        plt.clf()
        plt.subplot(211)
        plt.imshow(im_downsampled)

    # hack to create a mask to ignore black and white pixels when doing contrast enhancement. Otherwise, e.g. if the
    # image has black pixels, contrast enhancement will bleach the image
    enhancer_mask = np.ones(shape=im_downsampled.shape[0:2], dtype=bool)
    if ignore_white_threshold is not None:
        # mask where there are no white pixels
        non_white_mask = np.prod(im_downsampled >= ignore_white_threshold, axis=2) == 0
        enhancer_mask *= non_white_mask
    if ignore_black_threshold is not None:
        # mask where there are no black pixels
        non_black_mask = np.prod(im_downsampled <= ignore_black_threshold, axis=2) == 0
        enhancer_mask *= non_black_mask

    # contrast enhancement
    nchan = im_downsampled.shape[2]
    if (enhance_contrast is not None) and (enhance_contrast != 1.0):
        colour_mode = np.zeros((nchan,), dtype=im_downsampled.dtype)
        # replace black/white pixels with median-colour pixels
        for c in range(nchan):
            channel = im_downsampled[:, :, c]
            colour_mode[c] = mode(channel[enhancer_mask]).mode
            channel[~enhancer_mask] = colour_mode[c]
        # enhance contrast
        enhancer = ImageEnhance.Contrast(Image.fromarray(im_downsampled))
        im_downsampled = np.array(enhancer.enhance(enhance_contrast))

    # reshape image to matrix with one column per colour channel, only pixels within the enhancer_mask
    im_downsampled_mat = []
    for c in range(nchan):
        channel = im_downsampled_bak[:, :, c]
        im_downsampled_mat.append(channel[enhancer_mask])
    im_downsampled_mat = np.vstack(im_downsampled_mat).T

    # background colour mode and typical variability after contrast correction
    background_colour = mode(im_downsampled_mat, axis=0).mode[0]
    background_colour_std = np.std(im_downsampled_mat, axis=0)

    # mask out violet border
    if ignore_violet_border is not None:
        # filter using the red channel
        violet_mask = im_downsampled[:, :, 0] <= ignore_violet_border
        for c in range(nchan):
            channel = im_downsampled[:, :, c]
            channel[violet_mask] = background_colour[c]

    # threshold segmentation
    seg = np.ones(im_downsampled.shape[0:2], dtype=bool)
    for c in range(nchan):
        seg = np.logical_and(seg, im_downsampled[:, :, c] < background_colour[c] - std_k * background_colour_std[c])
    seg = seg.astype(dtype=np.uint8)
    seg[seg == 1] = 255

    # closing to fill gaps within tissue
    if dilation_size != 0:
        kernel = np.ones((dilation_size, dilation_size), np.uint8)
        seg = cv2.dilate(seg, kernel, iterations=1)
        seg = cv2.erode(seg, kernel, iterations=1)

    # fill small holes
    if hole_size_treshold != 0:
        seg = remove_small_holes(seg > 0, area_threshold=hole_size_treshold).astype(seg.dtype)

    # remove segmentation noise
    seg = remove_small_objects(seg > 0, min_size=component_size_threshold).astype(seg.dtype)

    # remove borders
    if any(np.array(clear_border) < 0):
        raise ValueError('clear_border has negative values')
    [left, right, top, bottom] = clear_border
    seg[:, 0:left] = 0
    if right > 0:
        seg[:, -right:] = 0
    seg[0:top, :] = 0
    if bottom > 0:
        seg[-bottom:, :] = 0

    # # save segmentation as a tiff file (with ZLIB compression)
    # outfilename = os.path.basename(file)
    # outfilename = os.path.splitext(outfilename)[0] + '_seg'
    # outfilename = os.path.join(seg_dir, outfilename + '.tif')
    # tifffile.imsave(outfilename, seg,
    #                 compress=9,
    #                 resolution=(int(im.properties["tiff.XResolution"]) / downsample_factor,
    #                             int(im.properties["tiff.YResolution"]) / downsample_factor,
    #                             im.properties["tiff.ResolutionUnit"].upper()))

    # plot the segmentation
    if DEBUG:
        plt.subplot(212)
        plt.imshow(seg)

    if return_im:
        return seg, im_downsampled_bak
    else:
        return seg

    Rough segmentation of large segmentation objects in a microscope image with a format that can be read
    by OpenSlice. The objects are darker than the background.

    The function works by first estimating the colour of the background as the mode of all colours. This assumes
    that background pixels are the most numerous and relatively consistent in colour.

    Foreground pixels are selected as those that are one standard deviation darker than the background mode. Then,
    morphological operators are applied to dilate and connect those pixels. Selected objects are those connected
    components larger than a given threashold (1e5 pixels by default).

    :param Input histology, in one of the following formats:
      * filename: Path and filename of the microscope image. This file must be in a format understood by OpenSlice.
      * im: PIL.TiffImagePlugin.TiffImageFile. This is the object you obtain with PIL.Image.open('file.tif').
    :param downsample_factor: (def 8) For speed, the image will be loaded at this downsampled resolution. This
    downsample factor must exist in the multilevel pyramid in the file.
    :param dilation_size: (def 25) Thresholded foreground pixels will be dilated with a (dilation_size, dilation_size)
    kernel.
    :param component_size_threshold: (def 1e5) Minimum number of pixels to consider a connected component as a
    foreground object.
    :param std_k: (def 1.0) Constant to set the threshold for initial segmentation of foreground pixels.
    foreground = image < colour_mode - std_k * colour_std
    :param return_im: (def False) Whether to return also the downsampled image in filename.
    :param enhance_contrast: (def 1.0) Scalar with the contrast enhancement factor, from PIL.ImageEnhance.Contrast().
    This allows to internally enhance the image contrast before segmenting the foreground. Note that the returned image
    is not enhanced.
    enhance_contrast=0.0 returns a gray image with no contrast. enhance_contrast=1.0 returns the original image.
    enhance_contrast<1.0 decreases the contrast. enhance_contrast>1.0 increases the contrast.
    :param clear_border: (def [0, 0, 0, 0]) Wipe out a border of width clear_border=[left, right, top, bottom] pixels.
    This can be used e.g. to workaround a bug in openslide where if any location coordinate is 0, read_region() returns
    a black image, by using clear_border=[1, 0, 1, 0].
    :param ignore_white_threshold: (def None) Scalar. If not None, pixels with colour
    (ignore_white_threshold, ignore_white_threshold, ignore_white_threshold) or whiter will be ignored in terms of
    computing the background mode. For example, ignore_white_threshold=253 will ignore colours (253, 253, 253),
    (253, 253, 254), (253, 254, 254), etc, (255, 255, 255).
    :param ignore_black_threshold: (def None) Scalar. If not None, pixels with colour
    (ignore_black_threshold, ignore_black_threshold, ignore_black_threshold) or blacker will be ignored in terms of
    computing the background mode. For example, ignore_black_threshold=3 will ignore colours (3, 3, 3) and blacker.
    :param ignore_violet_border: (def False) In some slides, there's a violet border around the pinkish background that
    will be included in the coarse mask. If ignore_violet_border=x, pixels with R channel < ignore_violet_border will be
    ignored for the segmentation. E.g. ignore_white_threshold=0 will ignore pixels with colour (0, ..., ...) after
    contrast enhancement.
    :return:
    seg: downsampled segmentation mask.
    [im_downsampled]: if return_im=True, this is the downsampled image in filename. This is the image without contrast
    enhancement or masking applied to it.
    
Rough segmentation of large segmentation objects in a microscope image with a format that can be read
by OpenSlice. The objects are darker than the background.

The function works by first estimating the colour of the background as the mode of all colours. This assumes
that background pixels are the most numerous and relatively consistent in colour.

Foreground pixels are selected as those that are one standard deviation darker than the background mode. Then,
morphological operators are applied to dilate and connect those pixels. Selected objects are those connected
components larger than a given threashold (1e5 pixels by default).

:param Input histology, in one of the following formats:
filename: Path and filename of the microscope image. This file must be in a format understood by OpenSlice.
Rough segmentation of large segmentation objects in a microscope image with a format that can be read by OpenSlice . The objects are darker than the background . The function works by first estimating the colour of the background as the mode of all colours . This assumes that background pixels are the most numerous and relatively consistent in colour . Foreground pixels are selected as those that are one standard deviation darker than the background mode . Then morphological operators are applied to dilate and connect those pixels . Selected objects are those connected components larger than a given threashold ( 1e5 pixels by default ) . : param Input histology in one of the following formats : filename : Path and filename of the microscope image . This file must be in a format understood by OpenSlice .
def rough_foreground_mask(filename, downsample_factor=8.0, dilation_size=25,
                          component_size_threshold=1e6, hole_size_treshold=8000, std_k=1.0,
                          return_im=False, enhance_contrast=None, clear_border=[0, 0, 0, 0],
                          ignore_white_threshold=None, ignore_black_threshold=None, ignore_violet_border=None):
    if isinstance(filename, six.string_types):  
        im = openslide.OpenSlide(filename)
        downsample_level = np.argmin(np.abs(np.array(im.level_downsamples) - downsample_factor))
        if im.level_downsamples[downsample_level] != downsample_factor:
            warnings.warn('File does not contain level with downsample factor ' + str(downsample_factor)
                          + '.\nAvailable levels: ' + str(im.level_downsamples))
        downsample_factor = im.level_downsamples[downsample_level]
        im_downsampled = im.read_region(location=(0, 0), level=downsample_level, size=im.level_dimensions[downsample_level])
        im_downsampled = np.array(im_downsampled)
        im_downsampled = im_downsampled[:, :, 0:3]
    elif isinstance(filename, TiffImagePlugin.TiffImageFile):  
        downsampled_size = tuple(np.round(np.array(filename.size) / downsample_factor).astype(np.int32))
        im_downsampled = filename.resize(downsampled_size, resample=Image.BILINEAR)
        im_downsampled = np.array(im_downsampled)
    elif isinstance(filename, np.ndarray):
        downsampled_size = tuple(np.round(np.array(filename.shape[0:2]) / downsample_factor).astype(np.int32))
        im_downsampled = resize(filename, downsampled_size, resample=Image.BILINEAR)
    else:
        raise ValueError('Input histology has an unknown format')
    im_downsampled_bak = im_downsampled.copy()
    if DEBUG:
        plt.clf()
        plt.subplot(211)
        plt.imshow(im_downsampled)
    enhancer_mask = np.ones(shape=im_downsampled.shape[0:2], dtype=bool)
    if ignore_white_threshold is not None:
        non_white_mask = np.prod(im_downsampled >= ignore_white_threshold, axis=2) == 0
        enhancer_mask *= non_white_mask
    if ignore_black_threshold is not None:
        non_black_mask = np.prod(im_downsampled <= ignore_black_threshold, axis=2) == 0
        enhancer_mask *= non_black_mask
    nchan = im_downsampled.shape[2]
    if (enhance_contrast is not None) and (enhance_contrast != 1.0):
        colour_mode = np.zeros((nchan,), dtype=im_downsampled.dtype)
        for c in range(nchan):
            channel = im_downsampled[:, :, c]
            colour_mode[c] = mode(channel[enhancer_mask]).mode
            channel[~enhancer_mask] = colour_mode[c]
        enhancer = ImageEnhance.Contrast(Image.fromarray(im_downsampled))
        im_downsampled = np.array(enhancer.enhance(enhance_contrast))
    im_downsampled_mat = []
    for c in range(nchan):
        channel = im_downsampled_bak[:, :, c]
        im_downsampled_mat.append(channel[enhancer_mask])
    im_downsampled_mat = np.vstack(im_downsampled_mat).T
    background_colour = mode(im_downsampled_mat, axis=0).mode[0]
    background_colour_std = np.std(im_downsampled_mat, axis=0)
    if ignore_violet_border is not None:
        violet_mask = im_downsampled[:, :, 0] <= ignore_violet_border
        for c in range(nchan):
            channel = im_downsampled[:, :, c]
            channel[violet_mask] = background_colour[c]
    seg = np.ones(im_downsampled.shape[0:2], dtype=bool)
    for c in range(nchan):
        seg = np.logical_and(seg, im_downsampled[:, :, c] < background_colour[c] - std_k * background_colour_std[c])
    seg = seg.astype(dtype=np.uint8)
    seg[seg == 1] = 255
    if dilation_size != 0:
        kernel = np.ones((dilation_size, dilation_size), np.uint8)
        seg = cv2.dilate(seg, kernel, iterations=1)
        seg = cv2.erode(seg, kernel, iterations=1)
    if hole_size_treshold != 0:
        seg = remove_small_holes(seg > 0, area_threshold=hole_size_treshold).astype(seg.dtype)
    seg = remove_small_objects(seg > 0, min_size=component_size_threshold).astype(seg.dtype)
    if any(np.array(clear_border) < 0):
        raise ValueError('clear_border has negative values')
    [left, right, top, bottom] = clear_border
    seg[:, 0:left] = 0
    if right > 0:
        seg[:, -right:] = 0
    seg[0:top, :] = 0
    if bottom > 0:
        seg[-bottom:, :] = 0
    if DEBUG:
        plt.subplot(212)
        plt.imshow(seg)
    if return_im:
        return seg, im_downsampled_bak
    else:
        return seg
def rough_foreground_mask ( filename , downsample_factor = 8.0 , dilation_size = 25 , component_size_threshold = 1e6 , hole_size_treshold = 8000 , std_k = 1.0 , return_im = False , enhance_contrast = None , clear_border = [ 0 , 0 , 0 , 0 ] , ignore_white_threshold = None , ignore_black_threshold = None , ignore_violet_border = None ) : if isinstance ( filename , six . string_types ) : im = openslide . OpenSlide ( filename ) downsample_level = np . argmin ( np . abs ( np . array ( im . level_downsamples ) - downsample_factor ) ) if im . level_downsamples [ downsample_level ] != downsample_factor : warnings . warn ( 'File does not contain level with downsample factor ' + str ( downsample_factor ) + '.\nAvailable levels: ' + str ( im . level_downsamples ) ) downsample_factor = im . level_downsamples [ downsample_level ] im_downsampled = im . read_region ( location = ( 0 , 0 ) , level = downsample_level , size = im . level_dimensions [ downsample_level ] ) im_downsampled = np . array ( im_downsampled ) im_downsampled = im_downsampled [ : , : , 0 : 3 ] elif isinstance ( filename , TiffImagePlugin . TiffImageFile ) : downsampled_size = tuple ( np . round ( np . array ( filename . size ) / downsample_factor ) . astype ( np . int32 ) ) im_downsampled = filename . resize ( downsampled_size , resample = Image . BILINEAR ) im_downsampled = np . array ( im_downsampled ) elif isinstance ( filename , np . ndarray ) : downsampled_size = tuple ( np . round ( np . array ( filename . shape [ 0 : 2 ] ) / downsample_factor ) . astype ( np . int32 ) ) im_downsampled = resize ( filename , downsampled_size , resample = Image . BILINEAR ) else : raise ValueError ( 'Input histology has an unknown format' ) im_downsampled_bak = im_downsampled . copy ( ) if DEBUG : plt . clf ( ) plt . subplot ( 211 ) plt . imshow ( im_downsampled ) enhancer_mask = np . ones ( shape = im_downsampled . shape [ 0 : 2 ] , dtype = bool ) if ignore_white_threshold is not None : non_white_mask = np . prod ( im_downsampled >= ignore_white_threshold , axis = 2 ) == 0 enhancer_mask *= non_white_mask if ignore_black_threshold is not None : non_black_mask = np . prod ( im_downsampled <= ignore_black_threshold , axis = 2 ) == 0 enhancer_mask *= non_black_mask nchan = im_downsampled . shape [ 2 ] if ( enhance_contrast is not None ) and ( enhance_contrast != 1.0 ) : colour_mode = np . zeros ( ( nchan , ) , dtype = im_downsampled . dtype ) for c in range ( nchan ) : channel = im_downsampled [ : , : , c ] colour_mode [ c ] = mode ( channel [ enhancer_mask ] ) . mode channel [ ~ enhancer_mask ] = colour_mode [ c ] enhancer = ImageEnhance . Contrast ( Image . fromarray ( im_downsampled ) ) im_downsampled = np . array ( enhancer . enhance ( enhance_contrast ) ) im_downsampled_mat = [ ] for c in range ( nchan ) : channel = im_downsampled_bak [ : , : , c ] im_downsampled_mat . append ( channel [ enhancer_mask ] ) im_downsampled_mat = np . vstack ( im_downsampled_mat ) . T background_colour = mode ( im_downsampled_mat , axis = 0 ) . mode [ 0 ] background_colour_std = np . std ( im_downsampled_mat , axis = 0 ) if ignore_violet_border is not None : violet_mask = im_downsampled [ : , : , 0 ] <= ignore_violet_border for c in range ( nchan ) : channel = im_downsampled [ : , : , c ] channel [ violet_mask ] = background_colour [ c ] seg = np . ones ( im_downsampled . shape [ 0 : 2 ] , dtype = bool ) for c in range ( nchan ) : seg = np . logical_and ( seg , im_downsampled [ : , : , c ] < background_colour [ c ] - std_k * background_colour_std [ c ] ) seg = seg . astype ( dtype = np . uint8 ) seg [ seg == 1 ] = 255 if dilation_size != 0 : kernel = np . ones ( ( dilation_size , dilation_size ) , np . uint8 ) seg = cv2 . dilate ( seg , kernel , iterations = 1 ) seg = cv2 . erode ( seg , kernel , iterations = 1 ) if hole_size_treshold != 0 : seg = remove_small_holes ( seg > 0 , area_threshold = hole_size_treshold ) . astype ( seg . dtype ) seg = remove_small_objects ( seg > 0 , min_size = component_size_threshold ) . astype ( seg . dtype ) if any ( np . array ( clear_border ) < 0 ) : raise ValueError ( 'clear_border has negative values' ) [ left , right , top , bottom ] = clear_border seg [ : , 0 : left ] = 0 if right > 0 : seg [ : , - right : ] = 0 seg [ 0 : top , : ] = 0 if bottom > 0 : seg [ - bottom : , : ] = 0 if DEBUG : plt . subplot ( 212 ) plt . imshow ( seg ) if return_im : return seg , im_downsampled_bak else : return seg
Rough segmentation of large segmentation objects in a microscope image with a format that can be read
by OpenSlice.
Rough segmentation of large segmentation objects in a microscope image with a format that can be read by OpenSlice .
"""
    Rough segmentation of large segmentation objects in a microscope image with a format that can be read
    by OpenSlice. The objects are darker than the background.

    The function works by first estimating the colour of the background as the mode of all colours. This assumes
    that background pixels are the most numerous and relatively consistent in colour.

    Foreground pixels are selected as those that are one standard deviation darker than the background mode. Then,
    morphological operators are applied to dilate and connect those pixels. Selected objects are those connected
    components larger than a given threashold (1e5 pixels by default).

    :param Input histology, in one of the following formats:
      * filename: Path and filename of the microscope image. This file must be in a format understood by OpenSlice.
      * im: PIL.TiffImagePlugin.TiffImageFile. This is the object you obtain with PIL.Image.open('file.tif').
    :param downsample_factor: (def 8) For speed, the image will be loaded at this downsampled resolution. This
    downsample factor must exist in the multilevel pyramid in the file.
    :param dilation_size: (def 25) Thresholded foreground pixels will be dilated with a (dilation_size, dilation_size)
    kernel.
    :param component_size_threshold: (def 1e5) Minimum number of pixels to consider a connected component as a
    foreground object.
    :param std_k: (def 1.0) Constant to set the threshold for initial segmentation of foreground pixels.
    foreground = image < colour_mode - std_k * colour_std
    :param return_im: (def False) Whether to return also the downsampled image in filename.
    :param enhance_contrast: (def 1.0) Scalar with the contrast enhancement factor, from PIL.ImageEnhance.Contrast().
    This allows to internally enhance the image contrast before segmenting the foreground. Note that the returned image
    is not enhanced.
    enhance_contrast=0.0 returns a gray image with no contrast. enhance_contrast=1.0 returns the original image.
    enhance_contrast<1.0 decreases the contrast. enhance_contrast>1.0 increases the contrast.
    :param clear_border: (def [0, 0, 0, 0]) Wipe out a border of width clear_border=[left, right, top, bottom] pixels.
    This can be used e.g. to workaround a bug in openslide where if any location coordinate is 0, read_region() returns
    a black image, by using clear_border=[1, 0, 1, 0].
    :param ignore_white_threshold: (def None) Scalar. If not None, pixels with colour
    (ignore_white_threshold, ignore_white_threshold, ignore_white_threshold) or whiter will be ignored in terms of
    computing the background mode. For example, ignore_white_threshold=253 will ignore colours (253, 253, 253),
    (253, 253, 254), (253, 254, 254), etc, (255, 255, 255).
    :param ignore_black_threshold: (def None) Scalar. If not None, pixels with colour
    (ignore_black_threshold, ignore_black_threshold, ignore_black_threshold) or blacker will be ignored in terms of
    computing the background mode. For example, ignore_black_threshold=3 will ignore colours (3, 3, 3) and blacker.
    :param ignore_violet_border: (def False) In some slides, there's a violet border around the pinkish background that
    will be included in the coarse mask. If ignore_violet_border=x, pixels with R channel < ignore_violet_border will be
    ignored for the segmentation. E.g. ignore_white_threshold=0 will ignore pixels with colour (0, ..., ...) after
    contrast enhancement.
    :return:
    seg: downsampled segmentation mask.
    [im_downsampled]: if return_im=True, this is the downsampled image in filename. This is the image without contrast
    enhancement or masking applied to it.
    """ # filename provided # load file # level that corresponds to the downsample factor # actual downsample factor available in the image # get downsampled image # TIFF object provided # get downsampled image # get downsampled image # copy of the downsampled data for the output # hack to create a mask to ignore black and white pixels when doing contrast enhancement. Otherwise, e.g. if the # image has black pixels, contrast enhancement will bleach the image # mask where there are no white pixels # mask where there are no black pixels # contrast enhancement # replace black/white pixels with median-colour pixels # enhance contrast # reshape image to matrix with one column per colour channel, only pixels within the enhancer_mask # background colour mode and typical variability after contrast correction # mask out violet border # filter using the red channel # threshold segmentation # closing to fill gaps within tissue # fill small holes # remove segmentation noise # remove borders # # save segmentation as a tiff file (with ZLIB compression) # outfilename = os.path.basename(file) # outfilename = os.path.splitext(outfilename)[0] + '_seg' # outfilename = os.path.join(seg_dir, outfilename + '.tif') # tifffile.imsave(outfilename, seg, #                 compress=9, #                 resolution=(int(im.properties["tiff.XResolution"]) / downsample_factor, #                             int(im.properties["tiff.YResolution"]) / downsample_factor, #                             im.properties["tiff.ResolutionUnit"].upper())) # plot the segmentation
filename
downsample_factor
dilation_size
component_size_threshold
hole_size_treshold
std_k
return_im
enhance_contrast
clear_border
ignore_white_threshold
ignore_black_threshold
ignore_violet_border