def segment_images(inpDir, outDir, config_data):
    """ Workflow for data with a spotty appearance
    in each 2d frame such as fibrillarin and beta catenin.

    Args:
        inpDir : path to the input directory
        outDir : path to the output directory
        config_data : path to the configuration file
    """

    logging.basicConfig(
        format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s',
        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("main")
    logger.setLevel(logging.INFO)

    inpDir_files = os.listdir(inpDir)
    for i, f in enumerate(inpDir_files):
        logger.info('Segmenting image : {}'.format(f))

        # Load image
        br = BioReader(os.path.join(inpDir, f))
        image = br.read_image()
        structure_channel = 0
        struct_img0 = image[:, :, :, structure_channel, 0]
        struct_img0 = struct_img0.transpose(2, 0, 1).astype(np.float32)

        # main algorithm
        intensity_scaling_param = config_data['intensity_scaling_param']
        struct_img = intensity_normalization(
            struct_img0, scaling_param=intensity_scaling_param)
        gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma']
        structure_img_smooth = image_smoothing_gaussian_3d(
            struct_img, sigma=gaussian_smoothing_sigma)
        s2_param = config_data['s2_param']
        bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param)
        minArea = config_data['minArea']
        seg = remove_small_objects(bw > 0,
                                   min_size=minArea,
                                   connectivity=1,
                                   in_place=False)
        seg = seg > 0
        out_img = seg.astype(np.uint8)
        out_img[out_img > 0] = 255

        # create output image
        out_img = out_img.transpose(1, 2, 0)
        out_img = out_img.reshape(
            (out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1))

        # write image using BFIO
        bw = BioWriter(os.path.join(outDir, f))
        bw.num_x(out_img.shape[1])
        bw.num_y(out_img.shape[0])
        bw.num_z(out_img.shape[2])
        bw.num_c(out_img.shape[3])
        bw.num_t(out_img.shape[4])
        bw.pixel_type(dtype='uint8')
        bw.write_image(out_img)
        bw.close_image()
def Workflow_fbl_labelfree_4dn(
    struct_img: np.ndarray,
    rescale_ratio: float = -1,
    output_type: str = "default",
    output_path: Union[str, Path] = None,
    fn: Union[str, Path] = None,
    output_func=None,
):
    """
    classic segmentation workflow wrapper for structure FBL Labelfree 4dn

    Parameter:
    -----------
    struct_img: np.ndarray
        the 3D image to be segmented
    rescale_ratio: float
        an optional parameter to allow rescale the image before running the
        segmentation functions, default is no rescaling
    output_type: str
        select how to handle output. Currently, four types are supported:
        1. default: the result will be saved at output_path whose filename is
            original name without extention + "_struct_segmentaiton.tiff"
        2. array: the segmentation result will be simply returned as a numpy array
        3. array_with_contour: segmentation result will be returned together with
            the contour of the segmentation
        4. customize: pass in an extra output_func to do a special save. All the
            intermediate results, names of these results, the output_path, and the
            original filename (without extension) will be passed in to output_func.
    """
    ##########################################################################
    # PARAMETERS:
    minArea = 5
    low_level_min_size = 7000
    s2_param = [[0.5, 0.1]]
    intensity_scaling_param = [0.5, 19.5]
    gaussian_smoothing_sigma = 1

    ##########################################################################
    out_img_list = []
    out_name_list = []

    ###################
    # PRE_PROCESSING
    ###################
    # intenisty normalization
    struct_norm = intensity_normalization(
        struct_img, scaling_param=intensity_scaling_param)
    out_img_list.append(struct_img.copy())
    out_name_list.append("im_norm")

    # smoothing
    struct_smooth = image_smoothing_gaussian_3d(struct_norm,
                                                sigma=gaussian_smoothing_sigma)

    out_img_list.append(struct_smooth.copy())
    out_name_list.append("im_smooth")

    ###################
    # core algorithm
    ###################
    # step 1: low level thresholding
    # global_otsu = threshold_otsu(structure_img_smooth)
    global_tri = threshold_triangle(struct_smooth)
    global_median = np.percentile(struct_smooth, 50)

    th_low_level = (global_tri + global_median) / 2
    bw_low_level = struct_smooth > th_low_level
    bw_low_level = remove_small_objects(bw_low_level,
                                        min_size=low_level_min_size,
                                        connectivity=1,
                                        in_place=True)

    # step 2: high level thresholding
    bw_high_level = np.zeros_like(bw_low_level)
    lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1)
    for idx in range(num_obj):
        single_obj = lab_low == (idx + 1)
        local_otsu = threshold_otsu(struct_smooth[single_obj])
        bw_high_level[np.logical_and(struct_smooth > local_otsu * 1.2,
                                     single_obj)] = 1

    # step 3: finer segmentation
    response2d = dot_2d_slice_by_slice_wrapper(struct_smooth, s2_param)
    bw_finer = remove_small_objects(response2d,
                                    min_size=minArea,
                                    connectivity=1,
                                    in_place=True)

    # merge finer level detection into high level coarse segmentation
    # to include outside dim parts
    bw_high_level[bw_finer > 0] = 1

    ###################
    # POST-PROCESSING
    # make sure the variable name of final segmentation is 'seg'
    ###################
    seg = remove_small_objects(bw_high_level,
                               min_size=minArea,
                               connectivity=1,
                               in_place=True)

    # output
    seg = seg > 0
    seg = seg.astype(np.uint8)
    seg[seg > 0] = 255

    out_img_list.append(seg.copy())
    out_name_list.append("bw_final")

    if output_type == "default":
        # the default final output, simply save it to the output path
        save_segmentation(seg, False, Path(output_path), fn)
    elif output_type == "customize":
        # the hook for passing in a customized output function
        # use "out_img_list" and "out_name_list" in your hook to
        # customize your output functions
        # TODO CREATE OUT_IMG_LIST/OUT_NAMELIST?
        output_func(out_img_list, out_name_list, Path(output_path), fn)
    elif output_type == "array":
        return seg
    elif output_type == "array_with_contour":
        return (seg, generate_segmentation_contour(seg))
    else:
        raise NotImplementedError("invalid output type: {output_type}")
