apply region growing code to my image

Hi! I am using this code (see link) although it is a bit old. The example given by the author works:
load example
figure, imshow(cIM, [0 1500]), hold all
poly = regionGrowing(cIM, [], 300); % click somewhere inside the lungs
plot(poly(:,1), poly(:,2), 'LineWidth', 2)
I would like to do the same with my image (example_my.jpg) getting the output on the right.
Is there any parameter I should change?
It always leads me to an error but I can't find a solution.
cIM_1 = im2double(imread('example_my.jpg'));
% grayImage = rgb2gray(cIM_1);
% J = im2uint16(grayImage);
% imshow(J)
figure, imshow(cIM_1, [0 1500]), hold all
poly = regionGrowing(cIM_1, [], 300); % click somewhere inside the lungs
plot(poly(:,1), poly(:,2), 'LineWidth', 2)

10 Comments

That code was last updated 12 years ago.
It didn't warn you that it was treating your image as 3D. I don't fully understand what it is trying to do with the axis2pix function, so I can't easily debug that for you.
I would suggest using my RegGrow function instead, and salvage the second loop that converts the volume to a polygon. Note that my function will also treat your image as 3D unless you convert it explicitly to 2D.
Thank you for your answer @Rik!
I have modified the question so that it is clearer.
Yes I saw that it is a bit old the code I reported, but your example works and I was trying to get a similar result.
With your code how can I achieve this result? Possibly by highlighting the part inside the red curve in the figure to the right of my question (output)?
cIM_1 = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1275885/example_my.jpg');
mask = RegGrow(cIM_1(:,:,1),'seed',[188 114],'MaxDiff',20);
That will give you a binary mask of the area marked in your question:
imshow(imfuse(cIM_1(:,:,1),mask))
Now you only need to fill the mask and determine a polygon, for which you can use the code in the submission you already found.
Did this solve your issue? Which part should I move to the answer section? Or do you have questions remaining?
Yes I would have this last question. If I want to merge multiple 'masks' and display the pixels as 'white' I used this code but it does not give the desired result. How can I do this?
cIM_1 = imread('example_my.jpg');
figure
imshow(cIM_1)
impixelinfo
figure
mask_1 = RegGrow(cIM_1(:,:,1),'seed',[188 114],'MaxDiff',20);
mask_2 = RegGrow(cIM_1(:,:,1),'seed',[64 100],'MaxDiff',20);
A = imfuse(cIM_1(:,:,1),mask_1);
B = imfuse(cIM_1(:,:,1),mask_2);
C = imfuse(A, B);
imshow(C)
L = logical(C);
pixel_w = imoverlay(cIM_1, L(:,:,1), 'w');
figure
imshow(pixel_w)
impixelinfo
I don't understand exactly what you want to do, but perhaps you mean that you want to merge the masks? You can do that easily with the pipe symbol (i.e., |), since those masks are simply logical arrays.
Perfect, I succeeded!
Not sure why you even need to do region growing. My simple thresholding method, shown below in the Answer section, works fine to get those two blobs.
Hello @Rik! I wanted to insert the x and y coordinates in your code
mask = RegGrow(cIM_1(:,:,1),'seed',[y x],'MaxDiff',20);
with the command
[x,y] = ginput(1);
but it gives me the following error:
The seed must be a vector with a valid position.
Could you tell me how to solve it? Thanks!
You might need to round the coordinates to make the indices valid.

Sign in to comment.

 Accepted Answer

