2015-05-06 8 views
5

Attualmente sto imparando l'elaborazione delle immagini con Matlab. Quello che sto cercando di fare è trovare nella seguente immagine tutta la lettera a e rimuovere tutto il resto.Estrai oggetto dall'immagine in Matlab

a.tiff

Prima di tutto mi converte l'immagine in un unico binario. Quindi provo a liberarmi del rumore usando un filtro mediano. Ci sono alcune lacune in alcuni dei confini di a, che riempio aprendo l'immagine. Ma poi mi blocco, ho trovato alcune cose su internet (che non capisco completamente) con cui sono in grado di selezionare gli spazi tra tutte le a.

Cosa devo fare dopo?

Il mio codice è il seguente:

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 
+0

Hai provato tecniche di correlazione/corrispondenza del modello con un'immagine modello della lettera "a" ridimensionata a diverse scale? – eigenchris

risposta

9

Questo è un bel problema da affrontare. Ecco un approccio che potresti usare, ma ammetto che non è affatto perfetto e potrebbe non essere così robusto. Speriamo che possa darti idee ...

Quello che ho fatto è fondamentalmente filtrare l'immagine con un filtro mediano (come hai fatto tu) e rimuovere piccoli elementi usando bwareaopen. Quindi ho chiamato regionprops per ottenere un gruppo di proprietà, tra le quali le più importanti sono le area e eccentricity. L'idea era che tutte le lettere "a" dovessero avere un'eccentricità alquanto simile, quindi una volta che conosciamo l'eccentricità di una lettera possiamo trovare le altre lettere che hanno lo stesso. Probabilmente potresti rendere il codice più robusto usando proprietà aggiuntive che fanno risaltare le lettere dal resto; forse il rapporto MajorAxisLength/MinorAxisLength per esempio. Lascerò questa parte a te :)

Quindi il modo più semplice per scegliere una lettera in questo caso era selezionare l'oggetto con l'area più grande, ovvero il grande a al centro dell'immagine. Una volta che abbiamo la sua eccentricità, possiamo applicare qualche soglia e selezionare solo gli oggetti trovati usando regionprops che hanno un'eccentricità simile. Il filtro mediano e la chiamata a bwareaopen applicati in precedenza sono importanti qui perché il tipo di rumore nei 4 riquadri sulla destra può complicare le cose se non vengono rimossi, poiché alcuni dei punti casuali possono avere un'eccentricità simile alla nostra cara lettera a".

Detto questo, ecco il codice commentato. Si noti che ho cambiato il nome della variabile text in textIm poiché text è una funzione Matlab.

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 

Qui l'eccentricità del grande "a" è 0,6654. Un'eccentricità di 0 significa un cerchio e un'eccentricità di 1 significa una linea.

%// 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 

e output, con centroidi come puntini rossi e le caselle di delimitazione come rettangoli gialli:

enter image description here

E 'stato divertente! Spero di poter aiutare in qualche modo. Potrebbe essere necessario adattare il codice per altre lettere o se ci sono altri oggetti circolari nell'immagine, ma immagino che sia un inizio.

+2

La bellezza di questo post non può essere spiegata con le mie parole. +1. – rayryeng

+1

haha ​​wow è un grande complimento @rayryeng, in particolare proveniente da te :) Merci beaucoup mon ami! –

+1

Lavoro molto bello, signore! +1 –