Example #3
0
def segment_images(inpDir, outDir, config_data):
    """ Workflow for data with similar morphology
    as Nucleophosmin

    Args:
        inpDir : path to the input directory
        outDir : path to the output directory
        config_data : path to the configuration file
    """

    logging.basicConfig(
        format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s',
        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("main")
    logger.setLevel(logging.INFO)

    inpDir_files = os.listdir(inpDir)
    for i, f in enumerate(inpDir_files):
        logger.info('Segmenting image : {}'.format(f))

        # Load image
        br = BioReader(os.path.join(inpDir, f))
        image = br.read_image()
        structure_channel = 0
        struct_img0 = image[:, :, :, structure_channel, 0]
        struct_img0 = struct_img0.transpose(2, 0, 1).astype(np.float32)

        # main algorithm
        intensity_scaling_param = config_data['intensity_scaling_param']
        struct_img = intensity_normalization(
            struct_img0, scaling_param=intensity_scaling_param)
        gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma']
        structure_img_smooth = image_smoothing_gaussian_3d(
            struct_img, sigma=gaussian_smoothing_sigma)
        global_thresh_method = config_data['global_thresh_method']
        object_minArea = config_data['object_minArea']
        bw, object_for_debug = MO(structure_img_smooth,
                                  global_thresh_method=global_thresh_method,
                                  object_minArea=object_minArea,
                                  return_object=True)
        s2_param_bright = config_data['s2_param_bright']
        s2_param_dark = config_data['s2_param_dark']
        bw_extra = dot_2d_slice_by_slice_wrapper(structure_img_smooth,
                                                 s2_param_bright)
        bw_dark = dot_2d_slice_by_slice_wrapper(1 - structure_img_smooth,
                                                s2_param_dark)
        bw_merge = np.logical_or(bw, bw_extra)
        bw_merge[bw_dark > 0] = 0
        minArea = config_data['minArea']
        seg = remove_small_objects(bw_merge > 0,
                                   min_size=minArea,
                                   connectivity=1,
                                   in_place=False)
        seg = seg > 0
        out_img = seg.astype(np.uint8)
        out_img[out_img > 0] = 255

        # create output image
        out_img = out_img.transpose(1, 2, 0)
        out_img = out_img.reshape(
            (out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1))

        # write image using BFIO
        bw = BioWriter(os.path.join(outDir, f), metadata=br.read_metadata())
        bw.num_x(out_img.shape[1])
        bw.num_y(out_img.shape[0])
        bw.num_z(out_img.shape[2])
        bw.num_c(out_img.shape[3])
        bw.num_t(out_img.shape[4])
        bw.pixel_type(dtype='uint8')
        bw.write_image(out_img)
        bw.close_image()
Example #4
0
def Workflow_h2b(
    struct_img: np.ndarray,
    rescale_ratio: float = -1,
    output_type: str = "default",
    output_path: Union[str, Path] = None,
    fn: Union[str, Path] = None,
    output_func=None,
):
    """
    classic segmentation workflow wrapper for structure H2B

    Parameter:
    -----------
    struct_img: np.ndarray
        the 3D image to be segmented
    rescale_ratio: float
        an optional parameter to allow rescale the image before running the
        segmentation functions, default is no rescaling
    output_type: str
        select how to handle output. Currently, four types are supported:
        1. default: the result will be saved at output_path whose filename is
            original name without extention + "_struct_segmentaiton.tiff"
        2. array: the segmentation result will be simply returned as a numpy array
        3. array_with_contour: segmentation result will be returned together with
            the contour of the segmentation
        4. customize: pass in an extra output_func to do a special save. All the
            intermediate results, names of these results, the output_path, and the
            original filename (without extension) will be passed in to output_func.
    """
    ##########################################################################
    # PARAMETERS:
    #   note that these parameters are supposed to be fixed for the structure
    #   and work well accross different datasets

    intensity_norm_param = [1.0, 14]
    s2_param = [[1, 0.014], [2, 0.039]]
    minArea = 3
    ##########################################################################

    out_img_list = []
    out_name_list = []

    ###################
    # PRE_PROCESSING
    ###################
    # intenisty normalization (min/max)
    struct_img = intensity_normalization(struct_img,
                                         scaling_param=intensity_norm_param)

    out_img_list.append(struct_img.copy())
    out_name_list.append("im_norm")

    # rescale if needed
    if rescale_ratio > 0:
        struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio),
                          order=2)

        struct_img = (struct_img - struct_img.min() +
                      1e-8) / (struct_img.max() - struct_img.min() + 1e-8)

    # smoothing with gaussian filter
    structure_img_smooth = edge_preserving_smoothing_3d(struct_img)

    out_img_list.append(structure_img_smooth.copy())
    out_name_list.append("im_smooth")

    ###################
    # core algorithm
    ###################

    bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param)

    ###################
    # POST-PROCESSING
    ###################
    seg = remove_small_objects(bw > 0,
                               min_size=minArea,
                               connectivity=1,
                               in_place=False)

    # output
    seg = seg > 0
    seg = seg.astype(np.uint8)
    seg[seg > 0] = 255

    out_img_list.append(seg.copy())
    out_name_list.append("bw_final")

    if output_type == "default":
        # the default final output, simply save it to the output path
        save_segmentation(seg, False, Path(output_path), fn)
    elif output_type == "customize":
        # the hook for passing in a customized output function
        # use "out_img_list" and "out_name_list" in your hook to
        # customize your output functions
        output_func(out_img_list, out_name_list, Path(output_path), fn)
    elif output_type == "array":
        return seg
    elif output_type == "array_with_contour":
        return (seg, generate_segmentation_contour(seg))
    else:
        raise NotImplementedError("invalid output type: {output_type}")
