Extracting metrics from cellular pattern
2 views (last 30 days)
Show older comments
I'm trying to determine the width, height, area, and centroid of an scaly pattern shown in the attached image. I've tried using a gradient filter, edge detection, (see attached images) and various other functions, but the problem is I'm not able to get the edges to meet up and complete the cell pattern to where I can discern each cell as a separate object using, say, the regionprops function. I was hoping to get some guidance as to whether there are specific functions or established pre-processing steps I need in order to get the image in this format. Thanks in advance for any help!
2 Comments
Image Analyst
on 14 Sep 2024
I'm not exactly sure where the boundaries of the cell would be. In general, yes, in a very rough sense but not if you want it to be accurate down to the nearest pixel. Can you post an annotated one where you've drawn in the outlines, say, in red?
Would you be willing to place markers or points on the vertices of the cells? If so, a human assisted algorithm might work and be faster than trying to develop an automated algorithm, especially if you have only a handful of images, not thousands of them.
Accepted Answer
Image Analyst
on 16 Sep 2024
Try this:
clear all; close all; clc
% Load the synthetic detonation pattern image
gray_image = imread('CellularPattern_Test.png');
% Step 1: Convert to grayscale (if the image is RGB)
if size(gray_image, 3) == 3
gray_image = rgb2gray(gray_image);
end
hFig1 = figure('Name', 'Analysis by Image Analyst');
subplot(2, 3, 1);
imshow(gray_image);
title('Original Image')
[gradMag] = imgradient(gray_image);
subplot(2, 3, 2);
imshow(gradMag, []);
title('Gradient Magnitude')
subplot(2, 3, 3);
histogram(gradMag)
grid on;
threshold = 35;
xline(threshold, 'Color', 'r', 'LineWidth', 2)
binaryGrad = gradMag > threshold;
subplot(2, 3, 4);
imshow(binaryGrad, []);
impixelinfo
title('Gradient Magnitude above threshold')
binaryGrad = imdilate(binaryGrad,strel('disk', 2));
subplot(2, 3, 5);
imshow(binaryGrad);
title('Binary Image after Dilation')
% Get areas of blobs
props = regionprops(binaryGrad, 'Area')
subplot(2, 3, 6);
allAreas = sort([props.Area], 'ascend')
histogram(allAreas, 1000);
title('Histogram of blob areas')
% Remove very small components (noise) if necessary
% Use bwareaopen to remove small components (e.g., areas smaller than 1000 pixels)
binaryGrad = bwareafilt(binaryGrad, 1);
subplot(2, 3, 6);
imshow(binaryGrad);
title('Binary Image after Size Filter');
% Invert the image and remove blobs touching the border (partial blobs).
mask = imclearborder(~binaryGrad);
hfig2 = figure('Name', 'Analysis by Image Analyst');
subplot(2, 3, 1);
imshow(mask);
title('Individual Cells');
hfig2.WindowState = 'maximized';
% Shrink blobs to disconnect them.
se = strel('disk', 3, 0);
mask = imerode(mask, se);
% Grow them back out but don't let them reconnect.
mask = bwmorph(mask, 'thicken', 3);
% Get areas of blobs
props = regionprops(mask, 'Area')
subplot(2, 3, 2);
allAreas = sort([props.Area], 'ascend')
histogram(allAreas, 1000);
grid on;
title('Histogram of blob areas')
% Get rid of small blobs.
mask = bwareafilt(mask, [1000, inf]);
% Fill holes and get convex hull
mask = bwconvhull(mask, 'objects', 4);
subplot(2, 3, 3);
imshow(mask);
title('Individual Cells');
% Label each blob with 8-connectivity, so we can make measurements of it
[labeledImage, numberOfBlobs] = bwlabel(mask, 8);
% Apply a variety of pseudo-colors to the regions.
coloredLabelsImage = label2rgb (labeledImage, 'hsv', 'k', 'shuffle');
% Display the pseudo-colored image.
imshow(coloredLabelsImage);
% Get areas of blobs
props = regionprops(mask, 'Area')
subplot(2, 3, 4);
allAreas = sort([props.Area], 'ascend')
histogram(allAreas, 1000);
grid on;
title('Histogram of final blob areas')
% Get boundaries and display them over original image.
boundaries = bwboundaries(mask);
subplot(2, 3, 5:6);
imshow(gray_image);
title('Individual Cells');
hold on;
visboundaries(boundaries);
More Answers (1)
Image Analyst
on 14 Sep 2024
I think I can get fairly close. Can you give the code where you start with the image and get the binary/segmented image of the edges? Then I will try inverting the image and calling imerode and then bwmorph to grow them back out without joining them. Then call imclearborder (to get rid of partial blobs) and regionprops (to measure parameters).
By the way, you might like to look at my attached average cell shape demo, and my edge linking demo.
See Also
Categories
Find more on Image Processing Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!