Try this:
% Demo by Image Analyst
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
markerSize = 40;
%--------------------------------------------------------------------------------------------------------
% READ IN TEST IMAGE
folder = [];
baseFileName = 'example_my.jpg';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage)
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
fprintf('It is not really gray scale like we expected - it is color\n');
% Extract the blue channel.
grayImage = rgb2gray(grayImage);
end
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(2, 2, 1);
imshow(grayImage, []);
impixelinfo;
axis('on', 'image');
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Update the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage)
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
drawnow;
%--------------------------------------------------------------------------------------------------------
% Display histogram
subplot(2, 2, [2, 4]);
histogram(grayImage);
grid on;
title('Histogram of Image', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% Threshold to create mask
lowThreshold = 31;
highThreshold = 255;
% Interactively and visually set a threshold on a gray scale image.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
% [lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage);
mask = grayImage >= lowThreshold & grayImage <= highThreshold;
xline(lowThreshold, 'Color', 'r', 'LineWidth', 2)
% Get rid of blobs touching the border.
% mask = imclearborder(mask);
% Take 2 largest blobs.
mask = bwareafilt(mask, 2);
% Fill the blobs.
% mask = imfill(mask, 'holes');
subplot(2, 2, 3);
imshow(mask);
impixelinfo;
axis('on', 'image');
title('Mask Image', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% Get the areas, diameters, and centroids.
props = regionprops(mask, 'Area', 'Centroid', 'EquivDiameter')
if isempty(props)
warningMessage = 'No blobs found!'
uiwait(warndlg(warningMessage));
return;
end
allAreas = [props.Area]
allDiameters = [props.EquivDiameter]
xy = vertcat(props.Centroid)
% Plot centroids on image as red crosshairs
xCentroids = xy(:, 1);
yCentroids = xy(:, 2);
hold on;
plot(xCentroids, yCentroids, 'r+', 'LineWidth', 3, 'MarkerSize', 20)

10 Comments

Thank you for your reply. Actually your code is much more effective, only I have to adjust the values of lowThreshold and highThreshold and this is not good if for example I want to display only the bottom mask (excluding the top mask)
If you want the lowest one you can do
[~, index] = max(yCentroids); % Get index of max y value (max row so lowest blob).
labeledImage = bwlabel(mask);
mask = ismember(labeledImage, index); % Mask will have only the lowest blob.
Okay, thank you! Your code is definitely helpful, but at the moment it would be more useful if you could indicate the pixel coordinates so that you can then create the mask as in the code below. Could you tell me how I can do this using your code?
cIM_1 = imread('example_my.jpg');
figure
imshow(cIM_1)
impixelinfo
figure
mask_1 = RegGrow(cIM_1(:,:,1),'seed',[188 114],'MaxDiff',20);
mask_2 = RegGrow(cIM_1(:,:,1),'seed',[64 100],'MaxDiff',20);
A = imfuse(cIM_1(:,:,1),mask_1 | mask_2);
imshow(A)
L = logical(A);
pixel_w = imoverlay(cIM_1, L(:,:,1), 'w');
figure
imshow(pixel_w)
impixelinfo
I don't have RegGrow but if you want just the lower mask, just get mask_1, not mask_2.
I know that it is enough to indicate the mask I want.
My question was whether with your code it is possible to identify the mask by selecting a pixel and not by imposing Treshold values.
Region growing is essentially picking a point and then enlarging the region subject to some constraints. It looks like in your application the constraint is a certain number of gray levels darker than the selected point, and a certain number of gray levels brighter than the selected point. This is essentially just thresholding the image within that lower and upper graylevel (like I did). But that would apply to the whole image and possibly produce additional regions not connected to the point you picked. So to get rid of those you would use bwselect and give it the coordinate you clicked on. That would pick out only the blob that you clicked on.
It's not possible to do it by not "imposing Treshold values". Even with region growing, you have to specify a gray scale range. If you don't how do you know where to stop growing the region into.
Where should I enter the bwselect command ?
You asked is it "possible to identify the mask by selecting a pixel", so you enter that pixel row and column into the function. You can use ginput() to get the location
[x,y] = ginput(1)
R = round(y)
C = round(x)
help bwselect
BWSELECT Select objects in binary image. BW2 = BWSELECT(BW1,C,R,N) returns a binary image containing the objects that overlap the pixel (R,C). R and C can be scalars or equal-length vectors. If R and C are vectors, BW2 contains the set of objects overlapping with any of the pixels (R(k),C(k)). N can have a value of either 4 or 8 (the default), where 4 specifies 4-connected objects and 8 specifies 8-connected objects. Objects are connected sets of "on" pixels (i.e., having value of 1). BW2 = BWSELECT(BW1,N) displays the image BW1 on the screen and lets you select the (R,C) coordinates using the mouse. If you omit BW1, BWSELECT operates on the image in the current axes. Use normal button clicks to add points. Pressing <BACKSPACE> or <DELETE> removes the previously selected point. A shift-click, right-click, or double-click selects the final point; pressing <RETURN> finishes the selection without adding a point. [BW2,IDX] = BWSELECT(...) returns the linear indices of the pixels belonging to the selected objects. BW2 = BWSELECT(X,Y,BW1,Xi,Yi,N) uses the vectors X and Y to establish a nondefault spatial coordinate system for BW1. Xi and Yi are scalars or equal-length vectors that specify locations in this coordinate system. [X,Y,BW2,IDX,Xi,Yi] = BWSELECT(...) returns the XData and YData in X and Y; the output image in BW2; linear indices of the pixels belonging to the selected objects in IDX; and the specified spatial coordinates Xi and Yi. If bwselect is called with no output arguments, the resulting image is displayed in a new figure. Class Support ------------- The input image BW1 can be logical or any numeric type and must be 2-D and nonsparse. The output image BW2 is logical. Example ------- BW1 = imread('text.png'); c = [126 187 11]; r = [34 172 20]; BW2 = bwselect(BW1,c,r,4); figure, imshow(BW1) figure, imshow(BW2) See also IMFILL, BWLABEL, GRAYCONNECTED, REGIONFILL, ROIPOLY. Documentation for bwselect doc bwselect
Thank you for your reply. Indeed, the ginput command is preferable to indicating the pixel coordinates.
What I could not do is to apply the ginput command using your code. I thought of inserting it after the Treshold values but I don't know how to continue:
...
lowThreshold = 31;
highThreshold = 255;
[x,y] = ginput(1)
mask = bwselect(mask,y,x);
...
Could you help me with this?
You have to use the thresholds to create the mask first. Of course bwselect won't work until mask is created. So like:
%--------------------------------------------------------------------------------------------------------
% Threshold to create mask
lowThreshold = 31;
highThreshold = 255;
% Interactively and visually set a threshold on a gray scale image.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
% [lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage);
mask = grayImage >= lowThreshold & grayImage <= highThreshold;
xline(lowThreshold, 'Color', 'r', 'LineWidth', 2)
% Get rid of blobs touching the border.
% mask = imclearborder(mask);
% Take 2 largest blobs.
mask = bwareafilt(mask, 2);
% Ask user to click on the blob they want to keep.
uiwait(helpdlg('Click on the blob you want to keep'));
% Extract only the blob they clicked on.
mask = bwselect(mask, 8);
% Display the mask.
subplot(2, 2, 3);
imshow(mask);
impixelinfo;
axis('on', 'image');
title('Mask Image', 'FontSize', fontSize, 'Interpreter', 'None');

Sign in to comment.

More Answers (1)

Benjamin
Benjamin on 29 Jan 2023
Edited: Image Analyst on 29 Jan 2023
Region growing is a way to divide an image into smaller parts based on where different colors or shapes are found. It's like selecting starting points to divide the image into.

Categories

Products

Release

R2021b

Asked:

on 27 Jan 2023

Commented:

Rik
on 1 Feb 2023

Community Treasure Hunt

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

Start Hunting!