Example #5
0
def FABP3_Cardio_Pipeline(struct_img,
                          rescale_ratio,
                          output_type,
                          output_path,
                          fn,
                          output_func=None):
    ##########################################################################
    # PARAMETERS:
    #   note that these parameters are supposed to be fixed for the structure
    #   and work well accross different datasets

    # ADD you parameters here
    intensity_norm_param = [1, 18]
    minArea = 0
    gaussian_smoothing_sigma = 1
    # lower_bound = 685
    # upper_b = 18
    # ADD-HERE
    ##########################################################################

    out_img_list = []
    out_name_list = []

    ###################
    # PRE_PROCESSING
    ###################
    # intenisty normalization (min/max)
    struct_img = intensity_normalization(struct_img,
                                         scaling_param=intensity_norm_param)
    # upper_bound = np.mean(struct_img) + 18 * np.std(struct_img)
    # struct_img[struct_img < lower_bound] = lower_bound
    # struct_img[struct_img > upper_bound] = upper_bound
    # struct_img = (struct_img - lower_bound).astype(float)/(upper_bound - lower_bound)

    out_img_list.append(struct_img.copy())
    out_name_list.append("im_norm")

    # rescale if needed
    if rescale_ratio > 0:
        struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio],
                            method="cubic")
        struct_img = (struct_img - struct_img.min() +
                      1e-8) / (struct_img.max() - struct_img.min() + 1e-8)

    # smoothing with gaussian filter
    structure_img_smooth = image_smoothing_gaussian_slice_by_slice(
        struct_img, sigma=gaussian_smoothing_sigma)  # ADD-HERE

    out_img_list.append(structure_img_smooth.copy())
    out_name_list.append("im_smooth")

    # core algorithm
    # th_li = threshold_li(structure_img_smooth)

    # PARAMETERS for this step ##
    s2_param = [[1, 0.02]]

    bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param)

    # POST-PROCESSING

    seg = remove_small_objects(bw,
                               min_size=minArea,
                               connectivity=1,
                               in_place=False)

    # output
    seg = seg > 0
    seg = seg.astype(np.uint8)
    seg[seg > 0] = 255

    out_img_list.append(seg.copy())
    out_name_list.append("bw_final")

    if output_type == "default":
        # the default final output
        save_segmentation(seg, False, output_path, fn)
    elif output_type == "TEMPLATE":
        # the hook for pre-defined output functions
        template_output(out_img_list, out_name_list, output_type, output_path,
                        fn)