Extract object from image in matlab

I am currently studying image processing using Matlab. What I'm trying to do is find all the letters a in the following image and delete everything else.

a.tiff

First of all, I convert the image to binary. Then I try to get rid of the noise using a median filter. Within some borders there are some spaces that I fill in when opening the image. But then I got stuck, I found something on the Internet (which I don’t quite understand) with which I can select spaces from all a.

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 
+5
source share
1 answer

This is a good problem to solve. This is an approach that you could use, but I admit that it is by no means ideal and may not be so reliable. Hope this gives you ideas ...

What I did basically filters the image using a median filter (like you do) and removes small elements using bwareaopen . Then I called regionprops to get a bunch of properties, among which the most important are area and eccentricity . The idea was that all the letters "a" should have somewhat similar eccentricity, so as soon as we find out the eccentricity of one letter, we can find other letters that have the same. You could probably make the code more reliable by using additional properties that make letters stand out from the rest; perhaps the ratio MajorAxisLength/MinorAxisLength , for example. I will leave this part to you :)

Thus, the easiest way to select a letter in this case is to select the object with the largest area, which is a large a in the center of your image. As soon as we have its eccentricity, we can apply a certain threshold and select only those objects that were found using regionprops that have eccentricity relative to similar ones. The average media center and the bwareaopen call applied earlier are important here, because the kind of noise in the four rectangles on the right can complicate the situation if they are not removed, as some of the random spots will probably have an eccentricity similar to our traffic letter β€œa”.

That being said, here is the commented code. Please note that I changed the name of your variable text 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 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 (ie 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. Eccentricity 0 means circle and eccentricity 1 means 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 the conclusion, with centroids in the form of red dots and bounding rectangles in the form of yellow rectangles:

enter image description here

It was fun! Hope I can help. You may need to adapt the code for other letters or if you have other circle objects in your image, but I think that is the beginning.

+9
source

All Articles