enlarge a curved arc with rounded edges, only from the rounded edge

2 views (last 30 days)
This is an imagesc of a segmented matrix of a curved cell and I want to enlarge it but only from the ends of the curve (red)
  4 Comments
DGM
DGM on 28 Sep 2024
So do you just want to extrapolate as if using the same stroke width as the rest of the blob? You know how little to expect of extrapolation?
gaandi
gaandi on 28 Sep 2024
Edited: gaandi on 28 Sep 2024
Yes, I want to extrapolate using the same stroke width as the rest of the blob. Extrapolate it to 1/8th (of the original blob) on each end.
This image is an imagesc output of multiple cells and i want to extend each of them. I have also attached the matrix that was used to generate this image.
Thanks again for your help!

Sign in to comment.

Answers (2)

Image Analyst
Image Analyst on 28 Sep 2024
Try bwskel then bwmorph to find the endpoints. Mask off a certain radius from the endpoints then use imdilate to grow them bigger, then AND the grown tips with the original binary image. Sorry I don't have more time to try it for you but give it a try.

Umar
Umar on 28 Sep 2024

Hi @gaandi,

To address your query effectively, let me break down the provided code

% Load the matrix
load('multiple_cells.mat'); % Assuming 'L' is loaded into workspace
% Display original image
figure;
imagesc(L);
colormap(gray);
title('Original Image');
axis equal;
% Define parameters
extension_length = size(L, 1) / 8; % Extending 1/8th of original blob
% Identify edges using Canny edge detection
edges = edge(L, 'Canny');
% Find endpoints of the curve (red region)
[y, x] = find(edges); % Get coordinates of edges
endpoints = [x, y]; % Store endpoints
% Initialize extended image matrix
extended_L = L; 
% Extrapolate from each endpoint
for i = 1:size(endpoints, 1)
  endpoint = endpoints(i, :);
    % Create angles for extrapolation based on curve direction
    theta = linspace(-pi/2, pi/2, 100); % Adjust angle for curvature
    % Calculate extended points for positive extension
    x_ext_pos = round(endpoint(1) + extension_length * cos(theta));
    y_ext_pos = round(endpoint(2) + extension_length * sin(theta));
    % Ensure we stay within bounds for positive extension
    valid_pos_indices = (x_ext_pos >= 1 & x_ext_pos <= size(L, 2)) & ...
                        (y_ext_pos >= 1 & y_ext_pos <= size(L, 1));
    % Extend the original matrix for positive extension
    extended_L(sub2ind(size(extended_L), y_ext_pos(valid_pos_indices), 
    x_ext_pos(valid_pos_indices))) = 255; 
    % Calculate extended points for negative extension
    x_ext_neg = round(endpoint(1) - extension_length * cos(theta));
    y_ext_neg = round(endpoint(2) - extension_length * sin(theta));
    % Ensure we stay within bounds for negative extension
    valid_neg_indices = (x_ext_neg >= 1 & x_ext_neg <= size(L, 2)) & ...
                        (y_ext_neg >= 1 & y_ext_neg <= size(L, 1));
    % Extend the original matrix for negative extension
    extended_L(sub2ind(size(extended_L), y_ext_neg(valid_neg_indices), 
    x_ext_neg(valid_neg_indices))) = 255; 
  end
% Display updated image
figure;
imagesc(extended_L);
colormap(gray);
title('Extended Image');
axis 

and provide you step by step instructions that how it meets the requirements set forth in the comments:

Loading and Displaying the Original Image

   load('multiple_cells.mat'); % Assuming 'L' is loaded into workspace
   figure;
   imagesc(L);
   colormap(gray);
   title('Original Image');
   axis equal;

For more information on imagesc function, please refer to

https://www.mathworks.com/help/matlab/ref/imagesc.html?s_tid=doc_ta

This segment loads the matrix containing the image data and displays it using imagesc,setting a grayscale colormap for better visualization.

