def nuc_seg(image, scale, sigma, f2, hol_min, hol_max, minA):
    img = intensity_normalization(image, scale)
    img_s = image_smoothing_gaussian_3d(img, sigma)
    bw = filament_2d_wrapper(img_s, f2)
    bw_2 = hole_filling(bw, hol_min, hol_max)
    seg = remove_small_objects(bw_2 > 0,
                               min_size=minA,
                               connectivity=1,
                               in_place=False)
    seg2, n = label(seg, return_num=True)
    return (img_s, bw_2, seg2, n)
Exemple #2
0
def RAB5A_HiPSC_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

    intensity_norm_param = [1000]
    gaussian_smoothing_sigma = 1
    gaussian_smoothing_truncate_range = 3.0
    dot_3d_sigma = 1
    dot_3d_cutoff = 0.03

    hole_min = 0
    hole_max = 81

    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 = 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)
        gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio

    # smoothing with gaussian filter
    structure_img_smooth = image_smoothing_gaussian_slice_by_slice(
        struct_img,
        sigma=gaussian_smoothing_sigma,
        truncate_range=gaussian_smoothing_truncate_range)

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

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

    # step 1: LOG 3d
    response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma)
    bw = response > dot_3d_cutoff

    # step 2: fill holes and remove small objects
    bw_filled = hole_filling(bw, hole_min, hole_max, True)
    seg = remove_small_objects(bw_filled,
                               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 == 'AICS_pipeline':
        # pre-defined output function for pipeline data
        save_segmentation(seg, True, output_path, fn)
    elif output_type == 'customize':
        # the hook for passing in a customized output function
        output_fun(out_img_list, out_name_list, output_path, fn)
    else:
        # the hook for pre-defined RnD output functions (AICS internal)
        img_list, name_list = RAB5A_output(out_img_list, out_name_list,
                                           output_type, output_path, fn)
        if output_type == 'QCB':
            return img_list, name_list
def segment_images(inpDir, outDir, config_data):
    """ Workflow for data with similar morphology
    as LAMP-1

    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_slice_by_slice(
            struct_img, sigma=gaussian_smoothing_sigma)
        s2_param = config_data['s2_param']
        bw_spot = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param)
        f2_param = config_data['f2_param']
        bw_filament = filament_2d_wrapper(structure_img_smooth, f2_param)
        bw = np.logical_or(bw_spot, bw_filament)
        fill_2d = config_data['fill_2d']
        if fill_2d == 'True':
            fill_2d = True
        elif fill_2d == 'False':
            fill_2d = False
        fill_max_size = config_data['fill_max_size']
        minArea = config_data['minArea']
        bw_fill = hole_filling(bw, 0, fill_max_size, False)
        seg = remove_small_objects(bw_fill > 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()
Exemple #4
0
def segment_images(inpDir, outDir, config_data):
    """ Workflow for data with shell like shapes 
    such as lamin B1 (interphase-specific)

    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)
        middle_frame_method = config_data['middle_frame_method']
        mid_z = get_middle_frame(structure_img_smooth,
                                 method=middle_frame_method)
        f2_param = config_data['f2_param']
        bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :],
                                       f2_param)
        hole_max = config_data['hole_max']
        hole_min = config_data['hole_min']
        bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max)
        seed = get_3dseed_from_mid_frame(
            np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z,
            hole_min)
        bw_filled = watershed(
            struct_img, seed.astype(int), watershed_line=True) > 0
        seg = np.logical_xor(bw_filled, dilation(bw_filled, selem=ball(1)))
        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_rab5a(
    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 RAB5A

    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 = [1000]
    gaussian_smoothing_sigma = 1
    gaussian_smoothing_truncate_range = 3.0
    dot_3d_sigma = 1
    dot_3d_cutoff = 0.03

    hole_min = 0
    hole_max = 81

    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)
        gaussian_smoothing_truncate_range = (
            gaussian_smoothing_truncate_range * rescale_ratio)

    # smoothing with gaussian filter
    structure_img_smooth = image_smoothing_gaussian_slice_by_slice(
        struct_img,
        sigma=gaussian_smoothing_sigma,
        truncate_range=gaussian_smoothing_truncate_range,
    )

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

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

    # step 1: LOG 3d
    response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma)
    bw = response > dot_3d_cutoff

    # step 2: fill holes and remove small objects
    bw_filled = hole_filling(bw, hole_min, hole_max, True)
    seg = remove_small_objects(bw_filled,
                               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}")
from aicssegmentation.core.visual import blob2dExplorer_single, fila2dExplorer_single, random_colormap
from aicssegmentation.core.seg_dot import dot_2d, logSlice
from aicssegmentation.core.vessel import filament_2d_wrapper
from aicssegmentation.core.utils import hole_filling
from aicssegmentation.core.pre_processing_utils import intensity_normalization, suggest_normalization_param, edge_preserving_smoothing_3d

fn = '/Users/claytonwandishin/UNC_PCNA/161124 u2os #5 ncs 6NCS_0_1c1.tif'
os.path.isfile(fn)

