[c++] Elaborazione delle immagini: miglioramento dell'algoritmo per il riconoscimento "Coca-Cola Can"


11 Answers

Per accelerare le cose, vorrei approfittare del fatto che non ti viene chiesto di trovare un'immagine / oggetto arbitrario, ma in particolare uno con il logo Coca-Cola. Questo è significativo perché questo logo è molto distintivo e dovrebbe avere una caratteristica, la firma invariante scala nel dominio della frequenza, in particolare nel canale rosso di RGB. Vale a dire, il modello alternato di rosso-a-bianco-rosso incontrato da una linea di scansione orizzontale (allenato su un logo allineato orizzontalmente) avrà un "ritmo" distintivo mentre passa attraverso l'asse centrale del logo. Quel ritmo si "accelera" o "rallenta" a diverse scale e orientamenti, ma rimarrà proporzionalmente equivalente. È possibile identificare / definire alcune dozzine di tali linee di scansione, sia orizzontalmente che verticalmente attraverso il logo e molte altre in diagonale, in uno schema a stella. Chiama queste "linee di scansione della firma".

La ricerca di questa firma nell'immagine di destinazione è una semplice questione di scansionare l'immagine in strisce orizzontali. Cerca una frequenza alta nel canale rosso (indicando il passaggio da una regione rossa a una bianca) e, una volta trovata, verifica se è seguita da uno dei ritmi di frequenza identificati nella sessione di allenamento. Una volta trovata una corrispondenza, conoscerai immediatamente l'orientamento e la posizione della linea di scansione nel logo (se tieni traccia di queste cose durante l'allenamento), quindi identificare i confini del logo da lì è banale.

Sarei sorpreso se questo non fosse un algoritmo linearmente efficiente, o quasi. Ovviamente non affronta la tua discriminazione in bottiglia, ma almeno avrai i tuoi loghi.

