Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract object from image in Matlab

I'm currently learning image processing with Matlab. What I'm trying to do is to find in the following image all the letter a's and remove all the rest.

a.tiff

First of all I convert the image to a binary one. Then I try to get rid of the noise by using a median filter. There are some gaps in some of tha a's borders, which I fill by opening the image. But then I get stuck, I found some things on the internet (which I do not completely understand) with which I am able to select the gaps from all the a's.

What should I do next?

My code is as follows:

text = imread('http://i.stack.imgur.com/N4nCm.png');
text = mat2gray(text);

% find threshold and chance to binary image
border = graythresh(text);
textbw = im2bw(text, border);
imshow(textbw);

% remove noise with median filter
textfilt = medfilt2(textbw);

% remove small holes in the border of the a
se = strel('disk', 4);
texter = imopen(textfilt, se);

% find holes
s = regionprops(texter, 'BoundingBox');
bb = round(reshape([s.BoundingBox], 4, []).');

% show original image with holes
imshow(textbw);

for idx = 1 : numel(s)
    rectangle('Position', bb(idx,:), 'edgecolor', 'red');
end
like image 528
boortmans Avatar asked May 06 '15 20:05

boortmans


People also ask

What is Bwareafilt Matlab?

example. BW2 = bwareafilt( BW , range ) extracts all connected components (objects) from the binary image BW , where the area of the objects is in the specified range , producing another binary image BW2 . bwareafilt returns a binary image BW2 containing only those objects that meet the criteria.

What is Bwpropfilt Matlab?

bwpropfilt returns a binary image BW2 containing only those objects that meet the criteria. example. BW2 = bwpropfilt( BW , prop , n ) sorts the objects based on the value of the specified property, prop , returning a binary image that contains only the top n largest objects.

What is Regionprops Matlab?

example. stats = regionprops( BW , properties ) returns measurements for the set of properties for each 8-connected component (object) in the binary image, BW . You can use regionprops on contiguous regions and discontiguous regions (see More About). Note.

What is Bwlabel Matlab?

example. L = bwlabel( BW ) returns the label matrix L that contains labels for the 8-connected objects found in BW . L = bwlabel( BW , conn ) returns a label matrix, where conn specifies the connectivity.


1 Answers

That is a nice problem to tackle. Here is an approach you could use, but I admit that it is by no means perfect and might not be that robust. Hopefully it will give you ideas...

What I did is basically filter the image with a median filter (as you did) and removed small elements using bwareaopen. Then I called regionprops to get a bunch of properties, among which the most important are the area and eccentricity. The idea was that all letters "a" should have a somewhat similar eccentricity, therefore once we know the eccentricity of one letter we can find the other letters that have about the same. You could probably make the code more robust using additional properties that make the letters stand out from the rest; maybe the ratio MajorAxisLength/MinorAxisLength for instance. I'll leave that part up to you :)

So the easiest way to pick a letter in this case was to select the object with the largest area, which is the big a at the center of your image. Once we have its eccentricity, we can apply some threshold and select only those objects found using regionprops that have an eccentricity about similar. The median filter and call to bwareaopen applied earlier are important here because the kind of noise in the 4 boxes on the right can complicate things if they are not removed, as a few of the random spots are likely to have an eccentricity similar to our dear letter "a".

That being said, here is the commented code. Note that I changed the name of your text variable to textIm since text is a Matlab function.

clc
clear
close all

textIm = imread('http://i.stack.imgur.com/N4nCm.png');


%// find threshold and change to binary image
border = graythresh(textIm);

%// =========== NEW \\ ===========
%// NOTICE the use of ~im2bw(...)
textbw = ~im2bw(textIm, border);

%// remove noise with median filter

%// =========== NEW \\ ===========
textfilt = medfilt2(textbw,[7 7]);
textfilt = bwareaopen(textfilt,8);

%// =========== NEW \\ ===========
%// Use an absurdely large line structuring element oriented at 25 degrees
%// to make the a's stand out

se = strel('line', 20 ,25);
textfilt = imclose(textfilt, se);

%// Get a couple properties. Note the "Eccentricity"
S = regionprops(textfilt, 'Area','Eccentricity','Centroid','BoundingBox');

All_areas = vertcat(S.Area);

%// Find the largest element (i.e. the big a). We will use it to get its
%// eccentricity and fetch other a's.

[MaxArea, MaxAreaIdx] = (max(All_areas(:)));

%// Get eccentricity of largest letter.
RefEcc = S(MaxAreaIdx).Eccentricity

Here the eccentricity of the large "a" is 0.6654. An eccentricity of 0 means a circle and an eccentricity of 1 means a line.

%// Just concatenate everything. Easier to work with.
All_Ecc = vertcat(S.Eccentricity);
All_Centroids = vertcat(S.Centroid);
All_BB = vertcat(S.BoundingBox)

%// Find elements that have the approximate eccentricity of the large a
%// found earlier. You can be more/less stringent and add more conditions here.

PotA = find(All_Ecc > RefEcc*.8 & All_Ecc < RefEcc*1.2)

%// Display output with centroids and bounding boxes.
imshow(textIm)
hold on

scatter(All_Centroids(PotA,1),All_Centroids(PotA,2),60,'r','filled');

for k = 1:numel(PotA)

rectangle('Position',All_BB(PotA(k),:),'EdgeColor','y','LineWidth',2)
end

And output, with centroids as red dots and bounding boxes as yellow rectangles:

enter image description here

That was fun! Hope I could help somehow. You might need to adapt the code for other letters or if you have other circle-ish objects in your image, but I guess that's a start.

like image 118
Benoit_11 Avatar answered Oct 28 '22 04:10

Benoit_11