Quantcast
Channel: Machine Learning | Towards AI
Viewing all articles
Browse latest Browse all 819

Nuclei Detection and Fluorescence Quantification in Python: A Step-by-Step Guide (Part 2)

$
0
0
Author(s): MicroBioscopicData (by Alexandros Athanasopoulos) Originally published on Towards AI. Welcome back to the second tutorial in our series, “Nuclei Detection and Fluorescence Quantification in Python.” In this tutorial, we will focus on measuring the fluorescence intensity from the GFP channel, extracting relevant data, and performing a detailed analysis to derive meaningful biological insights. To fully benefit from this tutorial, it’s helpful to have a basic understanding of Python programming as well as some familiarity with fluorescence microscopy, including the principles behind using fluorescent proteins like GFP (Green Fluorescent Protein). In the previous tutorial, we used images of fibroblast cells where the nuclei are labeled with DAPI, a fluorescent dye (blue channel) that binds to DNA, and a protein of interest that is present in both the cytoplasm and nucleus, detected in the green channel. We began by preprocessing the images to enhance data quality. We applied Gaussian smoothing with varying sigma values to reduce noise and used thresholding methods to effectively distinguish the nuclei from the background. Additionally, we discussed post-processing techniques, such as removing small artifacts, to further refine the segmentation results. The code below (from our first tutorial) effectively segments and visualizes nuclei in fluorescence microscopy images, offering clear insights into the distribution and intensity of the detected features. The next step in fluorescence quantification is to label the segmented nuclei. from skimage import io, filters, morphology, measure, segmentation, colorfrom skimage.measure import regionpropsimport numpy as npimport matplotlib.pyplot as pltimport pandas as pdimport seaborn as sns# Set option to display all columns and rows in Pandas DataFramespd.set_option('display.max_columns', None)pd.set_option('display.max_rows', None)# Load the multi-channel TIFF imageimage = io.imread('fibro_nuclei.tif')# Separate the GFP channel (assuming channel 0 is GFP)channel1 = image[:, 0, :, :] # GFP channel# Perform Maximum Intensity Projection (MIP) on GFP channelchannel1_max_projection = np.max(channel1, axis=0) # Separate the DAPI channel (assuming channel 1 is DAPI)channel2 = image[:, 1, :, :] # DAPI channel# Perform Maximum Intensity Projection (MIP) on DAPI channelchannel2_max_projection = np.max(channel2, axis=0) # Apply Gaussian smoothing to the DAPI MIPsmoothed_image = filters.gaussian(channel2_max_projection, sigma=5)# Apply Otsu's method to find the optimal threshold and create a binary maskthreshold_value = filters.threshold_otsu(smoothed_image)binary_mask = smoothed_image > threshold_value# Create subplots with shared x-axis and y-axisfig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(10, 10))# Visualize the Maximum Intensity Projection (MIP) for the DAPI channelax1.imshow(channel2_max_projection, cmap='gray')ax1.set_title('Maximum Intensity Projection (DAPI Channel)')# Visualize the binary mask obtained after thresholding the smoothed DAPI MIPax2.imshow(binary_mask, cmap='gray')ax2.set_title('Binary Mask (After Thresholding)')# Adjust layout to prevent overlapplt.tight_layout()# Display the plotsplt.show() Left Panel: This image shows the Maximum Intensity Projection (MIP) of the DAPI channel, which highlights the nuclei stained with DAPI (a blue fluorescent dye). Right Panel: This panel displays the binary mask generated after applying Otsu’s thresholding to the DAPI channel. Labeling the Segmented Nuclei Labeling the binary mask is a crucial step in image analysis. When we perform thresholding on an image, the result is a binary mask (see also our previous tutorial) where pixels are classified as either foreground/True (e.g., nuclei) or background/False. However, this binary mask alone doesn’t distinguish between different individual nuclei — it simply shows which pixels belong to the foreground and to the background. Labeling is the process of assigning a unique identifier (label) to each nucleus in the binary mask. In the context of connected components, labeling involves identifying and marking groups of connected pixels (components) that represent individual objects, such as nuclei, in the image. Once the binary mask is created, the connected components algorithm is applied. This algorithm scans the binary mask to detect groups of connected pixels using either 4-connectivity or 8-connectivity criteria (see below the image) and assigns a unique label to each connected component. Each label corresponds to a distinct nucleus in the image [1]. There are different types of connectivity, primarily 4-connectivity and 8-connectivity: 4-Connectivity: Definition: In 4-connectivity, a pixel (of interest) is considered connected to another pixel if they share an edge. In a 2D grid, each pixel has four possible neighbors: left, right, above, and below. Applications: 4-connectivity is often used in algorithms where diagonal connections are not considered, thus providing a more restrictive form of connectivity. 8-Connectivity: Definition: In 8-connectivity, a pixel (of interest) is connected to all of its neighbors, including those that share a vertex. This means that, in addition to the four edge-connected neighbors (as in 4-connectivity), the pixel is also connected to the four diagonal neighbors. Applications: 8-connectivity is used in applications where diagonal connections are significant, providing a more inclusive form of connectivity. Left Panel: In 4-connectivity, the pixel of interest (highlighted in red) is connected to its four direct neighbors (up, down, left, and right), which are shown in blue. Right Panel: In 8-connectivity, the pixel of interest (highlighted in red) is connected to its eight surrounding neighbors (up, down, left, right, and diagonals), which are shown in blue. Why Labeling is Important Identification: Labeling allows us to identify and differentiate between individual nuclei within the binary mask. Each nucleus has a unique label, which makes it possible to treat and analyze each nucleus separately. Analysis: Once the nuclei are labeled, we can measure various properties of each nucleus individually, such as area, perimeter, and fluorescence intensity… This is essential for quantitative analysis in biological research. Visualization: Labeling also facilitates the visualization of segmented nuclei. By assigning different colors or intensities to each label, we can easily see and distinguish the segmented nuclei in a labeled image. The code below is used to label connected regions (components) in our binary image. The function skimage.measure.label scans the binary mask and assigns a unique integer label to each connected component. The output is a labeled image (2D numpy array) where each connected component is assigned a unique integer label (e.g., 1, 2, 3, etc.). Pixels that belong to the same component (e.g., a single nucleus) will have the same label. By default, the function uses 8-connectivity. The function color.label2rgb(labeled_nuclei, bg_label=0) from the skimage.color module converts a labeled image into an RGB (color) image. labeled_nuclei: This is the labeled image […]

Viewing all articles
Browse latest Browse all 819

Trending Articles