(Aggiornamento: per il riconoscimento delle bottiglie, cerco la coca (il liquido marrone) adiacente al logo, cioè all'interno della bottiglia, oppure, nel caso di una bottiglia vuota, cerco un cappuccio che avrà sempre il La stessa forma, dimensione e distanza dal logo sono in genere tutte bianche o rosse. Cerca una forma ellittica tinta unita dove dovrebbe essere un cappuccio, relativamente al logo. Non è infallibile, ovviamente, ma il tuo obiettivo qui dovrebbe essere trovare quelli facili in fretta .)

(Sono passati alcuni anni dai miei giorni di elaborazione delle immagini, quindi ho mantenuto questo suggerimento di alto livello e concettuale. Penso che potrebbe leggermente approssimare come un occhio umano potrebbe operare - o almeno come fa il mio cervello!)

Question

Uno dei progetti più interessanti su cui ho lavorato negli ultimi due anni è stato un progetto sull'elaborazione delle immagini . L'obiettivo era quello di sviluppare un sistema in grado di riconoscere le lattine di Coca-Cola (notare che sto sottolineando la parola "lattine", vedrete perché in un minuto). Puoi vedere un esempio qui sotto, con la lattina riconosciuta nel rettangolo verde con scala e rotazione.

Alcuni vincoli sul progetto:

  • Lo sfondo potrebbe essere molto rumoroso.
  • La lattina potrebbe avere qualsiasi scala o rotazione o anche orientamento (entro limiti ragionevoli).
  • L'immagine potrebbe avere un certo grado di sfocatura (i contorni potrebbero non essere interamente dritti).
  • Ci potrebbero essere bottiglie di Coca-Cola nell'immagine e l'algoritmo dovrebbe solo rilevare il barattolo !
  • La luminosità dell'immagine può variare molto (quindi non è possibile fare affidamento su "troppo" sul rilevamento del colore).
  • La lattina potrebbe essere parzialmente nascosta ai lati o al centro e probabilmente parzialmente nascosta dietro una bottiglia.
  • Non ci potrebbe essere alcuna lattina nell'immagine, nel qual caso non dovevi trovare nulla e scrivere un messaggio che dicesse così.

Quindi potresti finire con cose complicate come questa (che in questo caso ha avuto il mio algoritmo totalmente fallito):

Ho fatto questo progetto un po 'di tempo fa e mi sono divertito molto a farlo, e ho avuto un'implementazione decente. Ecco alcuni dettagli sulla mia implementazione:

Lingua : fatto in C ++ usando la libreria OpenCV .

Pre-elaborazione : per la pre-elaborazione dell'immagine, ovvero la trasformazione dell'immagine in una forma più grezza da assegnare all'algoritmo, ho utilizzato 2 metodi:

  1. Modifica del dominio dei colori da RGB a HSV e filtraggio basato sulla tonalità "rossa", saturazione superiore a una determinata soglia per evitare colori arancioni e filtro di valore basso 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 un sacco di schifezze nell'immagine, ma questo riduce il numero di dimensioni con cui devi lavorare.
  2. Filtraggio del rumore utilizzando il filtraggio mediano (prendendo il valore mediano del pixel di tutti i vicini e sostituendo il pixel con questo valore) per ridurre il rumore.
  3. Utilizzo di Canny Edge Detection Filter per ottenere i contorni di tutti gli elementi dopo 2 passaggi precedenti.

Algoritmo : l'algoritmo che ho scelto per questo compito è stato preso da this fantastico libro sull'estrazione delle feature e chiamato Generalized Hough Transform (molto diverso dalla normale Hough Transform). In pratica 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 il ridimensionamento e la rotazione, poiché testerà fondamentalmente l'immagine per ogni combinazione di fattore di scala e fattore di rotazione.
  • Usa un modello base (un modello) che l'algoritmo "apprenderà".
  • Ogni pixel rimasto nell'immagine del profilo voterà per un altro pixel che sarà presumibilmente il centro (in termini di gravità) dell'oggetto, in base a ciò che ha appreso dal modello.

Alla fine, si finisce con una mappa di calore dei voti, per esempio qui tutti i pixel del contorno della lattina voteranno per il proprio centro gravitazionale, quindi avrete molti voti nello stesso pixel corrispondente al centro, e vedrà un picco nella mappa di calore come di seguito:

Una volta ottenuto ciò, una semplice euristica basata sulla soglia può darti la posizione del pixel centrale, da cui puoi ricavare 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, è stato gravemente carente in alcune aree:

  • È estremamente lento ! Non lo sottolineerò abbastanza. Era 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 delle lattine erano molto piccole.
  • Era completamente perso quando le bottiglie erano nell'immagine e per qualche motivo quasi sempre trovavamo la bottiglia al posto del barattolo (forse perché le bottiglie erano più grandi, quindi avevano più pixel, quindi più voti)
  • Anche le immagini sfocate non erano buone, dal momento che i voti finivano in pixel in posizioni casuali attorno al centro, finendo quindi con una mappa di calore molto rumorosa.
  • In-varianza nella traslazione e nella rotazione è stata ottenuta, ma non nell'orientamento, il che significa che non è stato riconosciuto un barattolo che non si trovava direttamente di fronte all'obiettivo della telecamera.

Puoi aiutarmi a migliorare il mio algoritmo specifico , utilizzando esclusivamente le funzionalità OpenCV , per risolvere i quattro problemi specifici menzionati?

Spero che alcune persone impareranno qualcosa anche da questo, dopotutto penso che non solo le persone che fanno domande dovrebbero imparare. :)




In alternativa a tutte queste belle soluzioni, puoi addestrare il tuo classificatore e rendere l'applicazione robusta agli errori. Ad esempio, è possibile utilizzare Haar Training , fornendo un buon numero di immagini positive e negative del proprio target.

Può essere utile estrarre solo lattine e può essere combinato con il rilevamento di oggetti trasparenti.




If you are interested in it being realtime, then what you need is to add in a pre-processing filter to determine what gets scanned with the heavy-duty stuff. A good fast, very real time, pre-processing filter that will allow you to scan things that are more likely to be a coca-cola can than not before moving onto more iffy things is something like this: search the image for the biggest patches of color that are a certain tolerance away from the sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) of your coca-cola can. Start with a very strict color tolerance, and work your way down to more lenient color tolerances. Then, when your robot runs out of an allotted time to process the current frame, it uses the currently found bottles for your purposes. Please note that you will have to tweak the RGB colors in the sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) to get them just right.

Also, this is gona seem really dumb, but did you make sure to turn on -oFast compiler optimizations when you compiled your C code?




