How can I extract the largest blob in a binary image

210 ビュー (過去 30 日間)

採用された回答

Image Analyst
Image Analyst 2013 年 3 月 26 日
See this demo. Adapt it to use your binary images instead of the binary image I generate from the standard "coins.png' demo image. Save the code below as ExtractBiggestBlob.m and run it. The main part of the function is in a custom function called ExtractNLargestBlobs() that I wrote, and it's included at the bottom of the code. The code above that is just to make a fancy demo with nice pictures to illustrate what's going on.
function ExtractBiggestBlob()
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures if you have the Image Processing Toolbox.
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
% Read in a standard MATLAB gray scale demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
baseFileName = 'coins.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, '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.
% numberOfColorBands should be = 1.
[rows, columns, numberOfColorBands] = size(grayImage);
% Display the original gray scale image.
subplot(2, 2, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Give a name to the title bar.
set(gcf,'name','Demo by ImageAnalyst','numbertitle','off')
% Let's compute and display the histogram.
[pixelCount, grayLevels] = imhist(grayImage);
subplot(2, 2, 2);
bar(pixelCount);
grid on;
title('Histogram of original image', 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Threshold the image to binarize it.
binaryImage = grayImage > 100;
% Fill holes
binaryImage = imfill(binaryImage, 'holes');
% Display the image.
subplot(2, 2, 3);
imshow(binaryImage, []);
title('Binary Image', 'FontSize', fontSize);
% Get all the blob properties. Can only pass in originalImage in version R2008a and later.
[labeledImage, numberOfBlobs] = bwlabel(binaryImage);
blobMeasurements = regionprops(labeledImage, 'area', 'Centroid');
% Get all the areas
allAreas = [blobMeasurements.Area] % No semicolon so it will print to the command window.
menuOptions{1} = '0'; % Add option to extract no blobs.
% Display areas on image
for k = 1 : numberOfBlobs % Loop through all blobs.
thisCentroid = [blobMeasurements(k).Centroid(1), blobMeasurements(k).Centroid(2)];
message = sprintf('Area = %d', allAreas(k));
text(thisCentroid(1), thisCentroid(2), message, 'Color', 'r');
menuOptions{k+1} = sprintf('%d', k);
end
% Ask user how many blobs to extract.
numberToExtract = menu('How many do you want to extract', menuOptions) - 1;
% Ask user if they want the smallest or largest blobs.
promptMessage = sprintf('Do you want the %d largest, or %d smallest, blobs?',...
numberToExtract, numberToExtract);
titleBarCaption = 'Largest or Smallest?';
sizeOption = questdlg(promptMessage, titleBarCaption, 'Largest', 'Smallest', 'Cancel', 'Largest');
if strcmpi(sizeOption, 'Cancel')
return;
elseif strcmpi(sizeOption, 'Smallest')
% If they want the smallest, make the number negative.
numberToExtract = -numberToExtract;
end
%---------------------------------------------------------------------------
% Extract the largest area using our custom function ExtractNLargestBlobs().
% This is the meat of the demo!
biggestBlob = ExtractNLargestBlobs(binaryImage, numberToExtract);
%---------------------------------------------------------------------------
% Display the image.
subplot(2, 2, 4);
imshow(biggestBlob, []);
% Make the number positive again. We don't need it negative for smallest extraction anymore.
numberToExtract = abs(numberToExtract);
if numberToExtract == 1
caption = sprintf('Extracted %s Blob', sizeOption);
elseif numberToExtract > 1
caption = sprintf('Extracted %d %s Blobs', numberToExtract, sizeOption);
else % It's zero
caption = sprintf('Extracted 0 Blobs.');
end
title(caption, 'FontSize', fontSize);
msgbox('Done with demo!');
% Function to return the specified number of largest or smallest blobs in a binary image.
% If numberToExtract > 0 it returns the numberToExtract largest blobs.
% If numberToExtract < 0 it returns the numberToExtract smallest blobs.
% Example: return a binary image with only the largest blob:
% binaryImage = ExtractNLargestBlobs(binaryImage, 1)
% Example: return a binary image with the 3 smallest blobs:
% binaryImage = ExtractNLargestBlobs(binaryImage, -3)
function binaryImage = ExtractNLargestBlobs(binaryImage, numberToExtract)
try
% Get all the blob properties. Can only pass in originalImage in version R2008a and later.
[labeledImage, numberOfBlobs] = bwlabel(binaryImage);
blobMeasurements = regionprops(labeledImage, 'area');
% Get all the areas
allAreas = [blobMeasurements.Area];
if numberToExtract > 0
% For positive numbers, sort in order of largest to smallest.
% Sort them.
[sortedAreas, sortIndexes] = sort(allAreas, 'descend');
elseif numberToExtract < 0
% For negative numbers, sort in order of smallest to largest.
% Sort them.
[sortedAreas, sortIndexes] = sort(allAreas, 'ascend');
% Need to negate numberToExtract so we can use it in sortIndexes later.
numberToExtract = -numberToExtract;
else
% numberToExtract = 0. Shouldn't happen. Return no blobs.
binaryImage = false(size(binaryImage));
return;
end
% Extract the "numberToExtract" largest blob(a)s using ismember().
biggestBlob = ismember(labeledImage, sortIndexes(1:numberToExtract));
% Convert from integer labeled image into binary (logical) image.
binaryImage = biggestBlob > 0;
catch ME
errorMessage = sprintf('Error in function ExtractNLargestBlobs().\n\nError Message:\n%s', ME.message);
fprintf(1, '%s\n', errorMessage);
uiwait(warndlg(errorMessage));
end
  13 件のコメント
Image Analyst
Image Analyst 2019 年 12 月 2 日
Use bwareafilt(). For the biggest blob, something like
biggestBlob = bwareafilt(binaryImage, 1);
bigBlob = grayImage; % Initialize.
bigBlob(~biggestBlob) = false; % Erase outside of big blob.
Start a new question if you can't figure it out for the smallest blob or second biggest blob.

サインインしてコメントする。

その他の回答 (4 件)

leon
leon 2013 年 4 月 25 日
i don't know,because want ellipse detect just need object edge line only. if want change picture to format png or tiff just open the image then save as png format?

Sean de Wolski
Sean de Wolski 2013 年 5 月 1 日
Here's the function I wrote to do this. You can also use the example in the "tips section of the doc for regionprops which explains how to keep blobs based on some criteria.
function Imx = keepMaxObj(X)
%Function to keep only the maximum sized (biggest) object in an image
%SCd 11/30/2010
%
%Updates:
% -02/03/2011: Added ability to handle an image directly
%
%Usage:
% Imx = keepMaxObj(CC);
% Imx = keepMaxObj(V);
%
%Input Arguments:
% -CC: Connected components returned from bwconncomp
% -V: Logical image with parts you want true
%
%Output Arguments:
% -Imx: Logical volume with only the biggest object left true.
%
%See Also: bwconncomp
%
%Error checking:
assert(islogical(X)||isstruct(X),'The first input argument is expected to be a struct or a logical');
if isstruct(X)
CC = X;
parts = {'PixelIdxList','ImageSize'};
assert(all(ismember(parts,fieldnames(CC))),'CC is expected to be the output from bwconncomp');
else
CC = bwconncomp(X);
end
clear X;
%Preallocate and find number of voxels/object
Nvox = zeros(CC.NumObjects,1);
for ii = 1:CC.NumObjects
Nvox(ii) = numel(CC.PixelIdxList{ii});
end
%Find the biggest object's index, warn and save all if there are multiples
[mx,midx] = max(Nvox);
more_than1_max = sum(mx==Nvox);
if more_than1_max > 1
midx = find(mx == Nvox);
warning('Multiple:Maxima', 'There were %i objects with the maximum size.\n They are all left on!',more_than1_max);
end
%Create the final image
Imx = false(CC.ImageSize);
Imx([CC.PixelIdxList{midx}]) = true;
end
  7 件のコメント
Image Analyst
Image Analyst 2013 年 5 月 2 日
What form is your ellipse in? It looks like an RGB image with some white pixels and some blue pixels - at least the image you posted in the comment to my answer does. Why do you want that blue and white image burned into the image? You can easily do it (but I don't know why you'd want to):
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Extract the individual red, green, and blue color channels
% of the ellipse image.
redEllipseChannel = rgbEllipseImage(:, :, 1);
greenEllipseChannel = rgbEllipseImage(:, :, 2);
blueEllipseChannel = rgbEllipseImage(:, :, 3);
% Get mask
mask = redEllipseChannel > 0 & greenEllipseChannel > 0 & blueEllipseChannel > 0;
% Assign ellipse pixels in the masked region of the ellipse image
% to the original image in the masked region
redChannel(mask) = redEllipseChannel(mask);
greenChannel(mask) = greenEllipseChannel (mask);
blueChannel(mask) = blueEllipseChannel(mask);
% Recombine into RGB image
newRGBimage = cat(3, redChannel, greenChannel, blueChannel);
% Display
imshow(newRGBimage);

サインインしてコメントする。


r r
r r 2018 年 8 月 8 日
I have an image I want to extract the small areas of black color within the blue How so؟؟؟
  1 件のコメント
Image Analyst
Image Analyst 2018 年 8 月 8 日
Please start your own question rather than posting your question as official "Answers" to multiple other questions that are only mildly related.

サインインしてコメントする。


Henry Brown
Henry Brown 2019 年 6 月 5 日
I came across the bwpropfilt function, which serves this purpose in one line:
BW2 = bwpropfilt(BW, 'Area', n);
BW2 is the new binary image with only n largest objects in BW.
  1 件のコメント
Image Analyst
Image Analyst 2019 年 6 月 6 日
There is a new function to extract only the largest blob -- it's called bwareafilt()
BW = bwareafilt(BW, 1); % Extract largest blob.

サインインしてコメントする。

Community Treasure Hunt

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

Start Hunting!

Translated by