5

As you see, I have shapes and their white boundaries. I want to fill the shapes in white color.

The input is: enter image description here

I would like to get this output: http://s12.postimage.org/z3txnlb3f/untitled33.png

Can anybody help me please with this code? it doesn't change the black ellipses to white. Thanks alot :]]

I = imread('untitled4.bmp');
Ibw = im2bw(I);
CC = bwconncomp(Ibw); %Ibw is my binary image
stats = regionprops(CC,'pixellist');

% pass all over the stats
for i=1:length(stats),
size = length(stats(i).PixelList);
% check only the relevant stats (the black ellipses)
if size >150 && size < 600 
    % fill the black pixel by white    
    x = round(mean(stats(i).PixelList(:,2)));
    y = round(mean(stats(i).PixelList(:,1)));
    Ibw = imfill(Ibw, [x, y]);
end;
end;

imshow(Ibw);
Alon Shmiel
  • 6,753
  • 23
  • 90
  • 138
  • Related to http://stackoverflow.com/questions/10053651/obtain-the-pixels-belonging-to-a-shape – Gray Apr 07 '12 at 15:05

2 Answers2

3

Your code can be improved and simplified as follows. First, negating Ibw and using BWCONNCOMP to find 4-connected components will give you indices for each black region. Second, sorting the connected regions by the number of pixels in them and choosing all but the largest two will give you indices for all the smaller circular regions. Finally, the linear indices of these smaller regions can be collected and used to fill in the regions with white. Here's the code (quite a bit shorter and not requiring any loops):

I = imread('untitled4.bmp');
Ibw = im2bw(I);

CC = bwconncomp(~Ibw, 4);
[~, sortIndex] = sort(cellfun('prodofsize', CC.PixelIdxList));

Ifilled = Ibw;
Ifilled(vertcat(CC.PixelIdxList{sortIndex(1:end-2)})) = true;
imshow(Ifilled);

And here's the resulting image:

enter image description here

gnovice
  • 125,304
  • 15
  • 256
  • 359
1

If your images are all black&white, and you have the image processing toolkit, then this looks like what you need: http://www.mathworks.co.uk/help/toolbox/images/ref/imfill.html

Something like:

imfill(image, [startX, startY])

where startX, startY is a pixel in the area that you want to fill.

Richante
  • 4,353
  • 19
  • 23
  • You can use bwconncomp(http://www.mathworks.co.uk/help/toolbox/images/ref/bwconncomp.html). If you do something like `c = bwconncomp(image)`, then you can see the components with `c.PixelIdxList`. These are linear indexes into the image, telling you which pixels are in which component. You want to ignore one component (the background), which you could just assume is the largest list in PixelIdxList, or you could look for a list that contains an edge pixel. From the rest of the components in c, you need to check whether they are black. If they are, use imfill on them. – Richante Apr 07 '12 at 14:34
  • Oh, I notice your image has a huge white border too. You want to ignore that component as well (so maybe ignore the largest two components in `PixelIdxList`). – Richante Apr 07 '12 at 14:39
  • thank you very much! I feel that I'm so close. I updated my code and pasted it above.. unfortunately, the pic is the same pic :/ – Alon Shmiel Apr 07 '12 at 15:20
  • 1
    Yes, that looks close. Replace the loop over j with: `x = round(mean(stats(i).PixelList(:,2))); y = round(mean(stats(i).PixelList(:,1)));` (notice that x and y are the other way around). Also replace `bw5 = imfill(Ibw, [x, y]);` with `Ibw = imfill(Ibw, [x, y]);` and then show Ibw at the end. – Richante Apr 07 '12 at 15:51