How to do background Substraction for any RGB-image image using Matlab ?

3 次查看(过去 30 天)
I want to subtract the background of this image. How do I do it? I don't know how.

采纳的回答

DGM
DGM 2022-3-11
You ask for two things: a means to segment a leaf image and a means to segment any image. It should be obvious that the latter isn't an answerable question, so here's one way to get that specific leaf image segmented.
Argb = imread('anyimage.jpg');
Ahsv = rgb2hsv(Argb);
% make a mask
mask = Ahsv(:,:,2)>0.15 & Ahsv(:,:,1)>0.19 & Ahsv(:,:,1)<0.37;
mask = imfill(mask,'holes');
% apply the mask
Argb(repmat(~mask,[1 1 3])) = 0;
imshow(Argb)
  4 个评论
Image Analyst
Image Analyst 2022-3-11
@DGM I just do all the threshold adjustment in the Color Thresholder app and then export it as a function and then essentially call the function as a black box in my main script. Really easy, not tedious.
@Saikat Ghosh see my second answer below. Because I think you don't want to just "subtract the background" -- people don't usually just do that and completely stop. Usually they want the color, size, count, or other things measured. That's what my other answer will show you how to do.
DGM
DGM 2022-3-12
Most of the apps are simply slow or broken in my environment. Color Thresholder app works fine, but it's maddeningly laggy (few seconds UI lag at times). The only polar model is HSV, which is limiting. The current threshold settings aren't displayed anywhere, so I feel like I'm flying blind. You have to export to a function to get the numbers.
The auto-generated function file looks like something anyone here would complain about anyway. It's a pile of numbered variables that are all simultaneously verbose and generic. The code creates the mask with the fantastic name sliderBW and the unnecessarily duplicates it as BW for no apparent reason. The name of the HSV image is I, which in my convention means "a single-channel image".
When I'm actually doing something other than a terse example, I prefer to carry threshold pairs as vectors or as a 3x2 array. I would want things like that to be adjustable parameters available outside the scope of a helper function anyway.
I can't complain too much. I wrote immask() so I'd have the features I wanted, but if I had to dig through its guts today, I'd probably find plenty of things to complain about too. I guess it doesn't display thresholds either, but it was never intended for that sort of workflow.

请先登录,再进行评论。

更多回答(2 个)

Image Analyst
Image Analyst 2022-3-11
What does "background subtraction" mean to you? And why do you want to do it?
Do you merely want to blacken the background for some reason? Why? But if so, use the Color Thresholder app on the Apps tab of the tool ribbon to adjust thresholds in HSV color space and then Export the function.
Do you want to correct for lens shading and lighting non-uniformities? If so, you need to take a photo of a smooth, matte, uniform gray or white sheet and then DIVIDE by your uniform image, not subtract. Why? Well if your light or exposure at the corner was only 80% as bright as it is at the center, you'd need to divide by 80% to bring its color values up to what they would be as if they were at the center and your lighting/exposure did not vary from place to place in your image. See attached tutuorial.

Image Analyst
Image Analyst 2022-3-11
Try this to get rid of the background and measure the leaf color.
% Demo by Image Analyst to extract leaf.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
fprintf('Beginning to run %s.m ...\n', mfilename);
%-----------------------------------------------------------------------------------------------------------------------------------
% Read in image.
folder = pwd;
baseFileName = 'leaf2.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
rgbImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(rgbImage)
% Display the original RGB image.
subplot(3, 3, 1);
imshow(rgbImage, []);
axis('on', 'image');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
caption = sprintf('Original RGB Image : "%s"\n%d rows by %d columns', baseFileName, rows, columns);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
hFig1 = gcf;
hFig1.Units = 'Normalized';
hFig1.WindowState = 'maximized';
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
hFig1.Name = 'Demo by Image Analyst';
%-----------------------------------------------------------------------------------------------------------------------------------
% Get the white surround.
mask = createMask(rgbImage);
% Display the mask image.
subplot(3, 3, 2);
imshow(mask, []);
axis('on', 'image');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
caption = sprintf('Initial Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
% Get the Leaf mask.
mask = bwareafilt(mask, 1);
mask = imfill(mask, 'holes');
% Get a new masked image with the new mask.
% Mask the image using bsxfun() function to multiply the mask by each channel individually. Works for gray scale as well as RGB Color images.
maskedRGBImage = bsxfun(@times, rgbImage, cast(mask, 'like', rgbImage));
% Get the boundary coordinates.
boundaries = bwboundaries(mask);
xb = boundaries{1}(:, 2);
yb = boundaries{1}(:, 1);
%-----------------------------------------------------------------------------------------------------------------------------------]
% Display the image.
subplot(3, 3, 3);
imshow(mask);
caption = sprintf('Final Leaf Mask');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
% Display the masked RGB image.
subplot(3, 3, 4);
imshow(maskedRGBImage);
caption = sprintf('Final Masked Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
labImage = rgb2lab(maskedRGBImage);
[Limage, Aimage, Bimage] = imsplit(labImage);
% Make the color measurements.
propsL = regionprops(mask, Limage, 'MeanIntensity');
propsA = regionprops(mask, Aimage, 'MeanIntensity');
propsB = regionprops(mask, Bimage, 'MeanIntensity');
meanL = propsL.MeanIntensity
meanA = propsA.MeanIntensity
meanB = propsB.MeanIntensity
% Display the LAB images.
subplot(3, 3, 5);
imshow(Limage, []);
hold on;
plot(xb, yb, 'r-', 'LineWidth', 4);
axis('on', 'image');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
caption = sprintf('L image mean within red outline = %f', meanL);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
subplot(3, 3, 6);
imshow(Aimage, []);
hold on;
plot(xb, yb, 'r-', 'LineWidth', 4);
axis('on', 'image');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
caption = sprintf('A image mean within red outline = %f', meanA);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
subplot(3, 3, 7);
imshow(Bimage, []);
hold on;
plot(xb, yb, 'r-', 'LineWidth', 4);
axis('on', 'image');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
caption = sprintf('B image mean within red outline = %f', meanB);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 11-Mar-2022
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.095;
channel1Max = 0.391;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.151;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.000;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
  5 个评论
Sreyasee ROY
Sreyasee ROY 2022-3-17
@Image Analyst I tried to use the same code to segment a flower from the background. But it did not work. Could you please provide the updated code for the flower segmentation?
Image Analyst
Image Analyst 2022-3-17
It's the same process that you can do. What I would do is to load this image into Color Thresholder, adjust the thresholds in HSV color space, then export the function. Then rename it to CreateRedMask() and call it from the main program. If you really can't figure it out, I can do it for you but:

请先登录,再进行评论。

Community Treasure Hunt

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

Start Hunting!

Translated by