def generate_morphology_metrics(true_labels, pred_labels, properties): properties_df = pd.DataFrame() for i in range(true_labels.shape[0]): true_label = true_labels[i, :, :, 0] pred_label = pred_labels[i, :, :, 0] if np.max(true_label) == 0 or np.max(pred_label) == 0: continue true_props_table = regionprops_table(true_label, properties=properties) pred_props_table = regionprops_table(pred_label, properties=properties) properties_dict = {} for prop in properties[1:]: true_prop, pred_prop = get_paired_regionprops( true_label=true_label, pred_label=pred_label, true_props_table=true_props_table, pred_props_table=pred_props_table, field=prop) properties_dict[prop + '_true'] = true_prop properties_dict[prop + '_pred'] = pred_prop properties_df = properties_df.append(pd.DataFrame(properties_dict)) return properties_df
def stack_label_images_to_tidy_df_ratio( label_img_stack, num_intensity_img_stack, denom_intensity_img_stack, properties=["label", "mean_intensity", "area", "centroid"], ): features = pd.DataFrame() for i, lab_img in enumerate(label_img_stack): df = pd.DataFrame( measure.regionprops_table( lab_img, intensity_image=img_as_uint(num_intensity_img_stack[i, :, :]), properties=properties, )) df["frame"] = i df.rename( columns={ "mean_intensity": "mean_intensity_num", "centroid-0": "y", "centroid-1": "x", }, inplace=True, ) df["mean_intensity_denom"] = pd.DataFrame( measure.regionprops_table( lab_img, intensity_image=img_as_uint( denom_intensity_img_stack[i, :, :]), properties=["mean_intensity"], )["mean_intensity"]) df["mean_intensity_num_denom"] = (df["mean_intensity_num"] / df["mean_intensity_denom"]) features = features.append(df) return features
def combine_label_images_return_df_of_regions(label_img_inner, label_img_outer, overlap_thresh=0.1): df_lab_inner = pd.DataFrame( measure.regionprops_table(label_img_inner, properties=("label", "bbox", "image"))) df_lab_outer = pd.DataFrame( measure.regionprops_table(label_img_outer, properties=("label", "bbox", "image"))) overlapping_labels = df_lab_inner.apply( cca.region_overlap, axis=1, label_img_outer=label_img_outer, label_img_inner=label_img_inner, overlap_thresh=overlap_thresh, ).unique() labels_in_outer_not_inner = np.unique(label_img_outer)[ ~np.isin(np.unique(label_img_outer), overlapping_labels)] combined_df_of_regions = pd.concat([ df_lab_inner, df_lab_outer.query("label in @labels_in_outer_not_inner") ]).reset_index(drop=True) combined_df_of_regions["label"] = combined_df_of_regions.index + 1 return combined_df_of_regions
def compute_morphology_metrics(true_labels, pred_labels, properties=None): if properties is None: properties = [ 'label', 'area', 'major_axis_length', 'minor_axis_length' ] prop_df = pd.DataFrame() for idx in range(true_labels.shape[0]): pred_label = pred_labels[idx, :, :, 0] true_label = true_labels[idx, :, :, 0] true_ids, pred_ids = get_paired_cell_ids(true_label=true_label, pred_label=pred_label) true_props_table = pd.DataFrame( regionprops_table(true_label, properties=properties)) pred_props_table = pd.DataFrame( regionprops_table(pred_label, properties=properties)) paired_df = get_paired_metrics(true_ids=true_ids, pred_ids=pred_ids, true_metrics=true_props_table, pred_metrics=pred_props_table) paired_df['img_num'] = idx prop_df = prop_df.append(paired_df) return prop_df
def remove_narrow_part(thresholded_image, narrow_constant=2): skel, distance = medial_axis(thresholded_image, return_distance=True) dist_on_skel = distance * skel contour_image = get_contour_image(thresholded_image) distance_no_border = get_complement_image(skel, contour_image) distance_no_border[np.where(distance_no_border < 0)] = 0 distance_no_border[np.where(distance > narrow_constant)] = 0 distance_labeled_image = measure.label(distance_no_border, connectivity=2) if len(np.unique(distance_labeled_image)) > 1: distance_region_props = measure.regionprops_table( distance_labeled_image, properties=('label', 'area', 'image')) result_image = np.zeros_like(distance_labeled_image) for i in range(len(distance_region_props['label'])): if distance_region_props['area'][i] < 2: distance_labeled_image[np.where( distance_labeled_image == distance_region_props['label'] [i])] = 0 result_image[np.where(distance_labeled_image > 0)] = 1 dilated_image = binary_dilation(result_image, square(narrow_constant + 1)) removed_narrow_part_image = get_complement_image( thresholded_image, dilated_image) removed_narrow_part_image[np.where(removed_narrow_part_image < 0)] = 0 return removed_narrow_part_image else: return thresholded_image
def createSpotsFromDecodedPixels(x_dim, y_dim, decoded_pixels_df, min_area=2, max_area=10000): # Create an empty image to store the gene labels in gene_labeled_image = np.zeros((y_dim, x_dim)) for row in decoded_pixels_df.itertuples(): gene_labeled_image[row.Y, row.X] = row.Gene_Label # aggregate the pixels with the same gene label using skimage.measure.label region_labeled_image, num_spots = label(gene_labeled_image, background=0, return_num=True) # Convert the found "spot" regions into a dataframe regions_table = regionprops_table(region_labeled_image, properties=("label", "area", "centroid")) regions_df = pd.DataFrame(regions_table) # Remove spots that only have an area of min_area and max_area regions_df = regions_df[(regions_df['area'] >= min_area) & (regions_df['area'] <= max_area)] regions_df['Y'] = [int(y) for y in list(regions_df['centroid-0'])] regions_df['X'] = [int(x) for x in list(regions_df['centroid-1'])] regions_df = regions_df.drop(columns=["centroid-0", "centroid-1"]) regions_df = regions_df.rename(columns={"label": "Spot_label"}) # combine with the decoded pixels dataframe to add gene name and barcode to the spots merged_df = regions_df.merge(decoded_pixels_df, on=["X", "Y"], how="left") return merged_df
def _centroids_from_single_arr( segmentation: Union[np.ndarray, Generator], properties: Tuple[str], frame: int, intensity_image: Optional[np.ndarray] = None, scale: Optional[Tuple[float]] = None, use_weighted_centroid: bool = False, ) -> np.ndarray: """Return the object centroids from a numpy array representing the image data.""" if np.sum(segmentation) == 0: return {} def _is_binary(x: np.ndarray) -> bool: return ((x == 0) | (x == 1)).all() if use_weighted_centroid and intensity_image is not None: CENTROID_PROPERTY = "weighted_centroid" else: CENTROID_PROPERTY = "centroid" if CENTROID_PROPERTY not in properties: properties = (CENTROID_PROPERTY, ) + properties # check to see whether this is a binary segmentation # TODO(arl): of course, this may also be ternary etc, so this will # fail, should really check that the labels are unique if _is_binary(segmentation): labeled = label(segmentation) else: labeled = segmentation _centroids = regionprops_table( labeled, intensity_image=intensity_image, properties=properties, ) # add time to the array _centroids['t'] = np.full(_centroids[f"{CENTROID_PROPERTY}-0"].shape, frame) # apply the anistropic scaling if scale is not None: if len(scale) != segmentation.ndim: raise ValueError("Scale dimensions do not match segmentation.") # perform the anistropic scaling for dim in range(segmentation.ndim): _centroids[f"{CENTROID_PROPERTY}-{dim}"] = np.multiply( _centroids[f"{CENTROID_PROPERTY}-{dim}"], float(scale[dim])) # now rename the axes for btrack dim_names = ["z", "y", "x"][-(segmentation.ndim):] for dim in range(segmentation.ndim): dim_name = dim_names[dim] _centroids[dim_name] = _centroids.pop(f"{CENTROID_PROPERTY}-{dim}") return _centroids
def autoencoder_postprocess(image, saveprops): ''' Arguments --------- image: np.array generates region properties for autoencoder-processed images Returns ------- regionlist: list. list of instance segmented regions label_image: np.array. labeled image mask of regions image_label_overlay: np.array. image with segmeneted regions overlaid ''' thresh = threshold_otsu(image) bw = closing(image < thresh) cleared = clear_border(bw) label_image = img_as_ubyte(label(cleared)) image_label_overlay = label2rgb(label_image, image=image, bg_label=0) # regionlist = regionprops(label_image) # regionlist = sorted(regionlist, key=lambda x: (x.centroid[0], (x.centroid[1]))) regiontable = pd.DataFrame(regionprops_table(label_image, properties = saveprops)) regiontable = regiontable.loc[regiontable['area'] > 1].reset_index(drop=True) # print(regiontable) return regiontable, label_image, image_label_overlay
def get_intensity_df(regions, rp_props_int, data, ch, bf=None): data.slices[data.axlab.index('c')] = slice(ch, ch + 1, 1) ch_data = data.slice_dataset() if bf is not None: bias = get_bias_field_block(bf, data.slices, ch_data.shape) bias = np.reshape(bias, ch_data.shape) ch_data /= bias ch_data = np.nan_to_num(ch_data, copy=False) try: rpt = regionprops_table(regions, ch_data, properties=rp_props_int) except ValueError: print('got ValueError on INT {}'.format(ch)) cols = [ 'ch{:02d}_{}'.format(ch, col) for col in get_column_names(rp_props_int) ] df_int = pd.DataFrame(columns=cols) else: df_int = pd.DataFrame(rpt) df_int.columns = [ 'ch{:02d}_{}'.format(ch, col) for col in get_column_names(rp_props_int) ] return df_int
def generate_props(mask, intensity_image_=None, dataframe=False, properties= ('label', 'centroid', 'mean_intensity', 'intensity_image', 'image', 'area', 'bbox')): """ converts binarized image into a list of region-properties using scikit-image first generates labels for the cleaned (binary_closing) binary image then generates regionprops on the remaining :param mask: np.ndarray binary version of cropped image :param intensity_image_: np.ndarray intensity image corresponding to this binary :param dataframe: bool return pandas dataframe instead of list of prop objects if true :return: list of skimage region-props object """ labels = measure.label(mask) if dataframe: props = measure.regionprops_table(labels, intensity_image=intensity_image_, properties=properties) props = pd.DataFrame(props) else: props = measure.regionprops(labels, intensity_image=intensity_image_) return props
def chcenters(accumMatrix, accumThresh): suppThreshold = accumThresh medFiltSize = 5 kernel = np.ones((medFiltSize, medFiltSize), np.float32) / medFiltSize**2 Hd = cv2.filter2D(accumMatrix, -1, kernel) suppThreshold = np.max((suppThreshold - np.spacing(suppThreshold), 0)) Hd = reconstruction(Hd - suppThreshold, Hd, method='dilation') lm = scipy.ndimage.filters.maximum_filter(Hd, size=3) bw = lm > np.max(lm) / 3 label_bw = label(bw) s = regionprops_table(label_bw, properties=['label', 'centroid']) centers = np.stack((s['centroid-0'], s['centroid-1'])) centers_int = np.asarray(centers, dtype=np.int64) metric = Hd[centers_int[0], centers_int[1]] # Sort the centers in descending order of metric metric_sorted = np.sort(metric)[::-1] sortIndx = np.argsort(metric) centers_sorted = np.fliplr( np.stack((np.take(centers[0, :], sortIndx), np.take(centers[1, :], sortIndx)))) return np.flipud(centers_sorted), metric_sorted
def detect_nuclei(image, size = 200): """Detect nuclei in image using binary operations Parameters ---------- image : 2D numpy array image to be segmented size: number maximal nucleus size Returns ------- newimage : 2D numpy array mask of nuclei """ # filtering image = skimage.filters.median(image,selem=np.ones((2,2))) # local thresholding image_local_threshold = skimage.filters.threshold_local(image,block_size=51) image_local = image > image_local_threshold # remove tiny features image_local_open = skimage.morphology.binary_opening(image_local, selem=skimage.morphology.disk(2)) # label image image_labeled = label(image_local_open) # analyze regions our_regions = regionprops_table(image_labeled, properties = ('label','area','coords')) # create a new mask with constraints on the regions to keep newimage = np.zeros(image.shape) # fill in using region coordinates for x in range(len(our_regions['area'])): if our_regions['area'][x] > size: newimage[our_regions['coords'][x][:,0],our_regions['coords'][x][:,1]] = 1 return newimage
def get_props(self): """ Extracts the image properties from the labeled image using scikit-image's regionprops """ # extract image properties props_table = measure.regionprops_table( self.labeled_img, intensity_image=self.original_gray, properties=[ 'area', 'centroid', 'major_axis_length', 'minor_axis_length', 'perimeter', 'eccentricity', 'solidity', 'mean_intensity', 'bbox' ]) nuclei_df = pd.DataFrame.from_dict(props_table) nuclei_df['centroid'] = nuclei_df[['centroid-0', 'centroid-1']].values.tolist() # add intensity by channel - BGR because openCV nuclei_df['meanI_B'] = [ np.mean(self.color_img[self.labeled_img == i, 0]) for i in range(len(nuclei_df)) ] nuclei_df['meanI_G'] = [ np.mean(self.color_img[self.labeled_img == i, 1]) for i in range(len(nuclei_df)) ] nuclei_df['meanI_R'] = [ np.mean(self.color_img[self.labeled_img == i, 2]) for i in range(len(nuclei_df)) ] # add major:minor axis ratio nuclei_df['major_to_minor'] = nuclei_df[ 'major_axis_length'] / nuclei_df['minor_axis_length'] return nuclei_df
def centerline_from_mask(image, meta): """ Finds centerline from mask. Could implement this if I'm feeling bold at some point NOT DONE INPUTS: image - Image data array meta - geotiff meta data OUTPUTS: out_img - cropped image array meta - updated geotiff meta """ # Reduce dimension of image image = image[0, :, :] # Get image shape h, w = image.shape # Remove any spurious small patches by only keeping the largest area labels = measure.label(image) props = pandas.DataFrame( measure.regionprops_table(labels, properties=( 'area', 'coords', ))) largest_prop = props[props['area'] == numpy.max(props['area'])] largest_coords = list(largest_prop['coords']) image = numpy.zeros(image.shape) for coord in largest_coords[0]: image[coord[0], coord[1]] = 1 return image[0, :, :], meta
def analyse_single(image, metadata, min_area, max_eccentricity): """This function is doing the following steps : 1. Perform Otsu thresholding 2. Binarize the image according to the threshold value 3. Close the holes in the particles 4. Get rid of particles located on the edge of the image 5. Labels the particles and measure their properties 6. Show the results and export them in a panda dataframe""" # apply threshold (Otsu) threshold = threshold_otsu(image) # Closing the holes in the binarized particles binary = closing(image > threshold, square(3)) # Remove artifacts connected to image border cleared = clear_border(binary) # label image regions label_image = label(cleared) # Export dataframe and sort on area and eccentricity thresholds props = skmeas.regionprops_table( label_image, image, properties=["label", "area", "eccentricity"] ) data = pd.DataFrame(props) data = data[(data["area"] > min_area) & (data["eccentricity"] < max_eccentricity)] # Extract the pixel/um value from the metadata scalebar = metadata["XResolution"].value[0] / metadata["XResolution"].value[1] # Calculate the diameter and the volume, and add 2 columns to data data["diameter"] = np.sqrt(4 * data["area"] / math.pi) / scalebar return data, threshold, binary, cleared, props, label_image
def generate_properties(im, props=PROPERTIES): """ Generates geometric properties for shapes in the binary input image Parameters ---------- im : TYPE DESCRIPTION. props : TYPE, optional DESCRIPTION Returns ------- X_train : TYPE DESCRIPTION. """ X_train = pd.DataFrame() labeled = label_2d(im) for i in range(labeled.shape[2]): sli = labeled[:,:,i] try: X_train = X_train.append(pd.DataFrame(measure.regionprops_table(sli, properties=props))) except IndexError: pass # happens when the slice has no regions in it return X_train
def __init__(self, spts_segmented, first_last_frame): rgp = regionprops_table(spts_segmented, properties=["label", "coords", "centroid"]) # properties of spots organized in a dictionary rgp_cc = regionprops(spts_segmented) # regionprops to measure the centroids coordinates (the prvious gives approximation of it) rgp_arr = [] for k in range(len(rgp["label"])): rgp_arr.append([rgp_cc[k]["label"], int(np.round(rgp_cc[k]["centroid"][0])), int(np.round(rgp_cc[k]["centroid"][1])), int(np.round(rgp_cc[k]["centroid"][2]))]) # array with not approximate centroids-coordinates and label rgp_arr = np.asarray(rgp_arr) # convert to array for k in range(rgp["label"].size): # substitute the approximated centroids-coordinates with the non approximated ones idx2subst = np.where(rgp_arr[:, 0] == rgp["label"][k])[0][0] # check the indexes of the label rgp["centroid-0"][k], rgp["centroid-1"][k], rgp["centroid-2"][k] = rgp_arr[idx2subst][1], rgp_arr[idx2subst][2], rgp_arr[idx2subst][3] # substitute centroids-coordinates with the proper not approximated ones idxs_dwn = np.where(rgp["centroid-0"] <= first_last_frame[0]) # select spots whos centroid is below a certain z-threshold idxs_up = np.where(rgp["centroid-0"] >= first_last_frame[1]) # select spots whos centroid is above a certain z-threshold idxs2rem = np.intersect1d(idxs_dwn, idxs_up) # join the 2 array of labels msk = np.zeros(spts_segmented.shape, dtype=np.int32) # initialize matrix to remove from the input for kk in idxs2rem: for kk_in in range(rgp["coords"][kk].shape[0]): msk[rgp["coords"][kk][kk_in][0], rgp["coords"][kk][kk_in][1], rgp["coords"][kk][kk_in][2]] = 1 # insert the spots by coordinates: it is B&W self.spts_selected = spts_segmented * (1 - msk)
def measure_properties(): masks_edgefree_list = sorted(os.listdir(masks_edgefree_path)) images_list = sorted(os.listdir(images_path)) for i, image in enumerate(images_list): fullpath_image = os.path.join(images_path, image) fullpath_mask = os.path.join(masks_edgefree_path, masks_edgefree_list[i]) if os.path.isfile(fullpath_image): img = io.imread(fullpath_image) print('loading image') mask = np.load(fullpath_mask) print('loading mask') props = measure.regionprops_table(mask, img, properties=[ 'label', 'area', 'equivalent_diameter', 'mean_intensity', 'max_intensity' ]) props = pd.DataFrame(props) props = props.assign(filename=image.split('_')[0]) print(props) results.append(props) return results
def get_feature_table(segm, img): '''Return feature table for labelled regions ----------------------------------------- Computes region properties for the labelled regions and returns all features except 'image', 'filled_image', 'convex_image', 'extent' and 'coords'. Parameters ---------- segm : array Labelled image array img : array Intensity image Returns ------- feat_df : DataFrame Table with region properties with 'image' and 'filled_image' excluded. ''' feats_out = regionprops(label_image=segm, intensity_image=img) keys = [k for k in feats_out[0]] exclude = ['convex_image', 'coords', 'extent', 'filled_image', 'image'] selected_keys = list(set(keys) - set(exclude)) # sort by key lexicographically selected_keys.sort() feat_dict = regionprops_table(segm, intensity_image=img, properties=selected_keys) feat_df = pd.DataFrame(feat_dict) return feat_df
def merge_areas(labels): props = regionprops_table(labels, properties=('label', 'area', 'major_axis_length', 'minor_axis_length')) df = pd.DataFrame(props) df['coef'] = df['major_axis_length'] / df['minor_axis_length'] area = df['area'].values coef = df['coef'].values unique = df['label'].values min_area = np.percentile(area, 2) print('Minimum area: ', min_area, 'and trees detected are ', len(df.index)) indice = np.where((coef > 3) | (area < min_area)) s_label = unique[indice] for i in range(len(s_label)): mask = labels == s_label[i] mask_d = binary_dilation(mask) mask_c = np.logical_xor(mask_d, mask) label = mode(np.ravel(labels[mask_c])).mode labels[mask] = label return labels
def find_boundry(dapi, dapi_t=50): # x10, y10 = [int(x/10) for x in dapi.shape] # img_10th = transform.resize(dapi,(x10,y10)) # x100, y100 = [int(x/10) for x in img_10th.shape] # img_100h = transform.resize(img_10th,(x100,y100)) # img_100h_padded = util.pad(img_100h,10) # edge_t = filters.threshold_otsu(img_100h_padded) # edges = feature.canny(img_100h_padded>edge_t,sigma=3) # edges = morphology.closing(edges,morphology.disk(3)) # dapi_boundry = ndi.binary_fill_holes(edges) # dapi_boundry = dapi_boundry[10:-10,10:-10] # dapi_boundry = transform.resize(dapi_boundry, (x10,y10)) # dapi_boundry = transform.resize(dapi_boundry, (dapi.shape)) # dapi_boundry = dapi_boundry boundry_masks = filters.gaussian(dapi > dapi_t, 4) * 1.0 boundry_masks = filters.gaussian(boundry_masks > 0, 4) * 1.0 boundry_masks = filters.gaussian(boundry_masks > 0, 4) * 1.0 labeled_boundry_masks = measure.label(boundry_masks) rps_table = pd.DataFrame( measure.regionprops_table(labeled_boundry_masks, properties=['label', 'area'])) mask_label = rps_table.loc[rps_table.area.idxmax(), 'label'] boundry_masks = labeled_boundry_masks == mask_label boundry_masks = ndi.binary_fill_holes(boundry_masks) img_border_mask_eroded = boundry_masks.copy() for i in range(dapi_t): img_border_mask_eroded = morphology.binary_erosion( img_border_mask_eroded, morphology.disk(2)) return img_border_mask_eroded
def get_cellprops(regions,intensity_imgtype2img,properties=['area', 'bbox_area', 'convex_area', 'eccentricity', 'equivalent_diameter', 'euler_number', 'extent', 'filled_area', 'label', 'major_axis_length', 'max_intensity', 'mean_intensity', 'min_intensity', 'minor_axis_length', 'orientation', 'perimeter', 'solidity', 'centroid']): from skimage.external import tifffile dn2df={} for imgtype in intensity_imgtype2img: df=pd.DataFrame(measure.regionprops_table(regions.astype(int), intensity_image=intensity_imgtype2img[imgtype], properties=properties)) df.index=df.index+1 dn2df[imgtype]=dmap2lin(df,coln='property',idxn='cell #') df=pd.concat(dn2df,axis=0,names=['image type']).droplevel(1)#.reset_index() return df
def __init__(self, spts, raw_data_spts): rgp = regionprops_table( spts, raw_data_spts, properties=["label", "intensity_image", "area"]) lbl_vol_ints_avints = [] for k in range(len(rgp["label"])): lbl_vol_ints_avints.append([ rgp["label"][k], rgp["area"][k], rgp["intensity_image"][k].sum(), rgp["intensity_image"][k].sum() / rgp["area"][k] ]) lbl_vol_ints_avints = np.asarray(lbl_vol_ints_avints) clusters_vol, ctrds = kmeans1d.cluster(lbl_vol_ints_avints[:, 1], 3) clusters_ints, ctrds = kmeans1d.cluster(lbl_vol_ints_avints[:, 2], 3) clusters_avints, ctrds = kmeans1d.cluster(lbl_vol_ints_avints[:, 3], 3) clusters_vol = np.asarray(clusters_vol) clusters_ints = np.asarray(clusters_ints) clusters_avints = np.asarray(clusters_avints) idxs = np.where(clusters_vol + clusters_ints + clusters_avints == 6)[0] ts_mtx = np.zeros(spts.shape, dtype=np.int32) for k in idxs: ts_mtx += int(lbl_vol_ints_avints[k, 0]) * (spts == int( lbl_vol_ints_avints[k, 0])) self.ts_mtx = ts_mtx
def get_cellprops(regions,intensity_imgtype2img,properties=['area', 'bbox_area', 'convex_area', 'eccentricity', 'equivalent_diameter', 'euler_number', 'extent', 'filled_area', 'label', 'major_axis_length', 'max_intensity', 'mean_intensity', 'min_intensity', 'minor_axis_length', 'orientation', 'perimeter', 'solidity', 'centroid']): dn2df={} for imgtype in intensity_imgtype2img: df=pd.DataFrame(measure.regionprops_table(regions.astype(int), intensity_image=intensity_imgtype2img[imgtype], properties=properties)) df.index=df.index+1 df.index.name='cell #' dn2df[imgtype]=df.melt(ignore_index=False,var_name='property').reset_index() df=pd.concat(dn2df,axis=0,names=['image type']).reset_index(0) return df
def MaskIDs(mask, mask_props=None): """This function will extract the CellIDs and the XY positions for each cell based on that cells centroid Returns a dictionary object""" all_mask_props = set([ "label", "centroid", "area", "major_axis_length", "minor_axis_length", "eccentricity", "solidity", "extent", "orientation" ]) if mask_props is not None: all_mask_props = all_mask_props.union(mask_props) dat = measure.regionprops_table(mask, properties=all_mask_props) name_map = { "CellID": "label", "X_centroid": "centroid-1", "Y_centroid": "centroid-0", "Area": "area", "MajorAxisLength": "major_axis_length", "MinorAxisLength": "minor_axis_length", "Eccentricity": "eccentricity", "Solidity": "solidity", "Extent": "extent", "Orientation": "orientation", } for new_name, old_name in name_map.items(): dat[new_name] = dat[old_name] for old_name in set(name_map.values()): del dat[old_name] return dat
def measure_rois(mask, image, file_id, threshold=0.5, min_pixel=30, properties=['mean_intensity', 'label', 'area']): 'Measure regions and return region properties' if mask.ndim == 3: mask = np.squeeze(mask, axis=2) # apply threshold to mask bw = (mask > threshold).astype(int) # label image regions label_image = label(bw, connectivity=2) # Falk p.13, 8-“connectivity”. # remove areas < min pixel unique, counts = np.unique(label_image, return_counts=True) label_image[np.isin(label_image, unique[counts < min_pixel])] = 0 # re-label image label_image, _, _ = relabel_sequential(label_image, offset=1) # measure region props if label_image.max() > 0: props_inner = regionprops_table(label_image, image, properties=properties) df = pd.DataFrame(props_inner) else: df = pd.DataFrame(np.nan, index=[0], columns=properties) df['ID'] = file_id return (df)
def measure_curvature_features( binary_image:np.ndarray, step:int = 2, prominance:float = 0.1, width:int = 5, dist_bt_peaks:int =10): """Comupte all curvature features This function computes all features that describe the local boundary features Args: binary_image:(image_array) Binary image step: (integer) Step size used to obtain the vertices, use larger values for a smoother curvatures prominance: (numeric) minimal required prominance of peaks (Default=0.1) width: (numeric) minimum width required of peaks (Deafult=5) dist_bt_peaks: (numeric) required minimum distance between peaks (Default=10) Returns: A pandas dataframe with all the features for the given image """ r_c = local_radius_curvature(binary_image, step, False) # calculate local curvature features local_curvature = np.array([ np.divide(1, r_c[x]) if r_c[x] != 0 else 0 for x in range(len(r_c)) ]) feat ={} feat.update(global_curvature_features(local_curvatures = local_curvature)) feat.update(prominant_curvature_features(local_curvatures = local_curvature, min_prominance = prominance, min_width = width, dist_bwt_peaks = dist_bt_peaks)) feat = pd.DataFrame([feat]) foo = (measure.regionprops_table(binary_image.astype(int),properties=["perimeter"])) perimeter = float(foo["perimeter"]) feat["frac_peri_w_posi_curvature"] = (feat["len_posi_curv"].replace(to_replace="NA", value=0)/ perimeter) feat["frac_peri_w_neg_curvature"] = (feat["len_neg_curv"].replace(to_replace="NA", value=0)/perimeter) feat["frac_peri_w_polarity_changes"] = (feat["npolarity_changes"] / perimeter) return feat
def find_GUVs_in_all_frames(self): self.frames_filled = [] dfcols = ('frame', 'x', 'y', 'r', 'area', 'ar') self.frames_regions = pd.DataFrame(columns=dfcols) for i, frame in enumerate(self.frames): self.frames_filled.append( helpers.process_find_edges(frame, self.params)) frame_regions = regionprops_table( label(self.frames_filled[i]), properties=('centroid', 'major_axis_length', 'minor_axis_length', 'area')) if frame_regions: # rename columns and delete old ones frame_regions['x'] = frame_regions['centroid-1'] frame_regions['y'] = frame_regions['centroid-0'] del frame_regions['centroid-0'] del frame_regions['centroid-1'] # initialize dataframe for easier merging and data storage frame_regions_df = pd.DataFrame(frame_regions) frame_regions_df['minor_axis_length'].apply(lambda x: 1. if x == 0. else x) frame_regions_df['ar'] = frame_regions_df[ 'major_axis_length'] / frame_regions_df['minor_axis_length'] frame_regions_df = frame_regions_df.drop( columns=['minor_axis_length', 'major_axis_length']) frame_regions_df['r'] = np.sqrt(frame_regions_df['area'] / np.pi) frame_regions_df['frame'] = i # append to dataframe that holds all GUVs self.frames_regions = self.frames_regions.append( helpers.filter_GUV_dataframe(frame_regions_df, self.params), ignore_index=True)
def getnewMask(seg_file,dilation,WS_outfile,WS_transfile,WS_maskImage): temp = np.asarray(np.load(seg_file,allow_pickle=True)).item() masks_1 = temp['masks'] im = np.zeros_like(np.array(masks_1)) points_frame = pd.DataFrame(measure.regionprops_table(masks_1, properties=['label','centroid'])) pointList = np.array(points_frame.iloc[:,-2:].astype(int)) for x in range(pointList.shape[0]): im[pointList[x,0],pointList[x,1]] = 1 masks = temp['masks']>0 masks=morphology.dilation(masks,morphology.disk(dilation)) secmask = np.zeros(masks.shape, dtype=bool) secmask[tuple(pointList.T)] = True secmask = morphology.dilation(secmask,morphology.square(3)) markers, _ = ndi.label(secmask) labels = segmentation.watershed( -im, markers, mask=(masks>0)) np.save(WS_outfile, labels, allow_pickle=True, fix_imports=True) points_frame['newLabel'] = [labels[pointList[x,0],pointList[x,1]] for x in range(pointList.shape[0])] points_frame.to_csv(WS_transfile) io.imsave(WS_maskImage, segmentation.find_boundaries(labels))
def measure(input: Image, labels: Image): from skimage.measure import regionprops_table table = regionprops_table(labels.data.astype(int), intensity_image=input.data, properties=('area', 'centroid', 'mean_intensity')) dock_widget = table_to_widget(table) viewer.window.add_dock_widget(dock_widget, area='right')