Defining Parameters for Extrapolation

   extension_length = size(L, 1) / 8; % Extending 1/8th of original blob

Here, the code defines extension_length as one-eighth of the height of the original image, which directly relates to gaandi's request to extend each end by this proportion.

Edge Detection

   edges = edge(L, 'Canny');
   [y, x] = find(edges); % Get coordinates of edges
   endpoints = [x, y]; % Store endpoints

For more information on edge function,please refer to

https://www.mathworks.com/help/images/ref/edge.html

The Canny edge detection algorithm identifies edges within the segmented matrix. The subsequent find function extracts coordinates of these edges, which are crucial for identifying where to begin extrapolation (as noted in Matt J's comment).

Extrapolation from Each Endpoint

   for i = 1:size(endpoints, 1)
       endpoint = endpoints(i, :);
       theta = linspace(-pi/2, pi/2, 100); % Adjust angle for curvature
       % Calculate extended points for positive extension
       x_ext_pos = round(endpoint(1) + extension_length * cos(theta));
       y_ext_pos = round(endpoint(2) + extension_length * sin(theta));
       % Ensure we stay within bounds for positive extension
       valid_pos_indices = (x_ext_pos >= 1 & x_ext_pos <= size(L, 2)) & 
       ...
                           (y_ext_pos >= 1 & y_ext_pos <= size(L, 1));
       extended_L(sub2ind(size(extended_L), y_ext_pos(valid_pos_indices), 
       x_ext_pos(valid_pos_indices))) = 255; 
       % Calculate extended points for negative extension
       x_ext_neg = round(endpoint(1) - extension_length * cos(theta));
       y_ext_neg = round(endpoint(2) - extension_length * sin(theta));
       % Ensure we stay within bounds for negative extension
       valid_neg_indices = (x_ext_neg >= 1 & x_ext_neg <= size(L, 2)) & 
       ...
                           (y_ext_neg >= 1 & y_ext_neg <= size(L, 1));
       extended_L(sub2ind(size(extended_L), y_ext_neg(valid_neg_indices), 
       x_ext_neg(valid_neg_indices))) = 255; 
   end

This loop iterates over each endpoint found in the edge-detected image. For each endpoint:

  • It calculates potential new points to extend both positively and negatively based on the direction defined by `theta`, which represents angles around the endpoint.
  • Valid indices are checked to ensure that extrapolated points remain within image boundaries before they are added to `extended_L`, effectively extending both ends of each curve as requested by gaandi.

Displaying the Extended Image

   figure;
   imagesc(extended_L);
   colormap(gray);
   title('Extended Image');
   axis equal;

For more information on imageesc function, please refer to

https://www.mathworks.com/help/matlab/ref/imagesc.html

Finally, this section visualizes the newly created matrix with extended regions.

Please see attached.

As DGM pointed out, extrapolating shapes can be complex due to varying widths and orientations. The code employs a consistent stroke width by using a constant extension_length, ensuring that extensions remain uniform.

Please let us know if you have any further questions for us.

  9 Comments
gaandi
gaandi on 30 Sep 2024
Thank you @Umar for your effort and swift responses. I tried this out, but I am still not able to associate the focus with a cell, as it falls at the very edge of the DIC binary mask.
Again, what I really need is a way to create this, using matlab.
Umar
Umar on 30 Sep 2024
Edited: Umar on 1 Oct 2024

Hi @ gaandi,

Hope, this new improved code addresses several of the concerns raised in the comments regarding fluorescence detection in segmented cells. Below, I will break down how the code responds to the specific issues mentioned and suggest improvements for better accuracy and reliability.

fluorescence_data = load('/MATLAB   
Drive/multiple_cells.mat');  
fluorescence_image = fluorescence_data.L;   
figure;  
imshow(fluorescence_image, []); 
title('Fluorescence Image');
threshold = adaptthresh(fluorescence_image, 0.5); 
binary_mask = imbinarize(fluorescence_image, threshold);
binary_mask = imopen(binary_mask, strel('disk', 3)); 
binary_mask = imclose(binary_mask, strel('disk', 3));
[B,L] = bwboundaries(binary_mask, 'noholes'); 
labeled_cells = bwlabel(binary_mask); 
figure;  
imshow(label2rgb(labeled_cells));  
title('Labeled Cells');
cell_stats = regionprops(labeled_cells, 'Area'); 
fluorescent_stats = regionprops(labeled_cells .*   
binary_mask, 'Area'); 
area_fraction_fluorescent = [fluorescent_stats.Area] ./   
[cell_stats.Area];
figure; 
bar(area_fraction_fluorescent); 
xlabel('Cell ID'); 
ylabel('Area Fraction of Fluorescent Pixels'); 
title('Area Fraction of Fluorescent Pixels per Cell');
focus_sizes = [fluorescent_stats.Area];  
cell_lengths = [cell_stats.Area];   
correlation_coefficient = corrcoef(focus_sizes,   
cell_lengths);  
disp(['Correlation coefficient between focus size and cell 
length: ', num2str(correlation_coefficient(1,2))]);

Adaptive Thresholding for Binary Mask Creation

The code employs adaptive thresholding to create a binary mask from the fluorescence image:

threshold = adaptthresh(fluorescence_image, 0.5);
binary_mask = imbinarize(fluorescence_image, threshold);

This approach is beneficial as it adjusts the threshold based on local image characteristics, which can help in accurately capturing fluorescence even at the edges of cells. This method addresses the concern of excluding fluorescence that is located at the very edge of the DIC binary mask.

Morphological Operations

The subsequent morphological operations (imopen and imclose) are crucial for refining the binary mask:

binary_mask = imopen(binary_mask, strel('disk', 3)); %   
Remove small noise
binary_mask = imclose(binary_mask, strel('disk', 3)); % 

Close gaps

These operations help eliminate small noise and close gaps in the binary mask, which can further enhance the detection of fluorescence that may be partially included in the segmentation.

Contour Detection and Cell Labeling

Instead of relying solely on watershed segmentation, the code uses contour detection:

[B,L] = bwboundaries(binary_mask, 'noholes');
labeled_cells = bwlabel(binary_mask);

This method allows for a more accurate delineation of cell boundaries, which is essential for associating fluorescence with the correct cells, especially when they are in close proximity to one another.

Area Fraction Calculation

The code calculates the area fraction of fluorescent pixels per cell:

cell_stats = regionprops(labeled_cells, 'Area');
fluorescent_stats = regionprops(labeled_cells .* 
binary_mask, 'Area');
area_fraction_fluorescent = [fluorescent_stats.Area] ./ 
[cell_stats.Area];

This metric directly addresses the suggestion to use the area fraction of fluorescent pixels as a simpler and potentially more effective measure. By focusing on the area fraction, the code avoids the complications of individual cell segmentation and instead provides a bulk metric that can correlate with biological outcomes.

Correlation Analysis

The code also includes a correlation analysis between focus sizes and cell lengths:

correlation_coefficient = corrcoef(focus_sizes,   
cell_lengths);
disp(['Correlation coefficient between focus size and cell 
length: ', num2str(correlation_coefficient(1,2))]);

This analysis is critical for understanding the relationship between fluorescence intensity and cell dimensions, which can provide insights into the biological significance of the observed fluorescence.

Please see attached.

So, in nutshell, this provided updated MATLAB code now effectively addresses the comments regarding fluorescence detection within segmented cells. By utilizing adaptive thresholding, morphological operations, contour detection, and area fraction calculations, the code enhances the accuracy of fluorescence detection while simplifying the analysis process. Furthermore, the correlation analysis offers a pathway to explore the relationship between fluorescence and cell characteristics, which can be pivotal for future research.

Sign in to comment.

Tags

Products


Release

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!