Ci sono un sacco di descrittori di colori usati per riconoscere gli oggetti, la carta qui sotto ne confronta molti. Sono particolarmente potenti se combinati con SIFT o SURF. SURF o SIFT da soli non sono molto utili in un'immagine di una coca cola in quanto non riconoscono molti punti di interesse, per cui è necessario disporre delle informazioni sul colore. Io uso BIC (Border / Interior Pixel Classi fi cation) con SURF in un progetto e ha funzionato benissimo per riconoscere gli oggetti.

Descrittori di colore per il recupero di immagini Web: uno studio comparativo




Questa potrebbe essere un'idea molto ingenua (o potrebbe non funzionare affatto), ma le dimensioni di tutte le lattine di coca sono fisse. Così può essere se la stessa immagine contiene sia una lattina che una bottiglia, quindi puoi distinguerle in base alle dimensioni (le bottiglie saranno più grandi). Ora a causa della profondità mancante (ad esempio la mappatura 3D alla mappatura 2D) è possibile che una bottiglia possa apparire ridotta e non ci sia una differenza di dimensioni. È possibile recuperare alcune informazioni sulla profondità utilizzando stereo-imaging e quindi ripristinare le dimensioni originali.




Se non sei limitato solo a una videocamera che non era in uno dei tuoi vincoli, forse puoi passare a utilizzare un sensore di distanza come Xbox Kinect . Con questo è possibile eseguire la segmentazione dell'immagine basata sulla profondità e sul colore. Ciò consente una separazione più rapida degli oggetti nell'immagine. È quindi possibile utilizzare la corrispondenza ICP o tecniche simili per uniformare la forma della lattina piuttosto che solo il contorno o il colore e, dato che è cilindrica, questa può essere un'opzione valida per qualsiasi orientamento se si dispone di una precedente scansione 3D della destinazione. Queste tecniche sono spesso abbastanza veloci soprattutto se utilizzate per uno scopo specifico che dovrebbe risolvere il tuo problema di velocità.

Potrei anche suggerire, non necessariamente per precisione o velocità, ma per divertimento potresti usare una rete neurale addestrata sulla tua immagine segmentata per identificare la forma della lattina. Questi sono molto veloci e possono spesso essere accurati fino all'80 / 90%. La formazione sarebbe un po 'troppo lunga, poiché dovresti identificare manualmente la lattina in ogni immagine.




The first things I would look for are color - like RED , when doing Red eye detection in an image - there is a certain color range to detect , some characteristics about it considering the surrounding area and such as distance apart from the other eye if it is indeed visible in the image.

1: First characteristic is color and Red is very dominant. After detecting the Coca Cola Red there are several items of interest 1A: How big is this red area (is it of sufficient quantity to make a determination of a true can or not - 10 pixels is probably not enough), 1B: Does it contain the color of the Label - "Coca-Cola" or wave. 1B1: Is there enough to consider a high probability that it is a label.

Item 1 is kind of a short cut - pre-process if that doe snot exist in the image - move on.

So if that is the case I can then utilize that segment of my image and start looking more zoom out of the area in question a little bit - basically look at the surrounding region / edges...

2: Given the above image area ID'd in 1 - verify the surrounding points [edges] of the item in question. A: Is there what appears to be a can top or bottom - silver? B: A bottle might appear transparent , but so might a glass table - so is there a glass table/shelf or a transparent area - if so there are multiple possible out comes. A Bottle MIGHT have a red cap, it might not, but it should have either the shape of the bottle top / thread screws, or a cap. C: Even if this fails A and B it still can be a can - partial.. This is more complex when it is partial because a partial bottle / partial can might look the same , so some more processing of measurement of the Red region edge to edge.. small bottle might be similar in size ..

3: Dopo l'analisi di cui sopra, cioè quando guarderei il lettering e il logo dell'onda, perché posso orientare la mia ricerca per alcune delle lettere nelle parole Come potreste non avere tutto il testo perché non ho tutto il può, l'onda si allinea in alcuni punti al testo (distanza saggia) in modo da poter cercare quella probabilità e sapere quali lettere dovrebbero esistere in quel punto dell'onda a distanza x.




Guardando la forma

Date un'occhiata alla forma della porzione rossa della lattina / bottiglia. Notate come la lattina si assottiglia leggermente in alto mentre l'etichetta della bottiglia è diritta. È possibile distinguere tra questi due confrontando la larghezza della porzione rossa per tutta la sua lunghezza.

Guardando in evidenza

