Domanda

Ho un'immagine con linee orizzontali e verticali. In effetti, questa immagine è il sito Web della BBC convertito in linee orizzontali e verticali. Il mio problema è che voglio essere in grado di trovare tutti i rettangoli nell'immagine. Voglio scrivere un programma per computer per trovare tutti i rettangoli. Qualcuno sa come fare questo o suggerire idee su come iniziare? Questo compito è facile per me come persona trovare i rettangoli visivi, ma non sono sicuro di come descriverlo come programma.

L'immagine è il sito Web della BBC qui http://www.bbc.co.uk/


Aggiornamento a questo, ho scritto il codice che converte l'immagine del sito Web della BBC in linea orizzontale e verticale, il problema è che queste linee non si incontrano completamente agli angoli e a volte non formano completamente un rettangolo. Grazie!

È stato utile?

Soluzione

Opencv (libreria di elaborazione delle immagini e visione artificiale scritta in c) ha un'implementazione per Hough Transform ( la semplice trasformazione hough trova linee in un'immagine, mentre quella generalizzata trova oggetti più complessi), quindi potrebbe essere un buon inizio. Per i rettangoli che hanno angoli chiusi ci sono anche rilevatori di angoli come cornerHarris che possono aiutare.

Ho eseguito la demo di houghlines fornita con opencv ed ecco il risultato sull'immagine che hai dato (linee rilevate contrassegnate in rosso): alt text
(fonte: splintec.com )

Altri suggerimenti

Credo che tu stia cercando la trasformazione Hough generalizzata .

Nella visione artificiale esiste un algoritmo chiamato Generalized Hough Transform che forse può risolvere il tuo problema . Dovrebbe esserci un codice open source che ha implementato questo algoritmo. Basta cercarlo.

Supponendo che sia un'immagine ragionevolmente priva di rumore (non un video di uno schermo), allora uno dei semplici algoritmi di allagamento dovrebbe funzionare. Potrebbe essere necessario eseguire una dilatazione / erosione sull'immagine per colmare le lacune.

Il modo normale di trovare le linee è una trasformazione di Hough (quindi trova le linee ad angolo retto) Opencv è il modo più semplice.

Dai un'occhiata a questa domanda OpenCV Object Detection - Center Point

Esistono diversi approcci al problema. Vorrei utilizzare uno elaborazione morfologica di immagini come questo . Avrai la flessibilità di definire "rettangolo" anche qualcosa che non è "chiuso esattamente" (dove l'algoritmo di riempimento fallirà).

Un'altra possibilità potrebbe essere quella di utilizzare un approccio machine learning , che sostanzialmente è più dati- guidato da definizione guidato come quello precedente. Dovrai fornire al tuo algoritmo diversi "esempi" di cosa sia un rettangolo e alla fine imparerà (con un bias e un tasso di errore) .

iterare da sinistra a destra fino a quando non si colpisce un pixel di colore, quindi utilizzare l'algoritmo di riempimento flood modificato. maggiori informazioni sull'algo flood flood @ wiki

un altro approccio sarebbe quello di trovare QUALSIASI pixel colorato sull'immagine e poi andare con

while(pixel under current is colored)
{
  lowest pixel coordinate = pixel under current
  current = pixel under
}

quindi fai lo stesso verso l'alto. ora hai definito una sola riga. quindi usa le estremità delle linee per approssimare le linee in rettangoli. se non sono pixel perfetti, potresti fare una sorta di tresholding.

Il riempimento dell'inondazione funzionerebbe oppure potresti utilizzare una modifica di un algoritmo di tracciamento dei bordi.

quello che fai è: crea un array 2d (o qualsiasi altra struttura di dati d2): ogni riga rappresenta una linea di pixel orizzontale sullo schermo e ogni colonna una linea verticale

scorre tutti i pixel, da sinistra a destra, e ogni volta che ne trovi uno colorato aggiungi le sue coordinate all'array

itera attraverso l'array e trova le linee e memorizza il pixel iniziale e finale per ognuno (diversa struttura di dati)

sapendo che l'inizio di ogni riga è il suo pixel sinistro / superiore, puoi facilmente verificare se 4 righe comprendono un rettangolo

Per ottenere dall'immagine che hai con le linee orizzontali e verticali quasi toccanti solo i rettangoli:

  1. Converti in binario (cioè tutte le righe sono bianchi, il resto è nero)
  2. Esegui una Dilatazione binaria (qui crei ogni pixel che tocca un pixel bianco nell'immagine sorgente o è un pixel bianco nell'immagine sorgente bianco. Il tocco è solo dritto (quindi ogni pixel "tocca" i pixel a sinistra, a destra, sopra e sotto di esso) questo è chiamato "4-connesso" ;
  3. ripeti il ??passaggio 3 alcune volte se gli spazi tra le estremità sono più grandi di 2 pixel di larghezza, ma non troppo spesso!
  4. Esegui un'operazione scheletro (qui rendi neri tutti i pixel dell'immagine di output se si tratta di un pixel bianco nell'immagine sorgente che tocca almeno un pixel nero e i pixel bianchi che tocca (nell'immagine sorgente) si toccano tutti Di nuovo tocco definito con 4-connessione. Vedi esempio sotto.
  5. Ripeti il ??passaggio 4 fino a quando l'immagine non cambia dopo una ripetizione (tutti i pixel bianchi sono estremità di linea o connettori)

Questo, con un po 'di fortuna, mostrerà prima le scatole con linee grasse spesse, lasciando artefatti grassi spessi su tutta l'immagine (dopo il passaggio 3) e poi dopo il passaggio 5 saranno stati rimossi tutti gli artefatti grassi spessi, mentre rimangono tutte le scatole. È necessario modificare il numero di ripetizioni nel passaggio 3 per ottenere i migliori risultati. Se sei interessato alla morfologia delle immagini, questo è il libro di un corso introduttivo davvero buono che ho seguito.

Esempio: (0 = nero, 1 = bianco, i pixel al centro di ciascun blocco 3x3 sono considerati, input left, output right)

011 => 011    
011 => 001  all other white pixels touch, so eliminate      
011 => 011    

010 => 010    
010 => 010  top pixel would become disconnected, so leave      
010 => 010    

010 => 010    
010 => 000  touches only one white pixel, so remove     
000 => 000    

010 => 010    
111 => 111  does not touch black pixels, leave    
010 => 010    

010 => 010    
011 => 011  other pixels do not touch. so leave    
000 => 000    
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top