
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
How do I remove a white background and only keep certain objects in a binary image on MATLAB?
조회 수: 7 (최근 30일)
이전 댓글 표시
I would like the remove the white pixels in the background, but somehow keep the white lines. How would I go about doing that.
Sorry I didn't mean to remove the question. I was trying to comment on my phone, but I must have unknowingly modified the question.

댓글 수: 7
John BG
2017년 8월 1일
Hi Justin and IA
I completely agree that IA's answer is the answer to be accepted for this question so far, but with the current approach there are areas where the lines should be preserved but they are lost, for instance the top right corner

.
A fill-up approach, start from the image frame inwards, would catch all lines of interest, as long as they are connected, and then whatever single or small clusters of white pixels left behind would be easily discarded.
John BG
Image Analyst
2017년 8월 1일
Well, not technically since the "lines" there are broken apart into smaller blobs, but I think that people kind of mentally fill in the breaks to make complete lines. But I'm not sure what a "fill up" approach is -- region growing?
Image Analyst
2017년 8월 2일
I didn't see that grayscale image on the right. Not sure where you got it. I thought John was referring to the binary image in the original question, which did have cracks in the upper right. Now, after inspecting both binary images, it's clear the one John referred to is not the one in the original question that I was looking at.
John BG
2017년 8월 2일
IA thanks for pointing out that the original image had white contents on the top right corner.
Jan
2017년 8월 3일
@Image Analyst: The grey image is the image posted by Justin in his comment https://www.mathworks.com/matlabcentral/answers/345253-how-do-i-remove-a-white-background-and-only-keep-certain-objects-in-a-binary-image-on-matlab#comment_470979 .
채택된 답변
Image Analyst
2017년 6월 22일
Justin - are you still there? Perhaps you're still struggling over this so I made a complete and fancy demo for you. Here it is:
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 = 25;
%===============================================================================
% Get the name of the image the user wants to use.
baseFileName = 'concrete_inverted.png';
% Get the full filename, with path prepended.
folder = []; % Determine where demo folder is (works with all versions).
fullFileName = fullfile(folder, baseFileName);
%===============================================================================
% Read in a demo image.
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.
% Use weighted sum of ALL channels to create a gray scale image.
grayImage = rgb2gray(grayImage);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
% Display the image.
subplot(2, 2, 1);
imshow(grayImage, []);
axis on;
axis image;
caption = sprintf('Original Gray Scale Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo();
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% 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.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
drawnow;
% Binarize the image by thresholding.
mask = grayImage > 128;
% For some reason, the top two lines of his image are all white. Blacken those 2 lines:
mask(1:2, :) = false;
% Display the mask image.
subplot(2, 2, 2);
imshow(mask);
axis on;
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
title('Binary Image Mask', 'fontSize', fontSize);
drawnow;
% Get rid of small blobs.
mask = bwareaopen(mask, 500);
% Label the image.
labeledImage = bwlabel(mask);
% Find the areas and perimeters
props = regionprops(labeledImage, 'Area', 'Perimeter');
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend')
allPerimeters = [props.Perimeter];
% Compute circularities
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
sortedC = sort(circularities, 'descend')
% Keep conly blobs that are nowhere close to circular or compact.
minAllowableCircularity = 10;
keeperIndexes = find(circularities >= minAllowableCircularity);
mask = ismember(labeledImage, keeperIndexes);
% Display the mask image.
subplot(2, 2, 3);
imshow(mask);
axis on;
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
title('Intermediate Cleaned Mask', 'FontSize', fontSize);
drawnow;
% Get rid of black islands (holes) in struts without filling large black areas.
subplot(2, 2, 4);
mask = ~bwareaopen(~mask, 1000);
imshow(mask);
axis on;
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
title('Final Cleaned Mask', 'FontSize', fontSize);
drawnow;

I think the results look pretty good, like what I think you're expecting. Don't you? If not, let me know what I could do to improve it. Basically the same original crack lines are in the image (no change in exterior shape), except that the small black islands in them are filled in, all all the little isolated white island are removed. Is that what you want? There are a few parameters/variables in there, with obvious names, that you can adjust if you want to. Please get back to me.
댓글 수: 71
Image Analyst
2017년 7월 9일
I'd probably skeletonize the thing, then call bwmorph() to get endpoints and branchpoints, and count them.
Justin Johnson
2017년 7월 15일
Hello Image Analyst,
I tried the method above on another imagine, and I got the following image attached. What why am I getting black images on this one? I tried everything I could to figure it out, but I don't know what is going on. Thanks!
Justin Johnson
2017년 7월 15일
I used the image attached. Was that code you give for that specific image or would it work for others?
Image Analyst
2017년 7월 15일
It should work with other images. Please attach the actual PNG image, not the screenshot.
Image Analyst
2017년 7월 16일
편집: Image Analyst
2017년 7월 16일
That image has a huge white surround around it that I suspect may be messing up the result. Because the perimeter is the outside edge of the image, the circularity is only 3 instead of some high number. Plus, you have only 1 blob. Have you tried it without that huge surrounding white rectangle (crop it away)?
Image Analyst
2017년 7월 16일
편집: Image Analyst
2017년 7월 16일
So, I'm guessing that you tried it and still got the same answer? Please attach the actual image in a standard format like PNG, not a MATLAB proprietary fig file.
Justin Johnson
2017년 7월 16일
Ok, so here is the problem. Take the attached image above(inverted_cracking3). When I run it though the code you gave me, it automatically creates the white space you said that ruins the result(final_inverted_cracking3.png)
Justin Johnson
2017년 7월 16일
The original image before I inverted the binary pixels is the one attached above
Image Analyst
2017년 7월 16일
Alright, fine - when I get home later tonight, if I have time, I'll figure out where the white rectangular border is and crop out the center crock-only portion and crop away the white surround. Looks like the good part is from rows 37-804 and columns 109-1132. Not sure how you got that white box around your image, and why you didn't just use imwrite() to save the binary image. I bet if you just did
% Binarize the image by thresholding.
mask = grayImage(37:804, 109:1132) > 128;
you'd get something reasonable.
I'll work on it later tonight if I have time but I need to hit the road now to go back home.
Image Analyst
2017년 7월 16일
편집: Image Analyst
2017년 7월 17일
Look at gray image in the variable inspector, and find out where the values at the edge quit being 255.
Image Analyst
2017년 7월 17일
I hope you took my advice and used the code change I suggested and didn't wait for me, but I didn't hear back from you so I did it. Like I thought, once you make that code change to get rid of the huge white frame, it works fine. See below image and attached test2.m file

Go ahead and tweak the parameters if you want to improve the performance.
Justin Johnson
2017년 7월 22일
편집: Justin Johnson
2017년 7월 22일
So i'm stuck again. I'm trying to create a GUI that will do the same thing (auto detect cracks), but thing time with the option to change certain parameters.Because this is my first time creating a GUI, I though it would be best to start off with one button that will do everything before having multiple buttons that will transfer values. Anyways, I can't see what is going on. I avoid asking you, but I'm really stuck. This is my result: The picture attached is layout of my current GUI. As stated earlier, the finished product should come up with a click of a button after uploading the picture. I will upload the original image as well. This is what I keep getting:

Anyways, this is what I have as of right now:
For Importing the image:
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
a=uigetfile('*.jpg')
filename=a;
setappdata (0,'filename',filename);
a=imread(a);
invIm(a);
axes(handles.axes1);
imshow(a);
setappdata(0,'a',a)
setappdata(0,'filename',a);
plot(handles.axes1,'a')
For Detection:
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
a=getappdata(0,'a');
[rows, columns, numberOfColorChannels] = size(a)
if numberOfColorChannels > 1
% If not gray scale then color.
% Uses the weighted sum of all channels to create a gray scale image.
grayImage = rgb2gray(a);
end
% Display the image.
axes(handles.axes1);
imshow(grayImage);
axis on;
axis image;
hp = impixelinfo();
% Binarize the image by thresholding.
mask = grayImage > 128;
% For some reason, the top two lines of his image are all white. Blacken those 2 lines:
mask(1:2, :) = false;
% Display the mask image.
% Get rid of small blobs.
mask = bwareaopen(mask, 500);
% Label the image.
labeledImage = bwlabel(mask);
% Find the areas and perimeters
props = regionprops(labeledImage, 'Area', 'Perimeter');
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend')
allPerimeters = [props.Perimeter];
% Compute circularities
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
sortedC = sort(circularities, 'descend')
% Keep conly blobs that are nowhere close to circular or compact.
minAllowableCircularity = 10;
keeperIndexes = find(circularities >= minAllowableCircularity);
mask = ismember(labeledImage, keeperIndexes);
mask = ~bwareaopen(~mask, 1000);
imshow(mask);
axis on;
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
drawnow;
Justin Johnson
2017년 7월 22일
편집: Justin Johnson
2017년 7월 22일
Thank you so much! I will have to dissect the code to learn how to do it.However, is it possible to see how the GUI I tried to create isn't working. It is going to bug me if I don't know and knowing will only help me learn this better.
Justin Johnson
2017년 7월 24일
Can you explain to me why it was important to calculate the area, perimeter, and circularities? I don't understand how to plays a big part in the code.
Image Analyst
2017년 7월 24일
Objects with high circularities are line-like or crack-like. You want to retain those blobs. Blobs that have low circularity are roundish, non crack-like, and you want to get rid of those.
Justin Johnson
2017년 7월 26일
I believe this is my last question. Can you explain this part of the code to me:
Find the areas and perimeters
props = regionprops(labeledImage, 'Area', 'Perimeter');
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend')
allPerimeters = [props.Perimeter];
% Compute circularities
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
sortedC = sort(circularities, 'descend')
% Keep conly blobs that are nowhere close to circular or compact.
minAllowableCircularity = 10;
keeperIndexes = find(circularities >= minAllowableCircularity);
mask = ismember(labeledImage, keeperIndexes);
Also, would the noise in the background be circles too? Why is it not the other way around and have the cracks more line like and the noise circular like. I'm not challenging you i'm just trying to understand. Thanks!
Image Analyst
2017년 7월 27일
I thought I already explained it pretty well though my prior comment and the comments in the code, but let me try again:
% Each blob is labeled - in other words, it has an "ID" number.
% Find the areas and perimeters for each blob.
% The structure, props, has all the measurements of all the blobs.
% Each index of props is just one structure and has the measurements of only one single blob.
props = regionprops(labeledImage, 'Area', 'Perimeter');
% Extract all the area and perimeter measurements from the structure array
% into individual double arrays for convenience.
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend') % Just for interest (not used)
allPerimeters = [props.Perimeter];
% Compute circularities according to the formula.
% Perfect circles will have a value of 1
% and the less circular it is, the higher the circularity value.
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
% Sort them so we can see how the circularities progress
% from the high values of the major crack lattice
% and major isolated stick-like cracks, down towards more compact and circular blobs.
sortedC = sort(circularities, 'descend')
% Keep only blobs that are nowhere close to circular or compact.
minAllowableCircularity = 10;
% Blobs with a circularity less than 10 will be thrown out.
% circularities >= minAllowableCircularity is a logical vector
% of what blobs are or are not above the circularity threshold.
% in other words, a logical vector of whether it's a crack or not.
% Using find() turns it into a list ob blob indexes that
% we can use to identify "labels" in the labeled image
% that we want to keep/extract with ismember().
keeperIndexes = find(circularities >= minAllowableCircularity);
% Get a new binary image by asking ismember to return a
% binary image with only those indexes that we found
% that are crack-like.
mask = ismember(labeledImage, keeperIndexes);
Well there is is in extreme detail, with more lines of comments than lines of code. If you still don't understand it then you should look up the help for the individual functions like bwlabel(), regionprops(), ismember(), etc.
Justin Johnson
2017년 8월 1일
Hey Image Analyst, Can you tell me what is wrong with my code. I'm trying to figure out my my local function aren't communicating with each other. I'm trying to create a GUI that can do what we did above, but make it easy to change parameters. Using Matlab's GUIDE, I want to change the value of circularities. As you can see in the code, you use the function setappdata() and getappdata() to transfer information, but for some reason it's not working. What is going on?
Importing the image:
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
a=uigetfile('*.png')
filename=a;
setappdata (0,'filename',filename);
a=imread(a);
invIm(a);
axes(handles.axes1);
imshow(a);
setappdata(0,'a',a)
setappdata(0,'filename',a);
plot(handles.axes1,'a')
The noise reduction code:
a=getappdata(0,'a');
[rows, columns, numberOfColorChannels] = size(a)
if numberOfColorChannels > 1
% If not gray scale then color.
% Uses the weighted sum of all channels to create a gray scale image.
grayImage = rgb2gray(a);
end
% Display the image.
axes(handles.axes1);
imshow(grayImage);
axis on;
axis image;
hp = impixelinfo();
% Binarize the image by thresholding.
mask = grayImage > 128;
% For some reason, the top two lines of his image are all white. Blacken those 2 lines:
mask(1:2, :) = false;
% Display the mask image.
% Get rid of small blobs.
mask = bwareaopen(mask, 500);
% Label the image.
labeledImage = bwlabel(mask);
% Find the areas and perimeters
props = regionprops(labeledImage, 'Area', 'Perimeter');
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend')
allPerimeters = [props.Perimeter];
% Compute circularities
b=getappdata(0,'circle')
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
sortedC = sort(circularities, 'descend')
% Keep conly blobs that are nowhere close to circular or compact.
minAllowableCircularity = b;
keeperIndexes = find(circularities >= minAllowableCircularity);
mask = ismember(labeledImage, keeperIndexes);
mask = ~bwareaopen(~mask,100);
imshow(mask);
axis on;
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
drawnow;
Using input for circularity value change:
b=str2num(get(handles.circle,'string'));
setappdata(0,'circle',b);
end
Image Analyst
2017년 8월 1일
I don't know where you're setting circularity, but why don't you just have a slider control named sldCircularity and set the min to 0 and the max to 50 or something. Then just retrieve it directly from the slider
circularityThreshold = handles.sldCircularity.Value;
That way you don't ever need to worry about setting it with setappdata() and retrieving it with getappdata().
Jan
2017년 8월 1일
@Justin Johnson: Is it legal to post the image "concrete1.jpg" attached to your comment? The image is watermarked, but the copyright note is missing.
Justin Johnson
2017년 8월 7일
편집: Justin Johnson
2017년 8월 7일
bold Ok so something still isn't right. So I decided change the gui so that I can change the parameter of the pixels in in the function bwareaopen. Below is the layout of how I did it:
% Binarize the image by thresholding.
mask = grayImage > 128;
% For some reason, the top two lines of his image are all white. Blacken those 2 lines:
mask(1:2, :) = false;
% Display the mask image.
% Get rid of small blobs.
->mask = bwareaopen(mask,handles.edit2.Value); <-THIS IS THE EDITED PART!
% Label the image.
labeledImage = bwlabel(mask);
% Find the areas and perimeters
props = regionprops(labeledImage, 'Area', 'Perimeter');
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend')
allPerimeters = [props.Perimeter];
% Compute circularities
b=getappdata(0,'circle')
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
sortedC = sort(circularities, 'descend')
% Keep conly blobs that are nowhere close to circular or compact.
minAllowableCircularity = 10;
keeperIndexes = find(circularities >= minAllowableCircularity);
mask = ismember(labeledImage, keeperIndexes);
For some reason, when I change the value directly in the code, it works on the image, but when I put in my input in the exit text bar, it doesn't seem to work. The image gets rid of all the noise instead of amount depending on the inputted value. Attached above is an image of the layout of my GUI.

As you can see from the image above, I wanted an input of 40 for the function mask = bwareaopen(mask,500), and there is still an absence of noise in the picture. How do I fix this to easily change the parameters using the gui?
Image Analyst
2017년 8월 7일
편집: Image Analyst
2017년 8월 7일
That's not right. The Value property is not the string value converted to a number. Basically, don't use the value property for edit text boxes. Use the String property and convert that to double. Do this:
smallestAllowableArea = str2double(handles.edit2.String);
mask = bwareaopen(mask, smallestAllowableArea);
Justin Johnson
2017년 8월 8일
@jan simon: I got the image from google images so I didn't think it was a big deal.
Justin Johnson
2017년 8월 8일
Ok, maybe i'm confused by the code here. Where in the code allows for me to adjust how much noise I would like to eliminate? I thought it was the
mask = bwareaopen(mask, 500);
but no matter what I change to numeric value to, I still get a perfect picture with no noise. I tried playing around with the code, but it still comes out to be perfect.
Jan
2017년 8월 8일
편집: Jan
2017년 8월 8일
@Justin: This is a bold interpretation of the copy right. Not everything offer by Google "for free" can be copied without charges.
See https://de.123rf.com/photo_16528025_grunge-textured-concrete-sidewalk-with-cracks.html: This is a commercial service. As far as I can see, the download in the posted resolution costs 3,90€ (3 credits), but then without the visible watermark.
Image Analyst
2017년 8월 8일
Justin, maybe you're mistakenly displaying the original image instead of the "fixed" one. Who is sponsoring your research? Can you get some images from your sponsor?
Justin Johnson
2017년 8월 25일
@jan Simon: My apologies. I will definitely keep that in mind. Image Analyst: I figured it out. I forgot that there were two thresholds that I needed to satisfy in the code.
Justin Johnson
2017년 8월 25일
Ok, one more thing I would like to do. How can I "manually" modify a certain area within the image? I was thinking about cropping the image proportion and strategically placing it back, but i know that there is definitely a convenient way to choose which area I want to work with.I'm not doing any real research. I'm personally interested in how deformation and cracking of ceramics and I though what cool way to learn more about coding than this. I'm really enjoying my little project because I am defiantly learning a lot.
Justin Johnson
2017년 8월 25일
Guess i'm asking is there a function that will allow me to change a particular region of interest within a certain image? If so, what is it called so I can look into it?
Image Analyst
2017년 8월 25일
Yes you can use indexing or masking. For indexing just operate on grayImage(row1:row2, col1:col2). If you have a non-rectangular area (a mask), operate on grayImage(mask).
Justin Johnson
2017년 9월 1일
Yes, but I would like to manually erase noise from a particular area in the picture.How would grayImage(row1:row2, col1:col2) would allow me to do that?
Justin Johnson
2017년 9월 1일
Also, I wold like to thank you for your help. I am going through everything i'm learning and it is really helping me understand this!
Image Analyst
2017년 9월 1일
To manually erase some region, use imfreehand to zero out that region. I attach a demo.
Justin Johnson
2017년 9월 1일
Am I suppose to upload an image because when I try to run it I get the error "Error using cd Cannot CD to (No directory specified). "
Image Analyst
2017년 9월 1일
편집: Image Analyst
2017년 9월 1일
You can use the green and brown frame icon to the left of the paper clip icon.
Justin Johnson
2017년 9월 1일
편집: Justin Johnson
2017년 9월 1일

I guess we can continue to use this image as an example.
Image Analyst
2017년 9월 2일
That looks like the image we've already been using all along. Isn't the problem solved yet? If not, why not?
Justin Johnson
2017년 9월 2일
No no, it is. I just wanted to know how could I take this image and instead of clearing the noise of the whole image, I just clear it at a particular section of it.
Image Analyst
2017년 9월 2일
Create a mask, like with poly2mask() or some other way. Then you can erase non-mask regions:
maskedImage = grayImage; % Initialize
maskedImage(~mask) = 0; % Erase outside of the mask.
Then do your cleaning on maskedImage to get a new maskedImage. Then replace the masked portions of the original with the cleaned image
grayImage(mask) = maskedImage(mask);
Justin Johnson
2017년 9월 5일
How would you upload an image? I don't understand this part of the code: "
Change the current folder to the folder of this m-file.
if(~isdeployed)
cd(fileparts(which(mfilename)));
Image Analyst
2017년 9월 5일
Don't worry about it - delete it. Just start with the code starting at the line:
% Ask user to draw freehand mask.
Change variable name from grayImage to whatever you have.
Justin Johnson
2017년 9월 5일
I keep getting 'Undefined function or variable 'msgbox'.' as an error message
Image Analyst
2017년 9월 5일
msgbox() is a built-in function. You should have it unless your installation is messed up. What happens if you do this
>> which -all msgbox
>> msgbox('test');
Justin Johnson
2017년 9월 5일
I get the error "'msgbox' not found. Undefined function or variable 'msgbox'. "
Image Analyst
2017년 9월 5일
Your MATLAB installation is screwed up. You should definitely have msgbox() just like everyone else. Try reinstalling. If you still don't have it, then call the Mathworks for fast and free telephone help.
Justin Johnson
2017년 9월 8일
편집: Justin Johnson
2017년 9월 8일
Ok so I got it to work. I was just a matter of resetting the software. Is there a way I can set grayImage equal to the file I want? I tried tried it with
'grayImage = imread(‘concrete_inverted.png’);'
and I get:
"grayImage = imread(‘concrete_inverted.png’);
↑
Error: The input character is not valid in MATLAB statements or expressions."
Image Analyst
2017년 9월 8일
Try no double quote at the beginning of the line and standard single quotes (not fancy "smart"/slanted/curly ones) around the filename:
grayImage = imread('concrete_inverted.png');
Justin Johnson
2017년 9월 9일
I like the nice interface it gives me, but is there a way for me to just apply the noise reduction code so just a particular region of the image?
Justin Johnson
2017년 9월 12일
Say I just want to apply the code on a particular section of the image. How could I apply the first code you gave me to a section of my choosing?
Image Analyst
2017년 9월 12일
I already told you and showed you above. Use masking. Fix the entire image, then combine the original image with the masked image to produce an image in which only the masked area is fixed:
grayImage(mask) = filteredImage(mask);
Justin Johnson
2017년 9월 13일
편집: Justin Johnson
2017년 9월 15일
Ah ok I understand now!So in this case I apply the code to a particular area in the image and then mask it over using:
grayImage(mask) = filteredImage(mask);
If that is the case, how would I restrict the original code you gave me to just an area of the image? Which function would I use for that?
Justin Johnson
2017년 9월 13일
I'm sorry I don't know why i'm in a state of confusion. Let me see if I can sum up my question and i'll be out of your way. I know your probably tired of me haha. 1. The free hand masking attachment you gave me doesn't seem to work or at least i'm just confused on how i'm suppose to manually remove noise from it. When apply it to my image, i just get the image back on an interface that won't let me do anything to it. Here is what I get:

I attached an image below so you can try it for yourself.
2. Could it be possible to apply the original noise reduction code to a given region of the image and mask it using
grayImage(mask) = filteredImage(mask);
if so, what function would I use to restrict the code to a given region.
I believe this is all I would like to do for this. Once again thank you for your help.
Justin Johnson
2017년 9월 15일
Could I create a binary mask using imfreehand and then mask that with the original image?
Justin Johnson
2017년 9월 15일
편집: Justin Johnson
2017년 9월 16일
Ok, so I create this code that will allow the user to free hand mask a region of interest.
grayImage = imread('concrete_inverted.png');
BW = im2bw(grayImage);
imshow(grayImage)
hFH = imfreehand();
binaryImage = createMask(hFH);
totalBinary = IInvIm(grayImage);
for k = 1:5
totalBinary = totalBinary;
imshow(totalBinary); drawnow
hFH = imfreehand();
binaryImage = createMask(hFH);
end
"IInvIm()" is a built in function I created. This function is show below:
function inverted = IInvIm(im)
grayImage = imread('concrete_inverted.png');
[rows, columns, numberOfColorChannels] = size(grayImage)
if numberOfColorChannels > 1
% If not gray scale then color.
% Uses the weighted sum of all channels to create a gray scale image.
end
% Display the image.
imshow(grayImage);
axis on;
axis image;
hp = impixelinfo();
% Binarize the image by thresholding.
BW = im2bw(grayImage);
mask = grayImage > 128;
BW = grayImage < 100;
invIm(grayImage);
% For some reason, the top two lines of his image are all white. Blacken those 2 lines:
mask(1:2, :) = false;
% Display the mask image.
% Get rid of small blobs.
mask = bwareaopen(mask, 10);
% Label the image.
labeledImage = bwlabel(mask);
% Find the areas and perimeters
props = regionprops(labeledImage, 'Area', 'Perimeter');
allAreas = [props.Area];
sortedAreas = sort(allAreas, 'descend')
allPerimeters = [props.Perimeter];
% Compute circularities
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas)
sortedC = sort(circularities, 'descend')
% Keep conly blobs that are nowhere close to circular or compact.
minAllowableCircularity = 10;
keeperIndexes = find(circularities >= minAllowableCircularity);
mask = ismember(labeledImage, keeperIndexes);
mask = ~bwareaopen(~mask,100);
imshow(mask);
axis on;
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
drawnow;
end
____________________________________________________
Although I am able to draw my region around the area of interest, the code still will not excuse because of the error:
Error using bwlabel
Expected input number 1, BW, to be two-dimensional.
Error in bwlabel (line 65)
validateattributes(BW, {'logical' 'numeric'}, {'real', '2d', 'nonsparse'}, ...
I'm not understanding what is going on.
Justin Johnson
2017년 9월 16일
I even tried installing another function to convert the image into a binary one and it still gives me the same error.
Justin Johnson
2017년 9월 16일
Ok after follow your demo and modifying my code, I believe I figured it out, I just can't seem to understand why I keep getting this error message after I changed the image to binary:
Error using bwlabel
Expected input number 1, BW, to be two-dimensional.
Error in bwlabel (line 65)
validateattributes(BW, {'logical' 'numeric'}, {'real', '2d', 'nonsparse'}, ...
Error in IInvIm (line 28)
labeledImage = bwlabel(mask);
추가 답변 (2개)
Image Analyst
2017년 6월 19일
Threshold it to find a binary image
binaryImage = grayImage > 128;
Then take blobs only, say, 50 pixels or larger, then fill holes.
binaryImage = bwareaopen(binaryImage, 50);
binaryImage = imfill(binaryImage, 'holes');
If you then want to deal with the binary image, fine. If you want to use it to mask (blacken) the black and salty regions from your gray scale image, do this:
grayImage(~binaryImage) = 0;
John BG
2017년 6월 21일
편집: John BG
2017년 6월 23일
Hi Justin Johnson
1.
to threshold the image, in order to get a binary use command imbinarize on only one RGB layer, for instance red:
clear all;close all;clc
A=imread('petri_123.jpg');
%figure(1);imshow(A);
B=imbinarize(A(:,:,1))

.
2.
B2=areaopen(B,50);figure(2);imshow(B2)
the suggested
B3=imfill(B,'holes');figure(3);imshow(B3)

.
fills up large areas that should remain black.
3.
another way is using imoverlay
Alab = rgb2lab(A);
[L,N] = superpixels(Alab,20000,'isInputLab',true);
BW = boundarymask(L);
figure(4);imshow(imoverlay(A,BW,'black'))

figure(5);imshow(imoverlay(A,BW,'red'))

% figure(10);imshow(imoverlay(A,BW,'white')) % doesn't work
pixelIdxList = label2idx(L);
meanColor = zeros(N,3);
[m,n] = size(L);
for i = 1:N
meanColor(i,1) = mean(Alab(pixelIdxList{i}));
meanColor(i,2) = mean(Alab(pixelIdxList{i}+m*n));
meanColor(i,3) = mean(Alab(pixelIdxList{i}+2*m*n));
end
numColors = 3;
[idx,cmap] = kmeans(meanColor,numColors,'replicates',2);
cmap = lab2rgb(cmap);
Lout = zeros(size(A,1),size(A,2));
for i = 1:N
Lout(pixelIdxList{i}) = idx(i);
end
B=label2rgb(Lout);
figure(6);imshow(B)

.
4.
Since the boundaries are cyan, extracting cyan
B1=B(:,:,1);B2=B(:,:,2);B3=B(:,:,3);
Lb2=find(B2);
Lb3=find(B3);
L23=intersect(Lb2,Lb3);
[Lx,Ly]=ind2sub(size(B2),L23);
D=zeros(size(B2));
for k=1:1:numel(Lx)
D(Lx(k),Ly(k))=255;
end
figure(7);imshow(D)
B13=B(:,:,1)-B(:,:,3);B23=B(:,:,2)-B(:,:,3);
figure(8);imshow(B13)
figure(9);imshow(B23) % still some noise left

.
5.
the boundaries of interest have the highest pixel values, all RGB closest to 255, so setting the threshold at for instance 252
A1=A(:,:,1);A2=A(:,:,2);A3=A(:,:,3);
B=zeros(size(A1));
ct=0;
thr=252; % threshold
for k=1:1:numel(A1)
if A1(k)>thr && A2(k)>thr && A3(k)>thr
ct=[ct k];
end
end
ct(1)=[];
[nx,ny]=ind2sub(size(B),ct);
for k=1:1:numel(nx)
B(nx(k),ny(k))=255;
end
figure(5);imshow(B)

.
if you find this answer useful would you please be so kind to consider marking my answer as Accepted Answer?
To any other reader, if you find this answer useful please consider clicking on the thumbs-up vote link
thanks in advance
John BG
댓글 수: 3
Image Analyst
2017년 6월 24일
편집: Image Analyst
2017년 6월 24일
You're right - imfill() ends up filling some of the huge black regions that are connected all the way around, instead of only the small black holes in the white struts as I intended (as I found out when I tried it). That is why I changed it from imfill() to
mask = ~bwareaopen(~mask, 1000);
in my actual solution. That only fills in the tiny black holes. It would be a nice feature if imfill() had a range that you could specify, like bwareafilt() does, so one would not have to use the above trick (which I'm sure most people wouldn't know).
Unfortunately, I think Justin has long since forgotten about his post.
John BG
2017년 6월 25일
Image Analyst, your answer is far more accurate.
The question originator should give you the Accepted answer.
However I'd like to mention that when presenting this kind of image processing, larger images show more detail than the 4 subplots you have used.
subplot saves uploads, but showing each image in a separate figures helps spot details and choose.
Regards
John BG
Image Analyst
2017년 6월 26일
John, yes that is true, but then I'd have to post 4 images instead of one. I'm just used to writing code to show images in a 2 by 2 array. But sometimes small details get subsampled away.
참고 항목
카테고리
Help Center 및 File Exchange에서 Deep Learning Toolbox에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- 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)
아시아 태평양
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)