MATLAB: Image Processing, How to separate this bird from background

filteringfourier transformimage processing

I am wondering to separate a bird from background itself, and I have tried some different filters and but its not removing white lines which are not , anybody has an idea!

Best Answer

Here is a description of the way I did it - but note that there are many different possibilities. If you try to do it this way and get stuck, show me what you've written and I'll try to help.
  1. I read the image into memory using imread, and thresholded it (using the < operator) to give me a true binary image. At the same time I inverted it, so that foreground pixels had the value 1 and background pixels were 0.
  2. I made the assumption that the bars are parallel to the rows of the image. (Actually this isn't quite true for the first bar.) For any image processing task, identifying the assumptions you can make is a crucial step. To use the assumption, I found the sum of the pixel values in each row of the binary image. Every row where the sum exceeded a threshold (I used 80% of the image width) was identified as being in a bar. This was simply a matter of thresholding the sum vector.
  3. I made an image of the bars. I started with an array of zeros and set every pixel in the rows in the bars to one.
  4. I removed the bars from the original binary image, using logical operators. That gave me a bird outline, but with gaps in it where the bars had been.
  5. I tidied up the bird outline to remove the single-pixel line that resulted from the misalignment of the top bar, using morphological functions imerode and imdilate, and a vertical structuring element. This also removed a few isolated pixels from the bird outline, and for a perfect solution I would spend more time thinking about this step.
  6. Filling in the gaps was the most complex part. I started by dilating the bird outline using a vertical structuring element, and finding the overlaps between this and the bar image using the & operator. This gave me a set of horizontal lines at the top and bottom edge of the part of each bar that crossed the bird. I deleted lines shorter than 5% of the width of the image, to tidy up the region round the bird's feet.
  7. I found the end points of the lines, again using morphological operations, and I sorted the points in order of increasing row number.
  8. I then took the end points in groups of 4 and used roipoly to make a mask for each group. This gave me a binary image of each section of bar where it passed in front of the bird, taking the outline of the bird to be a straight line in those regions where it is obscured by the bar.
  9. I combined the bar sections and the bird outline using the | operator, to finally give me the bird with the gaps filled in.
EDIT Now that any likely courswork deadline will have passed, here's my code corresponding to the steps above, as a demo for reference.
% 1. read the bird image as downloaded
imraw = imread('tempbird.jpg');
% make it into a proper binary image, foreground 1
im = imraw < max(imraw(:))/2;
imshow(im); pause
% 2. find the bar rows
bar_rows = sum(im, 2) > 0.8 * size(im, 2);
% 3. make a bar image
im_bars = false(size(im));
im_bars(bar_rows, :) = true;
% 4. remove the bars from the image
im_nobars = im & ~im_bars;
imshow(im_nobars); pause
% 5. tidy image by removing 1-pixel thick horizontal structures
im_nobars = imerode(im_nobars, [1; 1]);
im_nobars = imdilate(im_nobars, [1; 1]);
imshow(im_nobars); pause
% 6. dilate bars and get overlap with bird - a set of horizontal lines
bar_bounds = im_bars & imdilate(im_nobars, [1; 1; 1]);
imshow(bar_bounds); pause
% tidy overlap lines by removing small segments
minline = size(im, 2) / 20;
bar_bounds = bwareaopen(bar_bounds, minline);
imshow(bar_bounds); pause
% 7. find end points of overlap lines and sort them
[yleft, xleft] = find(~imerode(bar_bounds, [1 1 0]) & bar_bounds);
[yright, xright] = find(~imerode(bar_bounds, [0 1 1]) & bar_bounds);
[yleft, ind] = sort(yleft);
xleft = xleft(ind);
[yright, ind] = sort(yright);
xright = xright(ind);
% 8. fill in bar regions where bars cross bird
bars_in_bird = false(size(im));
for poly = 1:2:length(xleft)
x = [xleft(poly) xright(poly) xright(poly+1), xleft(poly+1)];
y = [yleft(poly) yright(poly) yright(poly+1), yleft(poly+1)] ...
+ [-0.5 -0.5 0.5 0.5];
bar_part = roipoly(im, x, y);
bars_in_bird = bars_in_bird | bar_part;
end
imshow(bars_in_bird); pause
% 9. combine bird and bars to give final bird outline
bird = ~(im_nobars | bars_in_bird);
imshow(bird);