how can you determine the threshold that covers the functional area of the image in matlab?

5 views (last 30 days)
I have an image of a tissue and I want to make a mask of that tissue that is only of the functional area in the image (minus the long black tubular shapes which are blood vessels that I don't want to include in my measurements). How can I make this mask? Here's what i tried:
% Load image
img = imread('tissueimage.tif');
% Convert to grayscale
gray_img = rgb2gray(img);
% Threshold the image to create a binary mask
threshold = 8;
mask = gray_img > threshold;
% Remove small objects
min_size = 1000;
mask = bwareaopen(mask, min_size);
% Fill holes
mask = imfill(mask, 'holes');
% Erode and dilate the mask to remove noise and smooth edges
se = strel('disk', 5);
mask = imerode(mask, se);
mask = imdilate(mask, se);
% Display the original image and the resulting mask
figure;
subplot(1,2,1); imshow(img); title('Original Image');
subplot(1,2,2); imshow(mask); title('Functional Mask');
Here's what I have done so far:
  1. Preprocess the image
  2. Segment the tissue (removed background)
here's is where I'm unsure
Remove the blood vessels
i did try thresholding and picking numbers from 0-10 but 0, gets too many of the blood vessels and 10, I'm not sure if its all of the functional area or just the white pixels.
here's how i imagine it should look like (masked image). How can i get this?
Thanks pictures attached.
-L
  3 Comments

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 4 Mar 2023
@Laura just take your existing mask (top image) and invert it
mask = ~mask;
  15 Comments
Laura
Laura on 9 Mar 2023
Edited: Laura on 9 Mar 2023
@Image Analyst the worm mask doesn't exist, its just a photoshop picture of the mask i want to create.
I found your response in another forum that was pretty good! This will work, but my issue is highlighting the red areas that i don't want which isn't showing in my image. Here is the code:
% Read image as RGB
I = imread('bwimage.png'); %including the pull path is better
% Convert to binary
BW = imbinarize(rgb2gray(I));
% Get rid of white border
BWConv = bwconvhull(~BW);
BW = BW & BWConv;
% get region centers and major axis, and orientation
stats = regionprops('table',BW,'BoundingBox','MajorAxisLength','MinorAxisLength');
% Compute length/width ratio
stats.LenWdRatio = stats.MajorAxisLength ./ stats.MinorAxisLength;
% Set threshold and determine which objects
% are greater than the threshold.
thresh = 2.0;
stats.isGreater = stats.LenWdRatio > thresh;
% Show bounding box for objects that met the threshold
figure()
h = imshow(BW);
axis on
hold on
% Plot red rectangles around accepted objects
arrayfun(@(i)rectangle('Position',stats.BoundingBox(i,:),'EdgeColor','r'), find(stats.isGreater));
% Plot yellow rectangles around rejected objects
arrayfun(@(i)rectangle('Position',stats.BoundingBox(i,:),'EdgeColor','y'), find(~stats.isGreater));
I attached my image. mY ONLY ISSUES is how to put the big black circles in the rejected squares. bUt nomatter which threshold I pick the circles don't like up. thANKS very much @Image Analyst

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 11 Mar 2023
@Laura 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 = 'laura.jpeg';
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(3, 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;
%--------------------------------------------------------------------------------------------------------
% Get mask
mask = grayImage > 0;
subplot(3, 2, 2);
imshow(mask);
impixelinfo;
axis('on', 'image');
title('Mask Image', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
%--------------------------------------------------------------------------------------------------------
% Get Euclidean distance transform
edtImage = bwdist(mask);
subplot(3, 2, 3);
imshow(edtImage, []);
impixelinfo;
axis('on', 'image');
title('EDT Image', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
%--------------------------------------------------------------------------------------------------------
% Threshold the edt image to get the large black regions.
mask2 = edtImage > 8;
% The mask has sharp corners. OPTIONAL: if you want to smooth them out, blur and threshold.
windowWidth = 9;
mask2 = conv2(double(mask2), ones(windowWidth)/windowWidth^2, 'same') > 0.5;
% Looks like maybe we don't want blobs smaller than 1000 pixels. Remove those. (OPTIONAL)
mask2 = bwareaopen(mask2, 1000);
%--------------------------------------------------------------------------------------------------------
% Measure the areas of all the blobs.
props = regionprops(mask2, 'Area')
allAreas = sort([props.Area])
subplot(3, 2, 4);
imshow(mask2, []);
impixelinfo;
axis('on', 'image');
title('Mask Image', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
%--------------------------------------------------------------------------------------------------------
% Plot the borders of all the blobs in the overlay above the original grayscale image
% using the coordinates returned by bwboundaries().
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
subplot(3, 2, 5);
imshow(grayImage); % Optional : show the original image again. Or you can leave the binary image showing if you want.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(mask2);
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format. Note: NOT (x,y).
% Column 1 is rows, or y. Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
end
hold off;
caption = sprintf('%d Outlines, from bwboundaries()', numberOfBoundaries);
fontSize = 15;
title(caption, 'FontSize', fontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.
  5 Comments
Laura
Laura on 12 Mar 2023
The answer you gave answered me perfectly. Thanks for the link.
Why doesn't it really matter though? Thansk for the clarification. @Image Analyst
Image Analyst
Image Analyst on 13 Mar 2023
Because I think you said you want to measure things about the bright blobs. So you can get a mask of those. It's not needed to get the mask of larger dark areas in order to measure the small white blobs.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!