tif = TiffFile(fn)

num_img = len(tif.pages)
print(num_img)

img_seq = []
for ii in range(num_img):
    img_seq.append(imread(fn, key=ii))
img = img_seq[135]
suggest_normalization_param(img)
img_norm = intensity_normalization(img, [0.5, 8.0])
img_smooth = edge_preserving_smoothing_3d(img_norm)
interact(blob2dExplorer_single, im=fixed(img_smooth), \
         sigma=widgets.FloatRangeSlider(value=(1,5), min=1, max=15,step=1,continuous_update=False),  \
         th=widgets.FloatSlider(value=0.02,min=0.01, max=0.1, step=0.01,continuous_update=False))
ksize = (65, 65)
blur_smooth = cv2.blur(np.float32(img_smooth), ksize)
nuc_detection = dot_2d(blur_smooth, 11)
nuc_mask = nuc_detection > 0.0015
final_seg = hole_filling(remove_small_objects(nuc_mask), .5, 2500)
plt.imshow(final_seg)
#identifies objects
interact(blob2dExplorer_single, im=fixed(img_smooth), \
         sigma=widgets.FloatRangeSlider(value=(1,5), min=1, max=15,step=1,continuous_update=False),  \
         th=widgets.FloatSlider(value=0.02,min=0.01, max=0.1, step=0.01,continuous_update=False))

#plt.imshow(img_smooth)

#ksize = (60,60)
#blur_smooth = cv2.blur(np.float32(img_smooth), ksize)
#nuc_detection = dot_2d(img_smooth, 11)

#creates a mask
nuc_mask = img_smooth > 0.0015

#fills small holes
final_seg = hole_filling(remove_small_objects(nuc_mask), 1, 1500)

#inverts the image and crops it
inv_seg = np.invert(final_seg)
cropped = inv_seg[0:1983, 0:1983]
#fills holes in cropped image
cropped = hole_filling(remove_small_objects(cropped), 1, 1600)

plt.imshow(cropped, cmap='gray')
#plt.imshow(circle)

#change this directory if needed (actual image)
fn = '/Users/claytonwandishin/UNC_PCNA/UNC_PCNA_Split/161124u2os#5ncs6NCS_0_1c1-0136.tif'
os.path.isfile(fn)

tif1 = TiffFile(fn)
Exemple #8
0
def Workflow_lmnb1_interphase(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

    intensity_norm_param = [4000]
    gaussian_smoothing_sigma = 1
    gaussian_smoothing_truncate_range = 3.0
    f2_param = [[1, 0.01], [2, 0.01], [3, 0.01]]
    hole_max = 40000
    hole_min = 400
    ##########################################################################

    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 = 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 boundary preserving smoothing
    structure_img_smooth = image_smoothing_gaussian_3d(
        struct_img,
        sigma=gaussian_smoothing_sigma,
        truncate_range=gaussian_smoothing_truncate_range)

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

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

    # get the mid frame
    mid_z = get_middle_frame(structure_img_smooth, method='intensity')

    # 2d filament filter on the middle frame
    bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param)

    # hole filling
    bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max)
    seed = get_3dseed_from_mid_frame(np.logical_xor(bw_fill_mid_z, bw_mid_z),
                                     struct_img.shape,
                                     mid_z,
                                     hole_min,
                                     bg_seed=True)
    seg_filled = watershed(
        struct_img, seed.astype(int),
        watershed_line=True) > 1  # in watershed result, 1 is for background

    # get the actual shell
    seg = find_boundaries(seg_filled, connectivity=1, mode='thick')

    # output
    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 == 'array':
        return seg
    elif output_type == 'array_with_contour':
        return (seg, generate_segmentation_contour(seg))
    else:
        print('your can implement your output hook here, but not yet')
        quit()
def Workflow_lmnb1_interphase(
    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 LMNB1 interphase

    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 = [4000]
    gaussian_smoothing_sigma = 1
    gaussian_smoothing_truncate_range = 3.0
    f2_param = [[1, 0.01], [2, 0.01], [3, 0.01]]
    hole_max = 40000
    hole_min = 400
    ##########################################################################

    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 boundary preserving smoothing
    structure_img_smooth = image_smoothing_gaussian_3d(
        struct_img,
        sigma=gaussian_smoothing_sigma,
        truncate_range=gaussian_smoothing_truncate_range,
    )

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

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

    # get the mid frame
    mid_z = get_middle_frame(structure_img_smooth, method="intensity")

    # 2d filament filter on the middle frame
    bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param)

    # hole filling
    bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max)
    seed = get_3dseed_from_mid_frame(
        np.logical_xor(bw_fill_mid_z, bw_mid_z),
        struct_img.shape,
        mid_z,
        hole_min,
        bg_seed=True,
    )
    seg_filled = (
        watershed(struct_img, seed.astype(int), watershed_line=True) > 1
    )  # in watershed result, 1 is for background

    # get the actual shell
    seg = find_boundaries(seg_filled, connectivity=1, mode="thick")

    # output
    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}")