csi_images.csi_images
1import numpy as np 2import pandas as pd 3from skimage.measure import regionprops_table 4 5 6def extract_mask_info( 7 mask: np.ndarray, 8 images: list[np.ndarray] = None, 9 image_labels: list[str] = None, 10 properties: list[str] = None, 11) -> pd.DataFrame: 12 """ 13 Extracts events from a mask. Originated from @vishnu 14 :param mask: mask to extract events from 15 :param images: list of intensity images to extract from 16 :param image_labels: list of labels for images 17 :param properties: list of properties to extract in addition to the defaults: 18 label, centroid, axis_major_length. See 19 https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops 20 for additional properties. 21 :return: pd.DataFrame with columns: id, x, y, size, or an empty DataFrame 22 """ 23 # Return empty if the mask is empty 24 if np.max(mask) == 0: 25 return pd.DataFrame() 26 # Reshape any intensity images 27 if images is not None: 28 if isinstance(images, list): 29 images = np.stack(images, axis=-1) 30 if image_labels is not None and len(image_labels) != images.shape[-1]: 31 raise ValueError("Number of image labels must match number of images.") 32 # Accumulate any extra properties 33 base_properties = ["label", "centroid", "axis_major_length"] 34 if properties is not None: 35 properties = base_properties + properties 36 else: 37 properties = base_properties 38 39 # Use skimage.measure.regionprops_table to compute properties 40 info = pd.DataFrame( 41 regionprops_table(mask, intensity_image=images, properties=properties) 42 ) 43 44 # Rename columns to match desired output 45 info = info.rename( 46 columns={ 47 "label": "id", 48 "centroid-0": "y", 49 "centroid-1": "x", 50 "axis_major_length": "size", 51 }, 52 ) 53 renamings = {} 54 for column in info.columns: 55 for i in range(len(image_labels)): 56 suffix = f"-{i}" 57 if column.endswith(suffix): 58 renamings[column] = f"{image_labels[i]}_{column[:-len(suffix)]}" 59 info = info.rename(columns=renamings) 60 61 return info 62 63 64def make_rgb( 65 images: list[np.ndarray], colors=list[tuple[float, float, float]] 66) -> np.ndarray: 67 """ 68 Combine multiple channels into a single RGB image. 69 :param images: list of numpy arrays representing the channels. 70 :param colors: list of RGB tuples for each channel. 71 :return: 72 """ 73 if len(images) == 0: 74 raise ValueError("No images provided.") 75 if len(colors) == 0: 76 raise ValueError("No colors provided.") 77 if len(images) != len(colors): 78 raise ValueError("Number of images and colors must match.") 79 if not all([isinstance(image, np.ndarray) for image in images]): 80 raise ValueError("Images must be numpy arrays.") 81 if not all([len(c) == 3 for c in colors]): 82 raise ValueError("Colors must be RGB tuples.") 83 84 # Create an output with same shape and larger type to avoid overflow 85 dims = images[0].shape 86 dtype = images[0].dtype 87 if dtype not in [np.uint8, np.uint16]: 88 raise ValueError("Image dtype must be uint8 or uint16.") 89 rgb = np.zeros((*dims, 3), dtype=np.uint16 if dtype == np.uint8 else np.uint32) 90 91 # Combine images with colors (can also be thought of as gains) 92 for image, color in zip(images, colors): 93 if image.shape != dims: 94 raise ValueError("All images must have the same shape.") 95 if image.dtype != dtype: 96 raise ValueError("All images must have the same dtype.") 97 rgb[..., 0] += (image * color[0]).astype(rgb.dtype) 98 rgb[..., 1] += (image * color[1]).astype(rgb.dtype) 99 rgb[..., 2] += (image * color[2]).astype(rgb.dtype) 100 101 # Cut off any overflow and convert back to original dtype 102 rgb = np.clip(rgb, np.iinfo(dtype).min, np.iinfo(dtype).max).astype(dtype) 103 return rgb
def
extract_mask_info( mask: numpy.ndarray, images: list[numpy.ndarray] = None, image_labels: list[str] = None, properties: list[str] = None) -> pandas.core.frame.DataFrame:
7def extract_mask_info( 8 mask: np.ndarray, 9 images: list[np.ndarray] = None, 10 image_labels: list[str] = None, 11 properties: list[str] = None, 12) -> pd.DataFrame: 13 """ 14 Extracts events from a mask. Originated from @vishnu 15 :param mask: mask to extract events from 16 :param images: list of intensity images to extract from 17 :param image_labels: list of labels for images 18 :param properties: list of properties to extract in addition to the defaults: 19 label, centroid, axis_major_length. See 20 https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops 21 for additional properties. 22 :return: pd.DataFrame with columns: id, x, y, size, or an empty DataFrame 23 """ 24 # Return empty if the mask is empty 25 if np.max(mask) == 0: 26 return pd.DataFrame() 27 # Reshape any intensity images 28 if images is not None: 29 if isinstance(images, list): 30 images = np.stack(images, axis=-1) 31 if image_labels is not None and len(image_labels) != images.shape[-1]: 32 raise ValueError("Number of image labels must match number of images.") 33 # Accumulate any extra properties 34 base_properties = ["label", "centroid", "axis_major_length"] 35 if properties is not None: 36 properties = base_properties + properties 37 else: 38 properties = base_properties 39 40 # Use skimage.measure.regionprops_table to compute properties 41 info = pd.DataFrame( 42 regionprops_table(mask, intensity_image=images, properties=properties) 43 ) 44 45 # Rename columns to match desired output 46 info = info.rename( 47 columns={ 48 "label": "id", 49 "centroid-0": "y", 50 "centroid-1": "x", 51 "axis_major_length": "size", 52 }, 53 ) 54 renamings = {} 55 for column in info.columns: 56 for i in range(len(image_labels)): 57 suffix = f"-{i}" 58 if column.endswith(suffix): 59 renamings[column] = f"{image_labels[i]}_{column[:-len(suffix)]}" 60 info = info.rename(columns=renamings) 61 62 return info
Extracts events from a mask. Originated from @vishnu
Parameters
- mask: mask to extract events from
- images: list of intensity images to extract from
- image_labels: list of labels for images
- properties: list of properties to extract in addition to the defaults: label, centroid, axis_major_length. See https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops for additional properties.
Returns
pd.DataFrame with columns: id, x, y, size, or an empty DataFrame
def
make_rgb( images: list[numpy.ndarray], colors=list[tuple[float, float, float]]) -> numpy.ndarray:
65def make_rgb( 66 images: list[np.ndarray], colors=list[tuple[float, float, float]] 67) -> np.ndarray: 68 """ 69 Combine multiple channels into a single RGB image. 70 :param images: list of numpy arrays representing the channels. 71 :param colors: list of RGB tuples for each channel. 72 :return: 73 """ 74 if len(images) == 0: 75 raise ValueError("No images provided.") 76 if len(colors) == 0: 77 raise ValueError("No colors provided.") 78 if len(images) != len(colors): 79 raise ValueError("Number of images and colors must match.") 80 if not all([isinstance(image, np.ndarray) for image in images]): 81 raise ValueError("Images must be numpy arrays.") 82 if not all([len(c) == 3 for c in colors]): 83 raise ValueError("Colors must be RGB tuples.") 84 85 # Create an output with same shape and larger type to avoid overflow 86 dims = images[0].shape 87 dtype = images[0].dtype 88 if dtype not in [np.uint8, np.uint16]: 89 raise ValueError("Image dtype must be uint8 or uint16.") 90 rgb = np.zeros((*dims, 3), dtype=np.uint16 if dtype == np.uint8 else np.uint32) 91 92 # Combine images with colors (can also be thought of as gains) 93 for image, color in zip(images, colors): 94 if image.shape != dims: 95 raise ValueError("All images must have the same shape.") 96 if image.dtype != dtype: 97 raise ValueError("All images must have the same dtype.") 98 rgb[..., 0] += (image * color[0]).astype(rgb.dtype) 99 rgb[..., 1] += (image * color[1]).astype(rgb.dtype) 100 rgb[..., 2] += (image * color[2]).astype(rgb.dtype) 101 102 # Cut off any overflow and convert back to original dtype 103 rgb = np.clip(rgb, np.iinfo(dtype).min, np.iinfo(dtype).max).astype(dtype) 104 return rgb
Combine multiple channels into a single RGB image.
Parameters
- images: list of numpy arrays representing the channels.
- colors: list of RGB tuples for each channel.