Ci sono due modi per avvicinarsi a questo, in base alle proprie preferenze.
Metodo # 1 - Utilizzando bwareaopen
un modo economico per fare questo sarebbe per invertire l'immagine in modo che i pixel degli oggetti sono bianchi, invece di nero, quindi di eseguire una chiusura morfologica sull'immagine e la rimozione di quelle aree che cadere sotto una certa quantità. La chiusura si unirebbe alle regioni disconnesse e approfittando del fatto che unire la "struttura" genererebbe una regione con una vasta area, è possibile soglia per l'area di ciascuna regione ed eliminare quelle regioni che scendono al di sotto di una certa quantità.
È quindi possibile ripristinare l'immagine originale eseguendo semplicemente un valore logico AND
con l'immagine invertita e il risultato chiuso, quindi ripristinando questo risultato intermedio. L'effetto di ciò sarebbe che conserviamo solo i pixel che appartengono all'immagine originale a causa dell'operazione di chiusura che crea artificialmente pixel dell'oggetto. Nello specifico, l'unione delle regioni vicine della struttura creerebbe nuovi pixel oggetto e quindi l'esecuzione di un valore AND
assicurerà che quei pixel non in comune con l'originale vengano rimossi. Dato che questo viene eseguito sul retro del risultato originale, il ripristino riporta al dominio originale dei pixel dell'oggetto che sono neri anziché bianchi.
Qualcosa di simile a questo:
%// Read in image from StackOverflow
im = imread('http://i.stack.imgur.com/A7iT7.png');
%// Invert image
im = ~im;
%// Define 50 x 50 structuring element and close the image
se = strel('square', 50);
out = imclose(im, se);
%// Remove regions whose areas fall below 10000 pixels
out = bwareaopen(out, 10000);
%// Remove out extraneous closing areas by ANDing with inverted image
%// then reinvert to bring back to original label scheme
out = ~(im & out);
%// Show the image
imshow(out);
Riceviamo questa immagine:
Note
- La funzione
imclose
si esibirà la chiusura morfologica per voi con un elemento strutturante definito da strel
. Ho usato un quadrato 50 x 50 per garantire che abbiamo una finestra abbastanza grande per unire insieme i pixel degli oggetti vicini.
- La funzione
bwareaopen
acquisisce un'immagine binaria e rimuove le aree le cui aree di pixel scendono al di sotto di una certa quantità. Dopo aver effettuato una chiusura, avrai due regioni collegate: la parte superiore dell'immagine con la struttura e la parte inferiore con il testo. Con la sperimentazione, 10000 pixel hanno rimosso la regione nella parte inferiore.
Metodo # 2 - Utilizzare regionprops
correlati al metodo # 1, un metodo alternativo per fare questo ed essere la soglia agnostica è di andare con la vostra idea originale. Esegui l'operazione di chiusura, ma poi valuta le aree di ciascuna delle regioni collegate e seleziona quella con l'area più grande. Quello che consiglio è di usare regionprops
in quel caso, che è una funzione che è specificamente progettata per analizzare le caratteristiche di regioni dell'immagine distinte. L'output sarà una struttura degli elementi N
, dove N
è il numero totale di oggetti unici e connessi trovati nell'immagine e ogni struttura contiene i campi di proprietà che desideri misurare nell'immagine. Nel tuo caso, specifica gli attributi 'Area'
e 'PixelIdxList'
che contengono le aree e le posizioni dei pixel principali delle colonne di ciascuna regione.
Si trova l'area massima complessiva e si utilizzano le posizioni dei pixel corrispondenti e si imposta una mappa di output con la quale è logico AND
.
Qualcosa di simile a questo:
%// Read in image from StackOverflow
im = imread('http://i.stack.imgur.com/A7iT7.png');
%// Invert image
im = ~im;
%// Define 50 x 50 structuring element and close the image
se = strel('square', 50);
out = imclose(im, se);
s = regionprops(out, 'Area', 'PixelIdxList'); %// Apply regionprops
%// Find the region with the max area
[~,id] = max([s.Area]);
%// Create an output mask with the largest area
%// Make logical
out = false(size(im));
%// Set pixels from largest area
out(s(id).PixelIdxList) = true;
%// Rest of the logic from before
%// Remove out extraneous closing areas by ANDing with inverted image
%// then reinvert to bring back to original label scheme
out = ~(im & out);
%// Show the image
imshow(out);
si dovrebbe ottenere esattamente gli stessi risultati come il primo metodo.
La domanda può sembrare stupida, ma qual è la differenza tra le parti che vuoi e quelle che non vuoi? Entrambe sono linee e caratteri. Forse rilevi il divario verticale (usa la somma delle righe) e dividi lì? Forse usare l'imerode per connettere entrambe le aree nere, quindi segmentare con bwlabel? – Daniel