def remove_large_objects(ar, max_size=128, connectivity=1): if max_size == -1: # shortcut for efficiency return ar out = ar.copy() if out.dtype == bool: selem = generate_binary_structure(ar.ndim, connectivity) ccs = np.zeros_like(ar, dtype=np.int32) label_image(ar, selem, output=ccs) else: ccs = out try: component_sizes = np.bincount(ccs.ravel()) except ValueError: raise ValueError("Negative value labels are not supported. Try " "relabeling the input with `scipy.ndimage.label` or " "`skimage.morphology.label`.") too_big = component_sizes > max_size too_big_mask = too_big[ccs] out[too_big_mask] = 0 return out
def find_big_ones_clusters(bin_mask, min_cluster_length=None, min_cluster_order=None): labeled_mask, _ = label_image(bin_mask) cluster_labels, cluster_sizes = np.unique(labeled_mask, return_counts=True) # sort from max to min sorted_indexes = np.flip(cluster_sizes.argsort()) cluster_sizes = cluster_sizes[sorted_indexes] cluster_labels = cluster_labels[sorted_indexes] min_cluster_length = cluster_sizes[min_cluster_order] if min_cluster_order else min_cluster_length big_clusters_indexes = cluster_sizes > min_cluster_length big_ones_cluster_labels = cluster_labels[big_clusters_indexes] # TODO:refactor this part contour_mask = np.zeros(bin_mask.shape, dtype=bool) for label in big_ones_cluster_labels: if label == 0: continue contour_mask = np.logical_or(contour_mask, _create_mask_layer_for_label(labeled_mask, label)) return contour_mask
def find_mask_longest_contours(bin_img_with_contours, filter_by_contour_length=False, max_number_of_contours=None, min_contour_length=None): labeled_img, _ = label_image(bin_img_with_contours) unique_labels, unique_counts = np.unique(labeled_img, return_counts=True) longest_contours_indexes = np.flip(unique_counts.argsort()) if not filter_by_contour_length: if len(longest_contours_indexes) < max_number_of_contours: max_number_of_contours = len(longest_contours_indexes) longest_contours_labels = unique_labels[longest_contours_indexes][ 0:max_number_of_contours] else: longest_contours_lens = unique_counts[longest_contours_indexes][ 0:max_number_of_contours] longest_contours_lens_lower_max = longest_contours_lens > min_contour_length longest_contours_indexes_sampled = longest_contours_indexes[ longest_contours_lens_lower_max] longest_contours_labels = unique_labels[ longest_contours_indexes_sampled] # print("number of selected contour: ", len(longest_contours_labels)) contour_mask = np.zeros(labeled_img.shape, dtype=bool) for label in longest_contours_labels: if label == 0: continue contour_mask = np.logical_or( contour_mask, _create_mask_layer_for_label(labeled_img, label)) return contour_mask
def _apply_convective_criterion4(convective_flag_matrix, min_size_pixels): """Applies criterion 4 for convective classification. Criterion 4 states: if pixel (i, j) is marked convective but is not part of a connected region with size of >= K pixels, (i, j) is not actually convective. :param convective_flag_matrix: M-by-N numpy array of Boolean flags (True if convective, False if not). :param min_size_pixels: Minimum size of connected region. :return: convective_flag_matrix: Updated version of input. """ region_id_matrix = label_image(convective_flag_matrix.astype(int), structure=numpy.full((3, 3), 1.))[0] num_regions = numpy.max(region_id_matrix) for i in range(num_regions): these_indices = numpy.where(region_id_matrix == i + 1) if len(these_indices[0]) >= min_size_pixels: continue convective_flag_matrix[these_indices] = False return convective_flag_matrix
def get_pore_volume_distribution(levitatting_volume, structure_neighbors_num): structure = get_structure(neighbors_num=structure_neighbors_num) if levitatting_volume.ndim == 2: structure = structure[1] connected_components, _ = label_image(levitatting_volume, structure) pore_volume_distribution = np.unique(connected_components, return_counts=True)[1][1:] return pore_volume_distribution
def get_sparse_masks( segmented_img: np.ndarray, raw_img_shape: tuple, edge_method: str, selem: int, transpose=True ) -> np.ndarray: # allocate array with same size as the raw input image # so that the dims match for CNMF img = np.zeros(raw_img_shape, dtype=segmented_img.dtype) # fill the allocated array with vals from the NuSeT segmentation # sometimes the segmented image has its dims trimmed by a few pixels if len(raw_img_shape) == 3: img[:, :segmented_img.shape[1], :segmented_img.shape[2]] = segmented_img struc = np.array( [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]] ) else: img[:segmented_img.shape[0], :segmented_img.shape[1]] = segmented_img struc = None areas = label_image(img, structure=struc) # A = np.zeros((np.prod(img.shape), areas[1]), dtype=bool) selem: np.array = np.ones((selem,)*len(segmented_img.shape)) if areas[1] < 50: print("Less than 50 regions, not parallelizing") sparses = [] for i in tqdm(range(areas[1])): sparses.append( _get_sparse_mask(areas, i, edge_method, selem) ) else: print("Greater than 50 regions, parallelizing with joblib") sparses = Parallel(n_jobs=cpu_count(), verbose=5)( delayed(_get_sparse_mask)(areas, i, edge_method, selem) for i in range(areas[1]) ) if transpose: return scipy.sparse.vstack(sparses).T.toarray() else: return scipy.sparse.vstack(sparses).toarray()
def get_closed_pores(bin_3d_img, structure_neighbors_num=6): """ function returns a bin_3d_img of closed pores for the chosen neighbor voxels configuration """ if not np.asarray(bin_3d_img).dtype == bool: bin_3d_img = bin_3d_img.astype(bool) structure = get_structure(structure_neighbors_num) connected_components, _ = label_image(bin_3d_img, structure) levitating_volume = clear_border(connected_components) > 0 return levitating_volume
def filter_pores_mask(pore_mask_img, lowest_value, highest_value=None): labeled_img, _ = label_image(pore_mask_img) unique_labels, unique_counts = np.unique(labeled_img, return_counts=True) if highest_value == None: highest_value = np.max(unique_counts) + 1 accepted_labels = unique_labels[np.logical_and( unique_labels > 0, unique_counts < highest_value, unique_counts > lowest_value)] mask = np.zeros(pore_mask_img.shape) for elem in accepted_labels: # TODO: replace with _create_mask_layer_for_label mask += np.where(elem == labeled_img, True, False) return mask