Un modo per distinguere tra bottiglie e lattine è il materiale. Una bottiglia è di plastica mentre una lattina è in metallo di alluminio. In situazioni sufficientemente illuminate, osservare la specularità sarebbe un modo per raccontare un'etichetta di bottiglia da un'etichetta di lattina.

Per quello che posso dire, è così che un umano direbbe la differenza tra i due tipi di etichette. Se le condizioni di illuminazione sono scarse, ci sarà sicuramente qualche incertezza nel distinguere le due comunque. In tal caso, dovresti essere in grado di rilevare la presenza della bottiglia trasparente / traslucida stessa.




Non sono a conoscenza di OpenCV, ma guardando il problema logicamente penso che potresti differenziare tra bottiglia e lattina cambiando l'immagine che stai cercando, ad es. Coca Cola. Si dovrebbe incorporare fino alla parte superiore della lattina come nel caso in cui ci sia rivestimento d'argento in cima alla coca cola e in caso di bottiglia non ci sarà tale rivestimento d'argento.

Ma ovviamente questo algoritmo fallirà nei casi in cui la parte superiore del barattolo è nascosta, ma in tal caso anche l'umano non sarà in grado di distinguere tra i due (se è visibile solo la porzione di bottiglia / lattina di coca cola)




Non è difficile neanche per gli umani distinguere tra una bottiglia e una lattina nella seconda immagine (a condizione che la regione trasparente della bottiglia sia nascosta)?

Sono quasi la stessa eccezione fatta per una regione molto piccola (cioè, la larghezza nella parte superiore della lattina è un po 'piccola mentre l'involucro della bottiglia ha la stessa larghezza in tutto, ma un piccolo cambiamento vero?).

La prima cosa che mi è venuta in mente è stata controllare la parte superiore rossa della bottiglia. Ma è ancora un problema, se non c'è il massimo per la bottiglia, o se è parzialmente nascosto (come menzionato sopra).

La seconda cosa che pensavo riguardava la trasparenza della bottiglia. OpenCV ha alcuni lavori per trovare oggetti trasparenti in un'immagine. Controlla i link qui sotto.

In particolare, guarda questo per vedere con quale precisione rilevano il vetro:

Vedi il loro risultato di implmentazione:

Dicono che è l'implementazione del documento "A Geodesic Active Contour Framework for Finding Glass" by K. McHenry and J. Ponce, CVPR 2006. .. (Scarica la carta) .

Potrebbe essere utile nel tuo caso un po ', ma il problema sorge di nuovo se la bottiglia è piena.

Quindi penso che qui, puoi cercare prima il corpo trasparente delle bottiglie o una regione rossa collegata a due oggetti trasparenti lateralmente che è ovviamente la bottiglia. (Quando si lavora idealmente, un'immagine come segue.)

Ora puoi rimuovere la regione gialla, cioè l'etichetta della bottiglia ed eseguire l'algoritmo per trovare la lattina.

Ad ogni modo, questa soluzione ha anche diversi problemi come nelle altre soluzioni.

  1. Funziona solo se la tua bottiglia è vuota. In tal caso, dovrai cercare la regione rossa tra i due colori neri (se il liquido Coca Cola è nero).
  2. Un altro problema se la parte trasparente è coperta.

Ma comunque, se non ci sono nessuno dei problemi sopra nelle immagini, questo sembra essere un modo migliore.




È necessario un programma che impari e migliori l'accuratezza della classificazione organicamente dall'esperienza.

Suggerirò un apprendimento approfondito, con l'apprendimento profondo questo diventa un problema banale.

È possibile riqualificare il modello v3 di lancio su Tensorflow:

Come reintegrare lo strato finale di Inception per nuove categorie .

In questo caso, addestrerai una rete neurale convoluzionale per classificare un oggetto come una lattina di coca-cola oppure no.




Sono in ritardo di alcuni anni nel rispondere a questa domanda. Con lo stato dell'arte spinto ai limiti dalla CNN negli ultimi 5 anni, non avrei usato OpenCV per svolgere questo compito ora! ( So che hai specificamente desiderato le funzionalità di OpenCv nella domanda ) Ritengo che gli algoritmi di rilevamento degli oggetti come Faster-RCNN, YOLO, SSD, ecc., Possano affrontare questo problema con un margine significativo rispetto alle funzionalità di OpenCV. Se dovessi affrontare questo problema ora (dopo 6 anni !!) utilizzerei sicuramente Faster-RCNN .






Related