You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
separating foreground from background and working on the masked image in matlab
2 views (last 30 days)
Show older comments
Malini Bakthavatchalam
on 24 Sep 2020
Hi,
This question is haunting me for a long time. first I was working in color so I have asked people here. now i am working on grey levels, but still this question is not resolved. I am reading an image using imread function then converting the whole image to grey levels, then I have to work only on the grey levels of the foreground, the code should not include the background, could anyone suggest a code to insert in my code please....i will attach a sample image as well ...
18 Comments
Malini Bakthavatchalam
on 24 Sep 2020
HI, I did try but it convers the background to black but still in my forground analysis the black pixels is getting involved ...
Sindar
on 24 Sep 2020
(caveat: that was pretty much the limit of my knowledge)
What analysis are you doing? You may need to use the mask to do something else to the image, vs changing background to black.
Spitballing:
- NaNs
- Pass non-masked pixels as a single column
- Check the documentation of the analysis functions to see if you can pass in a mask
Malini Bakthavatchalam
on 25 Sep 2020
I have attached my code, in short, I am converting a color image to gray scale, then take the foreground of the image, calculate the median,using the median splitting the image from the median into 2 separate image... so one image will have value less than median and other image will have pixels greater than median.
Sindar
on 25 Sep 2020
everything above "figure(1)" can be replaced by this cleaner version
% image included in Matlab so we can compare
I = imread('ngc6543a.jpg');
G = rgb2gray(I);
my_median = median(G,"all");
K = my_median*ones(size(G),"uint8");
P = my_median*ones(size(G),"uint8");
idx = ( G <= my_median );
K(idx) = G(idx);
P(~idx) = G(~idx);
if you have a mask as a size(G) set of true/false in variable BW (the first output from image Segmenter app auto-generated code), then replace the my_median line with:
my_median = median(G(mask));
With the sample image and a segmenting function below, I get this:
G
[BW,G_masked] = segmentImage(G);
G_masked
BW (i.e. the mask)
Your plots
Segmenter code
function [BW,maskedImage] = segmentImage(X)
%segmentImage Segment image using auto-generated code from imageSegmenter app
% [BW,MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the imageSegmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 24-Sep-2020
%----------------------------------------------------
% Threshold image - manual threshold
BW = X > 25;
% Close mask with disk
radius = 20;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imclose(BW, se);
% Clear borders
BW = imclearborder(BW);
% Erode mask with disk
radius = 1;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imerode(BW, se);
% Create masked image.
maskedImage = X;
maskedImage(~BW) = 0;
end
KALYAN ACHARJYA
on 25 Sep 2020
Edited: KALYAN ACHARJYA
on 25 Sep 2020
Although you elaborate the question quite thoroughly, but sorry I didn't understand this question exactly. What does those forground and background means here?
Steps: 1. You have gray image
2 You segment the ROI, result image is also gray image (After mask applied)
3 Next--???
Sindar
on 25 Sep 2020
I don't know if they're including it in the analysis, but the background is changing in that video (just in "darks", not "lights")
Anyway, I wasn't really thinking about the histograms. That's easy to fix, just replace the lines like this:
subplot(234)
imhist(G(BW))
title('originalhist');
subplot(235)
imhist(K(BW))
title('lowerrectified hist');
ylim([0 10000])
subplot(236)
imhist(P(BW))
title('upperrectified hist');
ylim([0 10000])
If you don't want the backgrounds to be changed (even according to the median of the foreground), use these lines to compute K and P
K = use_median*ones(size(G),"uint8");
P = use_median*ones(size(G),"uint8");
idx_dark = ( G <= use_median ) | ~BW;
K(idx_dark) = G(idx_dark);
idx_light = ( G > use_median ) | ~BW;
P(idx_light) = G(idx_light);
Malini Bakthavatchalam
on 26 Sep 2020
so with this Do I have to keep marking my foreground all the time?, because i have 100 images.
Malini Bakthavatchalam
on 26 Sep 2020
@kalyan Acharjya: Thanks for the question, I am basically taking a color image, separating the foreground, then converting that foreground into grey levels, then finding the median for the foreground, Finally i create two more images from the median value splitting them into half. the answer is already given by Sindar. thanks to Sinder. Now my question is this image segmentar is asking to mark both foreground and background. I have 100 images to work, so making this foreground and background selection looks tough.. Could you suggest some better ways please...
Sindar
on 26 Sep 2020
First, the code:
It seems mostly like the algorithm is correct, but many lines refer to variables that aren't defined. Here's a functional version (minus the image segmenter):
clc
close all
clear all
I = imread('img29res.jpg');
G = rgb2gray(I);
[BW,G_masked] = segmentImage(G);
% change to true if you want to use the median of the whole image
if false
my_median = median(G,"all");
K = my_median*ones(size(G),"uint8");
P = my_median*ones(size(G),"uint8");
idx = ( G <= my_median );
K(idx) = G(idx);
P(~idx) = G(~idx);
else
my_median = median(G(BW));
K = my_median*ones(size(G),"uint8");
P = my_median*ones(size(G),"uint8");
idx_dark = ( G <= my_median ) | ~BW;
K(idx_dark) = G(idx_dark);
idx_light = ( G > my_median ) | ~BW;
P(idx_light) = G(idx_light);
end
figure(1)
subplot(3,3,1)
imshow(I)
title('original');
subplot(3,3,2)
imshow(G)
title('grayscale');
subplot(3,3,3)
imshow(BW)
title('foreground mask');
subplot(3,3,4)
imshow(G_masked)
title('orginal foreground');
subplot(3,3,5)
imshow(K)
title('lower rectified');
subplot(3,3,6)
imshow(P)
title('upper rectified');
subplot(3,3,7)
imhist(G(BW))
title('originalhist');
% get the limits of the orginal histogram and use the same for others
yl=ylim();
subplot(3,3,8)
imhist(K(BW))
title('lower rectified hist');
ylim(yl)
subplot(3,3,9)
imhist(P(BW))
title('upper rectified hist');
ylim(yl)
I added a row of plots to show the original color image, the mask itself, and just the foreground of the grayscale image.
Now, to the background/foreground segmentation:
The idea of the app is that you can play around with options to figure out what works for a few sample images. You generate code, paste it as "function [BW,maskedImage] = segmentImage(X)...". Then, you try it out on the whole batch and see if there are issues. So, no, you don't need to run the app for each image. If all your images have a solid light background, it should be relatively easy.
Right now, segmentation code you're using (mine?) doesn't work for your image:
You can see that it identifies none of the image as foreground
I just downloaded your actual image, played around with the App, and came up with this code. It works for this particular image, but you'll need to check and adjust it so it works decently for all images:
function [BW,maskedImage] = segmentImage(X)
%segmentImage Segment image using auto-generated code from imageSegmenter app
% [BW,MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the imageSegmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 26-Sep-2020
%----------------------------------------------------
% Adjust data to span data range.
X = imadjust(X);
% Threshold image - adaptive threshold
BW = imbinarize(X, 'adaptive', 'Sensitivity', 0.630000, 'ForegroundPolarity', 'bright');
% Invert mask
BW = imcomplement(BW);
% Fill holes
BW = imfill(BW, 'holes');
% Close mask with disk
radius = 41;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imclose(BW, se);
% Create masked image.
maskedImage = X;
maskedImage(~BW) = 0;
end
My suggestion would be to convert the script into a function that accepts an image, then you can run it on all of them quickly (there's even an Image Batch Processor App, but I have no experience with it)
Malini Bakthavatchalam
on 27 Sep 2020
Thanks, it worked for two to three images i have to try rest of the 96 images... all my images have only light background. Thanks so much for this help, this is a big help for my 6 months mental pressure...
I finally have only one clarification to ask, so the histogram and the lower and upper rectified images didnot involve background right ?
Sindar
on 28 Sep 2020
Yup, everything either ignores the background (histograms) or leaves it untouched (recitfying).
For histograms, you can see this here:
imhist(G(BW))
it is only creating a histogram from the masked data (i.e. the foreground)
For the rectification,
% median computed from masked data
my_median = median(G(BW));
% the below lines effectively replace all lighter-than-median foreground pixels with the median
% create an image with all pixels = median
K = my_median*ones(size(G),"uint8");
% find pixels darker than the median OR that are unmasked (i.e. the background)
idx_dark = ( G <= my_median ) | ~BW;
% replace these pixels
K(idx_dark) = G(idx_dark);
Malini Bakthavatchalam
on 28 Sep 2020
Thanks a lot as a beginner struggled with this for 6 months ....
Malini Bakthavatchalam
on 28 Sep 2020
this one is created by my labmate a few yrs ago, i got this through some means, can i use the same background removal stratergy i used in my code.... in his code ... because i feel his code looks more sophisticated than mine ...
Sindar
on 28 Sep 2020
potentially... it mostly looks like they just wrapped it in a GUI for convenience, but I haven't worked with the Matlab GUI controls. On first scan, I think all you'd need to do is alter the Lightness_Stat and Lightness_HistModif functions
Malini Bakthavatchalam
on 2 Oct 2020
Sindar
on 2 Oct 2020
Edited: Sindar
on 2 Oct 2020
This segmenter algorithm will likely fail, but you may be able to build a new algorithm in the Image Segmenter app (or Color Thresholder app). It really depends on the diversity of your images. For example, I'd expect 6.jpg to be almost trivial to segment, whereas 10.jpg and 25.jpg are probably doable but trickier, and creating a single algorithm that works on all three could be difficult.
(everything else in the code will function the same)
Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)