Uno dei progetti più interessanti a cui ho lavorato negli ultimi due anni è stato un progetto sull'elaborazione delle immagini . L'obiettivo era sviluppare un sistema in grado di riconoscere le "lattine" della Coca-Cola (nota che sto sottolineando la parola "lattine", vedrai perché tra un minuto). Di seguito puoi vedere un esempio, con la lattina riconosciuta nel rettangolo verde con scala e rotazione.
Alcuni vincoli al progetto:
- Lo sfondo potrebbe essere molto rumoroso.
- La lattina potrebbe avere qualsiasi scala o rotazione o persino orientamento (entro limiti ragionevoli).
- L'immagine potrebbe presentare un certo grado di sfocatura (i contorni potrebbero non essere completamente dritti).
- Nell'immagine potrebbero esserci delle bottiglie di Coca-Cola e l'algoritmo dovrebbe rilevare solo la lattina !
- La luminosità dell'immagine potrebbe variare molto (quindi non puoi fare affidamento "troppo" sul rilevamento del colore).
- La lattina potrebbe essere parzialmente nascosta ai lati o al centro e possibilmente in parte nascosta dietro una bottiglia.
- Non ci potrebbe essere alcuna possibilità nell'immagine, nel qual caso non devi trovare nulla e scrivere un messaggio dicendo così.
Quindi potresti finire con cose difficili come questa (che in questo caso il mio algoritmo ha fallito totalmente):
Ho fatto questo progetto un po 'di tempo fa e mi sono divertito molto a farlo, e ho avuto una buona realizzazione. Ecco alcuni dettagli sulla mia implementazione:
Lingua : Fatto in C ++ usando la libreria OpenCV .
Pre-elaborazione : per la pre-elaborazione dell'immagine, ovvero trasformando l'immagine in una forma più grezza da dare all'algoritmo, ho usato 2 metodi:
- Modifica del dominio del colore da RGB a HSV e filtro basato sulla tonalità "rossa", saturazione al di sopra di una certa soglia per evitare i colori di tipo arancione e filtro di basso valore per evitare i toni scuri. Il risultato finale era un'immagine binaria in bianco e nero, in cui tutti i pixel bianchi rappresentavano i pixel che corrispondono a questa soglia. Ovviamente c'è ancora molta schifezza nell'immagine, ma questo riduce il numero di dimensioni con cui devi lavorare.
- Filtro del rumore utilizzando il filtro mediano (prendendo il valore medio dei pixel di tutti i vicini e sostituendo il pixel con questo valore) per ridurre il rumore.
- Utilizzando il filtro di rilevamento dei bordi di Canny per ottenere i contorni di tutti gli elementi dopo 2 passaggi precedenti.
Algoritmo : l'algoritmo stesso che ho scelto per questo compito è stato preso da questo fantastico libro sull'estrazione di feature e chiamato Generalized Hough Transform (piuttosto diverso dalla normale Hough Transform). Fondamentalmente dice alcune cose:
- Puoi descrivere un oggetto nello spazio senza conoscere la sua equazione analitica (che è il caso qui).
- È resistente alle deformazioni dell'immagine come ridimensionamento e rotazione, in quanto testerà sostanzialmente l'immagine per ogni combinazione di fattore di scala e fattore di rotazione.
- Utilizza un modello di base (un modello) che l'algoritmo "apprenderà".
- Ogni pixel rimanente nell'immagine del contorno voterà per un altro pixel che presumibilmente sarà il centro (in termini di gravità) del tuo oggetto, in base a ciò che ha appreso dal modello.
Alla fine, finisci con una mappa di calore dei voti, ad esempio qui tutti i pixel del contorno della lattina voteranno per il suo centro gravitazionale, quindi avrai molti voti nello stesso pixel corrispondente al al centro e vedrà un picco nella mappa di calore come di seguito:
Una volta che lo hai, una semplice euristica basata su soglia può darti la posizione del pixel centrale, da cui puoi derivare la scala e la rotazione e quindi tracciare il tuo piccolo rettangolo attorno ad esso (la scala finale e il fattore di rotazione saranno ovviamente relativi al tuo modello originale). In teoria almeno ...
Risultati : ora, mentre questo approccio ha funzionato nei casi di base, in alcune aree era gravemente carente:
- È estremamente lento ! Non lo sto sottolineando abbastanza. È stato necessario quasi un giorno intero per elaborare le 30 immagini di prova, ovviamente perché avevo un fattore di ridimensionamento molto elevato per la rotazione e la traduzione, poiché alcune lattine erano molto piccole.
- Era completamente perso quando le bottiglie erano nell'immagine, e per qualche motivo quasi sempre trovava la bottiglia invece della lattina (forse perché le bottiglie erano più grandi, quindi avevano più pixel, quindi più voti)
- Anche le immagini sfocate non andavano bene, poiché i voti finivano in pixel in punti casuali intorno al centro, finendo così con una mappa di calore molto rumorosa.
- La varianza nella traduzione e nella rotazione è stata raggiunta, ma non nell'orientamento, il che significa che una lattina che non era direttamente rivolta verso l'obiettivo della fotocamera non è stata riconosciuta.
Potete aiutarmi a migliorare il mio algoritmo specifico , utilizzando esclusivamente le funzionalità OpenCV , per risolvere i quattro problemi specifici citati?
Spero che alcune persone imparino anche qualcosa da esso, dopo tutto penso che non solo le persone che fanno domande dovrebbero imparare. :)