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


1659

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.

Corrispondenza del modello

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):

Fallimento totale

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:

  1. 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. Immagine binarizzata
  2. 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.
  3. Utilizzando il filtro di rilevamento dei bordi di Canny per ottenere i contorni di tutti gli elementi dopo 2 passaggi precedenti. Rilevamento del contorno

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:

GHT

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. :)


45
Si potrebbe dire che questa domanda è più appropriata su dsp.stackexchange.com, o stats.stackexchange.com, e sicuramente dovresti prendere in considerazione di chiedere di nuovo anche a quei siti.
ely,

49
La prima cosa da fare qui è analizzare perché stanno accadendo i diversi casi di fallimento. Ad esempio, isolare esempi di luoghi in cui vincono le bottiglie, in cui le immagini sono sfocate, ecc. Ed eseguire alcune analisi statistiche per apprendere la differenza tra le loro rappresentazioni di Hough e quelle che si desidera vengano rilevate. Alcuni ottimi posti per conoscere approcci alternativi sono qui e qui
ely

7
@stacker ha ragione. Per la velocità, desideri ottenere funzionalità economiche per il calcolo, come istogrammi di gradienti orientati. Un primo approccio davvero ingenuo sarebbe quello di etichettare manualmente un gruppo di rettangoli di lattine in alcune immagini di addestramento e di usarli oltre a esempi negativi casuali per addestrare un classificatore SVM o un albero delle decisioni. La formazione richiederà più tempo, ma l'esecuzione su nuove immagini sarà molto più veloce. Sto programmando di scrivere questo metodo quando avrò più tempo libero per includere i riferimenti giusti.
ely,

9
Che ne dici di un approccio simile a reCAPTCHA ? ;)
George Duckett,

39
Perché questo è stato spostato da dsp.stackexchange.com ? Sembra che quel sito potrebbe adattarsi ancora meglio di
stackoverflow

Risposte:


672

Un approccio alternativo sarebbe quello di estrarre funzionalità (punti chiave) usando la trasformazione di caratteristiche invariante per la scala (SIFT) o Speeded Up Robust Features (SURF).

È implementato in OpenCV 2.3.1.

Puoi trovare un buon esempio di codice usando le funzionalità in Features2D + Homography per trovare un oggetto noto

Entrambi gli algoritmi sono invarianti al ridimensionamento e alla rotazione. Poiché funzionano con le funzionalità, puoi anche gestire l' occlusione (purché siano visibili abbastanza punti chiave).

Inserisci qui la descrizione dell'immagine

Fonte immagine: esempio tutorial

L'elaborazione richiede alcune centinaia di ms per SIFT, SURF è un po 'più veloce, ma non è adatto per applicazioni in tempo reale. ORB utilizza FAST, che è più debole in termini di invarianza di rotazione.

I documenti originali


6
Sono d'accordo con @stacker - SIFT è una scelta eccellente. È molto robusto contro le operazioni di scala e rotazione. È in qualche modo robusto contro la deformazione prospettica (questo può essere migliorato come suggerito dall'impilatore: un database modello con diverse viste prospettiche dell'oggetto desiderato). Il tacco di Achille nella mia esperienza sarebbe rappresentato da forti variazioni di illuminazione e calcoli molto costosi. Non conosco implementazioni Java. Sono a conoscenza di un'implementazione OpenCV e ho usato un'implementazione GPU c ++ / Windows ( SiftGPU ) adatta per prestazioni in tempo reale.

31
Una nota di avvertimento: per quanto io ami SIFT / SURF e ciò che mi hanno fatto, sono brevettati. Questo potrebbe essere un problema, a seconda di una serie di condizioni tra cui la posizione geografica AFAIK.
Agos,

12
Quindi prova ORB o FREAK di OpenCV che non hanno problemi di brevetto. ORB è molto più veloce di SIFT. ORB è un po 'scarso con variazioni di scala e di luce nella mia esperienza ma provalo tu stesso.
Rui Marques,

66
Come puoi accettarlo come una risposta ... Nessuno dei descrittori di caratteristiche è in grado di differenziare le bottiglie dalle lattine. Tutti visualizzano semplicemente descrittori di modelli locali invarianti. Sono d'accordo che SIFT, SURF, ORB, FREAK ecc. Possono aiutarti nell'abbinamento delle funzionalità ma ... Che dire delle altre parti della domanda come occlusioni, Bottle vs Can ecc. Spero che questa non sia una soluzione completa, infatti, se lo facessi GOOGLED il tuo problema probabilmente il primo risultato sarebbe solo questa risposta.
G453,

11
@ G453 hai assolutamente ragione! Probabilmente è stato affascinato dalle prestazioni di SHIFT e ha dimenticato che l'estrazione e la corrispondenza delle caratteristiche NON era IL PROBLEMA ...
sepdek,

383

Per accelerare le cose, approfitterei del fatto che non ti viene chiesto di trovare un'immagine / oggetto arbitrario, ma in particolare uno con il logo Coca-Cola. Ciò è significativo perché questo logo è molto distintivo e dovrebbe avere una firma caratteristica invariante nel dominio della frequenza, in particolare nel canale rosso di RGB. Vale a dire, il modello alternato di rosso-bianco-rosso-rosso incontrato da una linea di scansione orizzontale (formata su un logo allineato orizzontalmente) avrà un "ritmo" distintivo mentre attraversa l'asse centrale del logo. Quel ritmo "accelererà" o "rallenterà" a diverse scale e orientamenti, ma rimarrà proporzionalmente equivalente. Potresti 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".

Linea di scansione della firma

Cercare questa firma nell'immagine di destinazione è una semplice questione di scansionare l'immagine in strisce orizzontali. Cerca un'alta frequenza nel canale rosso (che indica lo spostamento da una regione rossa a una bianca) e, una volta trovata, vedi se è seguita da uno dei ritmi di frequenza identificati nella sessione di allenamento. Una volta trovata una corrispondenza, saprai immediatamente l'orientamento e la posizione della linea di scansione nel logo (se tieni traccia di quelle 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 della bottiglia, cerco la coca cola (il liquido marrone) adiacente al logo, cioè all'interno della bottiglia. O, nel caso di una bottiglia vuota, cerco un tappo che avrà sempre il stessa forma, dimensione e distanza di base dal logo e in genere saranno tutte bianche o rosse. Cerca una forma ellittica in tinta unita dove dovrebbe essere un cappuccio , rispetto al logo. Naturalmente non infallibile, ma l'obiettivo qui dovrebbe essere quello di trova 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 approssimare leggermente come potrebbe funzionare un occhio umano - o almeno come fa il mio cervello!)


24
Questo è un ottimo suggerimento, mi piace soprattutto il fatto che questo algoritmo dovrebbe essere piuttosto veloce, anche se probabilmente avrà molti falsi negativi. Uno dei miei obiettivi nascosti è utilizzare questo rilevamento in tempo reale per la robotica, quindi potrebbe essere un buon compromesso!
Charles Menguy,

42
Sì, è spesso dimenticato (in un campo caratterizzato dalla precisione) che gli algoritmi di approssimazione sono essenziali per la maggior parte delle attività di modellazione in tempo reale e nel mondo reale. (Ho basato la mia tesi su questo concetto.) Salva i tuoi algoritmi che richiedono tempo per regioni limitate (per potare i falsi positivi). E ricorda: nella robotica di solito non sei limitato a una singola immagine. Supponendo che un robot mobile, un veloce algoritmo può cercare dozzine di immagini da diverse angolazioni in meno tempo di quanto gli alg sofisticati impieghino su uno, riducendo significativamente i falsi negativi.
kmote

29
Mi piace l'idea di utilizzare ciò che equivale a uno scanner di codici a barre per il rilevamento estremamente rapido dei loghi Coca-Cola. +1!
Li-aung Yip,

8
Il problema di cercare firme in questo caso è che se giriamo la lattina dall'altra parte, cioè nascondendo la firma, l'algoritmo non riuscirà a rilevare la lattina.
karlphillip,

34
@karlphillip: se nascondi la firma, ovvero il logo, qualsiasi metodo basato sulla ricerca del logo fallirà.
Li-aung Yip,

162

Problema divertente: quando ho dato un'occhiata alla tua immagine di bottiglia, ho pensato che fosse anche una lattina. Ma, come essere umano, quello che ho fatto per dire la differenza è che poi ho notato che era anche una bottiglia ...

Quindi, per distinguere lattine e bottiglie, che ne dici di cercare prima le bottiglie? Se ne trovi uno, maschera l'etichetta prima di cercare lattine.

Non troppo difficile da implementare se stai già facendo lattine. Il vero aspetto negativo è che raddoppia i tempi di elaborazione. (Ma pensando alle applicazioni del mondo reale, finirai per voler comunque fare bottiglie ;-)


5
Sì, ci ho pensato anche io, ma non ho avuto molto tempo per farlo. Come riconosceresti una bottiglia, poiché la sua parte principale sembrerà una lattina in scala? Stavo pensando di cercare anche la spina rossa e vedere se è allineata con il centro in bottiglia, ma non sembra molto robusto.
Charles Menguy,

42
Se c'è un tappo rosso (o anello) parallelo alla "Coca cola" è molto probabilmente una bottiglia.
Lukasz Madon,

@linker Come hai allenato il tuo algoritmo per le lattine? Hai avuto esempi di lattine? Che ne dici di allenarti con esempi di bottiglie?
Siamii,

1
Il punto di forza di questo algoritmo è che hai solo bisogno di un modello su cui allenarti, quindi applica tutte le trasformazioni per abbinarlo ad altre potenziali lattine. Stavo usando una versione binarizzata e basata sul contorno di questo modello per allenarmi, quindi l'unica differenza tra lattina e bottiglia sarebbe la spina, ma temo che porterebbe più falsi positivi poiché il centro di gravità sarebbe da qualche parte sul bordo o fuori dalla bottiglia. Vale la pena provarlo, immagino. Ma questo raddoppierà il mio tempo di elaborazione e sto per piangere;)
Charles Menguy

7
Fondamentalmente questa è una direzione ragionevole. Lo direi in modo leggermente diverso: prima trovo tutti i candidati e poi per ogni candidato determinano se si tratta di una bottiglia, una lattina o qualcos'altro.
MSalters,

131

Non è difficile nemmeno 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 uguali, tranne per una regione molto piccola (vale a dire, la larghezza nella parte superiore della lattina è un po 'piccola mentre l'involucro della bottiglia è la stessa larghezza in tutto, ma un piccolo cambiamento giusto?)

La prima cosa che mi è venuta in mente è stata quella di verificare la cima rossa della bottiglia. Ma è ancora un problema, se non c'è un tappo 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 precisione il rilevamento del vetro:

Vedi il loro risultato di implementazione:

Inserisci qui la descrizione dell'immagine

Dicono che sia l'implementazione del documento "Un quadro geodetico di contorni attivi per la ricerca del vetro" di K. McHenry e J. Ponce, CVPR 2006 .

Potrebbe essere utile nel tuo caso un po ', ma il problema si ripresenta se la bottiglia è piena.

Quindi penso 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.)

Inserisci qui la descrizione dell'immagine

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

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

  1. Funziona solo se la 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.


+1 Ci ho pensato ed ero sulla mia strada per attuare questo approccio. Tuttavia, @linker dovrebbe condividere il suo set di immagini in modo da poter provare a fare ipotesi più istruite.
karlphillip,

sì .. sto troppo pensando che fosse bello se ci fossero più immagini.
Abid Rahman K

Considerando se abbiamo solo le etichette per bottiglie / lattine e nessuno degli altri fattori distintivi di tappo di bottiglia o trasparenza o lattina superiore / inferiore - La larghezza della bottiglia è diversa dalla larghezza della lattina.
Ken,

Cosa succede se una lattina viene posizionata davanti al logo per la bottiglia?
AlgoRythm,

51

Mi piacciono molto le risposte di Darren Cook e dell'impilatore a questo problema. Ero nel bel mezzo di gettare i miei pensieri in un commento su quelli, ma credo che il mio approccio sia troppo a forma di risposta per non andarmene da qui.

In breve riassunto, hai identificato un algoritmo per determinare che un logo Coca-Cola è presente in una particolare posizione nello spazio. Si sta ora cercando di stabilire, per gli orientamenti arbitrari e fattori di scala arbitrari, una euristica adatto per distinguere la Coca-Cola lattine da altri oggetti, comprensivi di: bottiglie , cartelloni pubblicitari , annunci pubblicitari , e Coca-Cola armamentario tutto associata a questo marchio iconico. Non hai indicato molti di questi casi aggiuntivi nella tua dichiarazione del problema, ma ritengo che siano vitali per il successo del tuo algoritmo.

Il segreto qui è determinare quali caratteristiche visive contiene una lattina o, attraverso lo spazio negativo, quali caratteristiche sono presenti per altri prodotti Coke che non sono presenti per lattine. A tal fine, l'attuale risposta principale delinea un approccio di base per la selezione di "can" se e solo se "bottiglia" non viene identificato, sia per la presenza di un tappo di bottiglia, liquido o altra euristica visiva simile.

Il problema è che questo si rompe. Una bottiglia potrebbe, ad esempio, essere vuota e priva della presenza di un tappo, portando a un falso positivo. Oppure, potrebbe essere una bottiglia parziale con caratteristiche aggiuntive alterate, che porta di nuovo al falso rilevamento. Inutile dire che questo non è elegante, né efficace per i nostri scopi.

A tal fine, i criteri di selezione più corretti per le lattine sembrano essere i seguenti:

  • La forma della sagoma dell'oggetto, come hai delineato nella tua domanda , è corretta? In tal caso, +1.
  • Se assumiamo la presenza di luce naturale o artificiale, rileviamo un contorno cromato sulla bottiglia che indica se questo è realizzato in alluminio? In tal caso, +1.
  • Determiniamo che le proprietà speculari dell'oggetto sono corrette, relativamente alle nostre fonti di luce ( collegamento video illustrativo sul rilevamento della fonte di luce )? In tal caso, +1.
  • Possiamo determinare qualsiasi altra proprietà sull'oggetto che lo identifica come una lattina, incluso, ma non limitato a, l'inclinazione dell'immagine topologica del logo, l'orientamento dell'oggetto, la giustapposizione dell'oggetto (ad esempio, su una superficie piana come una tabella o nel contesto di altre lattine) e la presenza di una linguetta? In tal caso, per ciascuno +1.

La tua classificazione potrebbe quindi apparire come segue:

  • Per ogni partita candidata, se viene rilevata la presenza di un logo Coca Cola, traccia un bordo grigio.
  • Per ogni partita oltre +2, disegna un bordo rosso.

Ciò evidenzia visivamente all'utente ciò che è stato rilevato, sottolineando i positivi deboli che possono, correttamente, essere rilevati come lattine rovinate.

Il rilevamento di ogni proprietà comporta una complessità temporale e spaziale molto diversa e, per ciascun approccio, un passaggio rapido attraverso http://dsp.stackexchange.com è più che ragionevole per determinare l'algoritmo più corretto ed efficiente per i tuoi scopi. Il mio intento qui è, puramente e semplicemente, enfatizzare che rilevare se qualcosa è possibile invalidando una piccola porzione dello spazio di rilevamento dei candidati non è la soluzione più solida o efficace a questo problema e, idealmente, dovresti intraprendere le azioni appropriate di conseguenza.

Ehi, congratulazioni per la pubblicazione di Hacker News! Nel complesso, questa è una domanda piuttosto formidabile degna della pubblicità che ha ricevuto. :)


2
È un approccio interessante che vale la pena provare, mi piace molto il tuo ragionamento sul problema
Charles Menguy,

Questo è un po 'quello che stavo pensando: non escludere particolari tipi di falsi positivi. Regola in più funzioni di ciò che rende una coca cola. Ma mi chiedo: cosa fai di una lattina schiacciata? Voglio dire, se calpesti una lattina di coca cola è ancora una lattina di coca cola. Ma non avrà più la stessa forma. O è quel problema AI-Complete?
Ian,

41

Guardando la forma

Prendi un assaggio a forma della porzione rossa della lattina / bottiglia. Notare come la lattina si assottigli leggermente nella parte superiore mentre l'etichetta della bottiglia è diritta. Puoi distinguere tra questi due confrontando la larghezza della porzione rossa su tutta la lunghezza.

Guardando i punti salienti

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

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


Mi piace l'idea, ma sembra che avresti bisogno di condizioni di illuminazione davvero molto buone. Nell'immagine di esempio in cui sono presenti sia la lattina che la bottiglia, ad esempio, sembra un po 'difficile distinguere.
Charles Menguy,

Nel tuo esempio, noti come la specularità per l'etichetta in plastica sia molto più diffusa rispetto ai punti molto luminosi sulla lattina? Ecco come puoi dirlo.
tskuzzy,

Vedo, che tipo di rappresentazione dello spazio colore useresti in questo caso per catturare la specularità nel tuo algoritmo? Sembra abbastanza difficile ottenere in RGB o HSV
Charles Menguy il

3
E se la fonte di luce fosse dietro la lattina? Penso che non vedresti il ​​momento clou.
Rui Marques,

37

Dai un'occhiata al tracker Predator di Zdenek Kalal . Richiede un po 'di addestramento, ma può imparare attivamente come l'oggetto tracciato guarda a diversi orientamenti e scale e lo fa in tempo reale!

Il codice sorgente è disponibile sul suo sito. È in MATLAB , ma forse esiste già un'implementazione Java eseguita da un membro della comunità. Ho implementato con successo la parte tracker di TLD in C #. Se ricordo bene, TLD utilizza Ferns come rilevatore di punti chiave. Uso invece SURF o SIFT (già suggerito da @stacker) per riacquistare l'oggetto se è stato perso dal tracker. Il feedback del tracker semplifica la creazione nel tempo di un elenco dinamico di modelli di setacciatura / navigazione che con il tempo consentono di riacquisire l'oggetto con altissima precisione.

Se sei interessato alla mia implementazione C # del tracker, non esitare a chiedere.


Grazie per il link che sembra interessante. Per quanto riguarda la formazione, qual è la dimensione del set di formazione che sarebbe ragionevole per ottenere risultati ragionevoli? Se hai un'implementazione anche in c #, sarebbe molto utile!
Charles Menguy,

Durante la ricerca di TLD, ho trovato un altro utente alla ricerca di un'implementazione in C # --- c'è qualche motivo per non pubblicare il tuo lavoro su Github? stackoverflow.com/questions/29436719/...
Spillner

2
NB: Anni dopo, il link è ora morto
J Evans,

33

Se non sei limitato a una sola fotocamera che non era in uno dei tuoi vincoli, forse puoi passare a utilizzare un sensore di portata come Xbox Kinect . Con questo è possibile eseguire la segmentazione corrispondente della profondità e del colore dell'immagine. Ciò consente una separazione più rapida degli oggetti nell'immagine. È quindi possibile utilizzare la corrispondenza ICP o tecniche simili per abbinare anche la forma della lattina piuttosto che solo il suo contorno o colore e dato che è cilindrico, questa potrebbe essere un'opzione valida per qualsiasi orientamento se si dispone di una precedente scansione 3D del bersaglio. Queste tecniche sono spesso piuttosto veloci, specialmente se usate per uno scopo così specifico che dovrebbe risolvere il tuo problema di velocità.

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


3
In realtà non l'ho spiegato nel post, ma per questo incarico mi è stato dato un set di circa 30 immagini, e ho dovuto fare un algoritmo che le corrispondesse tutte in varie situazioni come descritto. Naturalmente alcune immagini sono state tese per testare l'algoritmo alla fine. Ma mi piace l'idea dei sensori Kinect e mi piacerebbe leggere di più sull'argomento!
Charles Menguy,

Quale sarebbe approssimativamente la dimensione del set di addestramento con una rete neurale per avere risultati soddisfacenti? La cosa bella di questo metodo è che ho solo bisogno di un modello per abbinare quasi tutto.
Charles Menguy,

2
Se il tuo set di immagini è predefinito e limitato, solo risultati perfetti hardcore nel tuo prog;)
sne11ius

Sì, se mi alleno sul set di dati con cui eseguirò l'algoritmo, sicuramente otterrò risultati perfetti :) Ma ad esempio per questo compito, il programma è stato testato dall'insegnante alla fine su una serie di immagini tese . Mi piacerebbe fare qualcosa che fosse robusto e non adatto ai dati di allenamento.
Charles Menguy,

Il numero di set di allenamento varia, devi fare attenzione ad alcune cose: non allenarti troppo, probabilmente vuoi un set di test per mostrare come sta andando la tua precisione. Inoltre, il numero di set di allenamento dipenderà dal numero di livelli che utilizzerai.
Fantastico Mr Fox,

24

Rileverei rettangoli rossi: RGB -> HSV, filtro rosso -> immagine binaria, chiudi (dilata quindi erode, noto come imclosein matlab)

Quindi guarda attraverso i rettangoli dal più grande al più piccolo. I rettangoli che hanno rettangoli più piccoli in una posizione / scala nota possono entrambi essere rimossi (supponendo che le proporzioni della bottiglia siano costanti, il rettangolo più piccolo sarebbe un tappo di bottiglia).

Questo ti lascerebbe con rettangoli rossi, quindi dovrai in qualche modo rilevare i loghi per dire se sono un rettangolo rosso o una lattina di coca cola. Come l'OCR, ma con un logo noto?


2
Come questo è stato discusso su DSP nel breve periodo in cui è stato spostato, alcune bottiglie potrebbero non avere spine;) o la spina potrebbe essere parzialmente nascosta.
Charles Menguy,

22

Questa potrebbe essere un'idea molto ingenua (o potrebbe non funzionare affatto), ma le dimensioni di tutte le lattine di coca cola sono fisse. Quindi, se la stessa immagine contiene sia una lattina che una bottiglia, è possibile distinguerle in base alle dimensioni (le bottiglie saranno più grandi). Ora, a causa della profondità mancante (ovvero dalla mappatura 3D alla mappatura 2D), è possibile che una bottiglia appaia ridotta e che non ci siano differenze di dimensioni. È possibile recuperare alcune informazioni sulla profondità utilizzando l'imaging stereo e quindi ripristinare le dimensioni originali.


3
In realtà no: non c'è alcun vincolo di dimensioni o orientamento (o orientamento ma non l'ho davvero gestito), quindi puoi avere una bottiglia molto lontana sullo sfondo e una lattina in primo piano, e la lattina sarebbe molto più grande della bottiglia.
Charles Menguy,

Ho anche verificato che il rapporto larghezza-altezza è abbastanza simile per bottiglia e lattina, quindi non è un'opzione.
Charles Menguy,

Il rapporto etichetta (essendo un marchio) è lo stesso. Quindi se la bottiglia (più grande) è leggermente più lontana sull'immagine, la sua dimensione sarà esattamente la stessa di quella della lattina.
littleadv,

3
Per spiegare un po 'di più. Supponiamo che can sia a z = 0 e bottiglia a z = -100. Poiché la bottiglia è molto indietro sembrerà più piccola. Ma se so che la bottiglia è a z = -100 e la lattina a z = 0, allora posso calcolare la dimensione prevista della lattina / bottiglia se entrambi sono tradotti in z = 0. Quindi ora sono alla stessa profondità e quindi posso prendere decisioni in base alle dimensioni.
Sharad,

2
Questo è solo un commento, non una risposta, ma è molto più vicino all'essere una risposta che al commento come una risposta sopra con 120 voti.
Fattie,

22

Hmm, in realtà penso di essere su qualcosa (questa è come la domanda più interessante di sempre - quindi sarebbe un peccato non continuare a cercare di trovare la risposta "perfetta", anche se è stata trovata una accettabile) .. .

Una volta trovato il logo, i tuoi problemi sono a metà. Quindi devi solo capire le differenze tra ciò che è intorno al logo. Inoltre, vogliamo fare il minimo extra possibile. Penso che questa sia in realtà questa parte facile ...

Cosa c'è intorno al logo? Per una lattina, possiamo vedere il metallo, che nonostante gli effetti dell'illuminazione, non cambia affatto nel suo colore di base. Finché conosciamo l'angolazione dell'etichetta, possiamo dire cosa c'è direttamente sopra di esso, quindi stiamo osservando la differenza tra questi:

Qui, ciò che è sopra e sotto il logo è completamente scuro, di colore coerente. Relativamente facile da questo punto di vista.

Qui, ciò che è sopra e sotto è leggero, ma comunque coerente nel colore. È tutto argento, e il metallo tutto argento in realtà sembra piuttosto raro, così come i colori argento in generale. Inoltre, è in una sottile striscia e abbastanza vicino al rosso che è già stato identificato in modo da poterne tracciare la forma per tutta la sua lunghezza per calcolare una percentuale di quello che può essere considerato l'anello di metallo della lattina. In realtà, hai solo bisogno di una piccola parte di ciò ovunque lungo la lattina per dire che fa parte di esso, ma devi comunque trovare un equilibrio che assicuri che non sia solo una bottiglia vuota con qualcosa di metallo dietro.

E infine, quello difficile. Ma non è così complicato, una volta che passiamo solo da quello che possiamo vedere direttamente sopra (e sotto) l'involucro rosso. È trasparente, il che significa che mostrerà tutto ciò che c'è dietro. Va bene, perché le cose che stanno dietro non sono probabilmente di colore coerente come il metallo circolare d'argento della lattina. Potrebbero esserci molte cose diverse dietro, che ci direbbero che è una bottiglia vuota (o piena di liquido trasparente) o un colore coerente, che potrebbe significare che è piena di liquido o che la bottiglia è semplicemente di fronte a un colore solido. Stiamo lavorando con ciò che è più vicino alla parte superiore e inferiore e le probabilità che i colori giusti si trovino nel posto giusto sono relativamente scarse. Sappiamo che è una bottiglia, perché non ha quell'elemento visivo chiave della lattina,

(l'ultimo è stato il migliore che ho potuto trovare di una grande bottiglia vuota di coca cola - è interessante notare che il tappo E l'anello sono gialli, indicando che probabilmente il rossore del tappo non dovrebbe essere invocato)

Nella rara circostanza che dietro la bottiglia sia presente una tonalità simile di argento, anche dopo l'astrazione della plastica, o che la bottiglia sia in qualche modo riempita con la stessa tonalità di liquido d'argento, possiamo ricadere su ciò che possiamo approssimativamente stimare come il la forma dell'argento - che come ho già detto, è circolare e segue la forma della lattina. Ma anche se mi manca una certa conoscenza nell'elaborazione delle immagini, sembra lento. Meglio ancora, perché non dedurlo controllando per una volta i lati del logo per assicurarsi che non ci sia nulla dello stesso colore argento lì? Ah, ma cosa succede se c'è la stessa tonalità di argento dietro una lattina? Quindi, dobbiamo davvero prestare maggiore attenzione alle forme, guardando di nuovo in cima e in fondo alla lattina.

A seconda di quanto deve essere impeccabile tutto ciò, potrebbe essere molto lento, ma immagino che il mio concetto di base sia quello di controllare prima le cose più semplici e vicine. Passa per differenze di colore attorno alla forma già abbinata (che sembra comunque la parte più banale di questo) prima di dedicarti allo sforzo di elaborare la forma degli altri elementi. Per elencarlo, va:

  • Trova l'attrazione principale (sfondo del logo rosso, e possibilmente il logo stesso per l'orientamento, anche se nel caso in cui la lattina venga girata, devi concentrarti solo sul rosso)
  • Verifica la forma e l'orientamento, ancora una volta tramite il rossore molto caratteristico
  • Controlla i colori attorno alla forma (poiché è rapido e indolore)
  • Infine, se necessario, verificare la forma di quei colori attorno all'attrazione principale per la giusta rotondità.

Nel caso in cui non sia possibile farlo, probabilmente significa che la parte superiore e inferiore della lattina sono coperte e le uniche cose possibili che un essere umano avrebbe potuto usare per fare una distinzione affidabile tra la lattina e la bottiglia sono l'occlusione e la riflessione della lattina, che sarebbe una battaglia molto più difficile da elaborare. Tuttavia, per andare ancora oltre, è possibile seguire l'angolazione della lattina / bottiglia per verificare la presenza di altri tratti simili a quelli delle bottiglie, utilizzando le tecniche di scansione semitrasparente menzionate nelle altre risposte.

Interessanti incubi aggiuntivi potrebbero includere una lattina comodamente seduta dietro la bottiglia a una distanza tale che il metallo di essa si manifesti proprio sopra e sotto l'etichetta, il che fallirebbe ancora finché scansionerai per l'intera lunghezza del rosso etichetta - che in realtà è più un problema perché non stai rilevando una lattina dove potresti avere, al contrario di considerare che stai effettivamente rilevando una bottiglia, inclusa la lattina per caso. Il bicchiere è mezzo vuoto, in quel caso!


Come disclaimer, non ho esperienza né ho mai pensato all'elaborazione delle immagini al di fuori di questa domanda, ma è così interessante che mi ha fatto riflettere abbastanza profondamente su di esso, e dopo aver letto tutte le altre risposte, ritengo che questo possa essere il modo più semplice ed efficiente per farlo. Personalmente, sono solo felice di non dover davvero pensare a programmare questo!

MODIFICARE

cattivo disegno di una lattina in vernice MS Inoltre, guarda questo disegno che ho fatto in MS Paint ... È assolutamente orribile e abbastanza incompleto, ma basandoti solo sulla forma e sui colori, puoi indovinare quale sarà probabilmente. In sostanza, queste sono le uniche cose di cui bisogna preoccuparsi di scansionare. Quando guardi quella forma molto particolare e la combinazione di colori così vicini, cos'altro potrebbe essere? Il pezzo che non ho dipinto, lo sfondo bianco, dovrebbe essere considerato "qualcosa di incoerente". Se avesse uno sfondo trasparente, potrebbe andare su quasi tutte le altre immagini e puoi ancora vederlo.


10
La particolare tonalità di rosso è per lo più soggettiva e fortemente influenzata da considerazioni di illuminazione e bilanciamento del bianco. Potresti essere sorpreso da quanto possono cambiare. Considera, ad esempio, questa illusione a scacchiera .
Polpo,

2
Un aggiornamento al link pubblicato da @Octopus
Hat

L'illusione di una percezione non influisce su ciò che vede la tua webcam - cioè su ciò che il tuo codice ottiene - solo come un occhio umano (?) Aiuta ingannando il cervello.
barny

17

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 esempio la Coca Cola. Dovresti incorporare fino alla parte superiore della lattina come nel caso della lattina ci sia un rivestimento d'argento nella parte superiore della 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 della lattina è nascosta, ma in tal caso anche l'uomo non sarà in grado di distinguere tra i due (se è visibile solo la porzione di bottiglia / lattina di coca cola)


1
Ho avuto lo stesso pensiero, ma penso che il rivestimento d'argento sulla parte superiore della lattina cambi radicalmente a seconda dell'angolazione della lattina sulla foto. Può essere una linea retta o un cerchio. Forse potrebbe usare entrambi come riferimento?
Alexis Dufrenoy,

15

Mi piace la sfida e volevo dare una risposta, che risolve il problema, credo.

  1. Estrai le funzioni (punti chiave, descrittori come SIFT, SURF) del logo
  2. Abbina i punti con un'immagine modello del logo (usando Matcher come Brute Force)
  3. Stimare le coordinate del corpo rigido (problema PnP - SolvePnP)
  4. Stimare la posizione del cappuccio in base al corpo rigido
  5. Esegui la retroproiezione e calcola la posizione dei pixel dell'immagine (ROI) del tappo del flacone (suppongo che tu abbia i parametri intrinseci della fotocamera)
  6. Verificare con un metodo se il tappo è presente o meno. Se c'è, allora questa è la bottiglia

Il rilevamento del cappuccio è un altro problema. Può essere complicato o semplice. Se fossi in te, verificherei semplicemente l'istogramma del colore nel ROI per una semplice decisione.

Per favore, dai il feedback se sbaglio. Grazie.


13

Sono in ritardo di qualche anno per rispondere a questa domanda. Con lo stato dell'arte spinto al limite dai CNN negli ultimi 5 anni, non avrei usato OpenCV per fare questo compito ora! ( So che volevi specificamente le funzionalità OpenCv nella domanda ) Sento che gli algoritmi di rilevamento degli oggetti come Faster-RCNN, YOLO, SSD ecc. Avrebbero riscontrato questo problema con un margine significativo rispetto alle funzionalità OpenCV. Se dovessi affrontare questo problema ora (dopo 6 anni !!) utilizzerei sicuramente Faster-RCNN .


5
OP ha detto che c'erano 30 immagini ad alta risoluzione, che probabilmente non è lo scenario migliore per l'addestramento di ConvNets. Non solo sono troppo pochi (anche aumentati), la parte ad alta risoluzione distruggerebbe ConvNets.
Kostas Mouratidis,

11

Mi piace la tua domanda, indipendentemente dal fatto che sia fuori tema o meno: P

Una parte interessante; Ho appena completato un argomento nella mia laurea in cui abbiamo coperto robotica e visione artificiale. Il nostro progetto per il semestre è stato incredibilmente simile a quello che descrivi.

Abbiamo dovuto sviluppare un robot che utilizzava una Xbox Kinect per rilevare bottiglie di coca cola e lattine su qualsiasi orientamento in una varietà di condizioni di illuminazione e ambientali. La nostra soluzione prevedeva l'uso di un filtro passa banda sul canale Hue in combinazione con la trasformazione del cerchio hough. Siamo riusciti a limitare un po 'l'ambiente (potevamo scegliere dove e come posizionare il robot e il sensore Kinect), altrimenti avremmo usato le trasformazioni SIFT o SURF.

Puoi leggere il nostro approccio sul mio post sul blog sull'argomento :)


2
Progetto interessante ma si applica solo alla tua configurazione molto specifica.
Rui Marques,

10

Ci sono un sacco di descrittori di colori usati per riconoscere gli oggetti, la carta qui sotto li confronta molti. Sono particolarmente potenti se combinati con SIFT o SURF. SURF o SIFT da soli non sono molto utili in un'immagine di coca cola perché non riconoscono molti punti di interesse, sono necessarie le informazioni sul colore per aiutare. Uso un 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


10

Apprendimento profondo

Raccogli almeno alcune centinaia di immagini contenenti lattine di cola, annota la casella di delimitazione attorno a esse come classi positive, includi bottiglie di cola e altri prodotti di cola etichettandole classi negative e oggetti casuali.

A meno che non si raccolga un set di dati molto grande, eseguire il trucco dell'uso delle funzionalità di apprendimento profondo per un set di dati di piccole dimensioni. Idealmente usando una combinazione di Support Vector Machines (SVM) con reti neurali profonde.

Dopo aver inviato le immagini a un modello di apprendimento approfondito precedentemente addestrato (ad esempio GoogleNet), anziché utilizzare il livello decisionale (finale) della rete neurale per effettuare le classificazioni, utilizzare i dati dei livelli precedenti come funzionalità per addestrare il classificatore.

OpenCV e Google Net: http://docs.opencv.org/trunk/d5/de7/tutorial_dnn_googlenet.html

OpenCV e SVM: http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html


9

È necessario un programma che apprende e migliora la precisione della classificazione organicamente dall'esperienza.

Suggerirò il deep learning, con il deep learning questo diventa un problema banale.

Puoi riqualificare il modello v3 di Inception su Tensorflow:

Come riqualificare il livello finale di Inception per le nuove categorie .

In questo caso, addestrerai una rete neurale convoluzionale per classificare un oggetto come una coca-cola può o meno.


2
Hot dog o non hot dog?
YellowPillow

6

In alternativa a tutte queste belle soluzioni, puoi addestrare il tuo classificatore e rendere la tua applicazione robusta agli errori. Ad esempio, puoi utilizzare Haar Training , fornendo un buon numero di immagini positive e negative del tuo obiettivo.

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


3

Esiste un pacchetto di visione artificiale chiamato HALCON di MVTec le cui demo potrebbero darti buone idee sugli algoritmi. Ci sono molti esempi simili al tuo problema che potresti eseguire in modalità demo e quindi guardare gli operatori nel codice e vedere come implementarli dagli operatori OpenCV esistenti.

Ho usato questo pacchetto per prototipare rapidamente algoritmi complessi per problemi come questo e poi scoprire come implementarli utilizzando le funzionalità OpenCV esistenti. In particolare per il tuo caso potresti provare a implementare in OpenCV la funzionalità integrata nell'operatore find_scaled_shape_model . Alcuni operatori indicano il documento scientifico sull'implementazione dell'algoritmo che può aiutare a scoprire come fare qualcosa di simile in OpenCV. Spero che sia di aiuto...


0

Se sei interessato al fatto che sia in tempo reale, allora ciò che ti serve è aggiungere un filtro di pre-elaborazione per determinare cosa viene scansionato con le cose pesanti. Un buon filtro di pre-elaborazione veloce, molto in tempo reale, che ti permetterà di scansionare cose che hanno più probabilità di essere una lattina di coca-cola che non prima di passare a cose più incerte è qualcosa del genere: cerca nell'immagine le patch più grandi di colore che è una certa tolleranza lontano dalla sqrt(pow(red,2) + pow(blue,2) + pow(green,2))tua lattina di coca-cola. Inizia con una tolleranza cromatica molto rigorosa e scendi verso tolleranze cromatiche più delicate. Quindi, quando il robot esaurisce il tempo assegnato per elaborare il frame corrente, utilizza i flaconi attualmente trovati per i tuoi scopi. Si prega di notare che dovrete modificare i colori RGB in sqrt(pow(red,2) + pow(blue,2) + pow(green,2))per renderli giusti.

Inoltre, questo è davvero stupido, ma ti sei assicurato di attivare le -oFastottimizzazioni del compilatore quando hai compilato il tuo codice C?


0

Forse con troppi anni di ritardo, ma comunque una teoria da provare.

Il rapporto tra il rettangolo di delimitazione della regione del logo rosso e la dimensione complessiva della bottiglia / lattina è diverso. Nel caso di Can, dovrebbe essere 1: 1, mentre sarà diverso da quello della bottiglia (con o senza tappo). Ciò dovrebbe facilitare la distinzione tra i due.

Aggiornamento: la curvatura orizzontale della regione del logo sarà diversa tra Can e Bottle a causa della rispettiva differenza di dimensioni. Questo potrebbe essere particolarmente utile se il tuo robot ha bisogno di raccogliere una lattina / bottiglia e decidi di conseguenza la presa.


-1

Le prime cose che vorrei cercare sono i colori - come il ROSSO, quando si esegue il rilevamento degli occhi rossi in un'immagine - c'è una certa gamma di colori da rilevare, alcune caratteristiche al riguardo considerando l'area circostante e come la distanza dall'altro occhio se è davvero visibile nell'immagine.

1: La prima caratteristica è il colore e il rosso è molto dominante. Dopo aver rilevato il Coca Cola Red ci sono diversi elementi di interesse 1A: quanto è grande questa area rossa (è sufficiente per determinare o meno un barattolo vero - 10 pixel non è probabilmente sufficiente), 1B: contiene il colore dell'etichetta - "Coca-Cola" o onda. 1B1: c'è abbastanza per considerare un'alta probabilità che sia un'etichetta.

L'articolo 1 è una specie di scorciatoia - pre-process se nell'immagine esiste quel mozzicone di doe - vai avanti.

Quindi, in tal caso, posso utilizzare quel segmento della mia immagine e iniziare a guardare un po 'più di zoom fuori dall'area in questione un po' - fondamentalmente guardare la regione / i bordi circostanti ...

2: dato l'ID area immagine sopra riportato in 1 - verifica i punti [bordi] circostanti dell'oggetto in questione. A: Esiste quello che sembra essere un barattolo in alto o in basso - argento? B: Una bottiglia potrebbe apparire trasparente, ma potrebbe esserlo anche un tavolo di vetro - così c'è un tavolo / ripiano di vetro o un'area trasparente - se così ci sono più possibili uscite. Una bottiglia POTREBBE avere un tappo rosso, potrebbe non esserlo, ma dovrebbe avere la forma della vite del tappo della bottiglia / filo o un tappo. C: Anche se questo fallisce A e B, può comunque essere un barattolo - parziale .. Questo è più complesso quando è parziale perché un flacone parziale / un barattolo parziale potrebbe avere lo stesso aspetto, quindi un po 'più di elaborazione della misurazione del bordo della regione rossa a bordo .. la bottiglia piccola potrebbe avere dimensioni simili ..

3: Dopo l'analisi sopra che è quando guarderei le lettere e il logo dell'onda - perché posso orientare la mia ricerca di alcune lettere nelle parole Poiché potresti non avere tutto il testo a causa del non avere tutto il possibile, l'onda si allineerebbe in determinati punti al testo (per quanto riguarda la distanza) in modo da poter cercare quella probabilità e sapere quali lettere dovrebbero esistere in quel punto dell'onda alla distanza x.


-9

Questo è un vecchio progetto a cui ho lavorato. Le immagini MAP sono molto facili da usare con JavaScript. Ti offro l'oggetto, lo leggi e sai come usarlo. Non abbiamo bisogno di JQuery e di altri sistemi per usare le immagini MAP.

    //Copyright Cherif yahiaoui, by ELEBAN.FR

//variables de flottement.
var myInstOne = null;
var globalize = null;

var eleban_preload_images = function (name, imgs, url){
try{
    var oThis = this;
    this.images = new Array();
    this.imageshover = new Array();
    this.imagesNames = new Array(imgs.split(";"));


        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i] = new Image();
            this.imageshover[i] = new Image();
        }

    this.url = url;

    this.GetAbsoluteurl = function () {

    var img = new Image(); img.src = url;
    url = img.src; img = null; 
        this.url = url; 

    };

    this.Preload = function () {

        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i].src = this.url+("btn-"+this.imagesNames[0][i]+".png");
            this.imageshover[i].src = this.url+("btn-"+this.imagesNames[0][i]+"-hover.png");
        }

    };
    this.GetAbsoluteurl();
    this.Preload();
}
finally {return;}
}

var g_preloaderhover = new eleban_preload_images("loaderhover","menu;malette;reservation;cabine;facebook;map;amis","./images/");


//variable arret flottement
var g_stopflo = false;

var myObjfloater = function(name, idname, itop, differ ) {
var oThis = this; // création d'une référence vers l'objet courant
this.name = name;
this.id =idname;
this.xstep= 0.3;
this.itime = 30;
this.obj = null;
this.y = itop;
this.yadd = 0;
this.up = true;
this.pause = false;
this.differ = differ;
this.coordsimage = null;
this.objimg = null;
this.initimages = false;
this.compteur = 0;
this.over = false;
this.timeoutstop = null;
try{
this.initimage = function(){
var img = this.obj.getElementsByTagName('img')[0];
this.coordsimage = new Array(img.width, img.height);
this.objimg = img;
this.initimages = true;
};


this.myMethod = function() {
if(!g_stopflo){
    if(this.differ != 0){ 
this.differ=this.differ-0.1; 
}else{

if(this.obj){
if(this.over == false){
    this.yadd=this.yadd+0.1; this.itime = this.itime + 10;
this.obj.style.visibility = "hidden";
this.y = ((this.up)? this.y - this.yadd : this.y + this.yadd);
this.obj.style.marginTop = this.y +"%" ;
this.obj.style.visibility = "visible";

if (this.yadd > this.xstep){ 
    this.up = (this.up)? false : true;
    this.yadd = -0.1; this.itime=180;
}
}
}else{
    if (document){
        if(document.getElementById) {
         this.obj = document.getElementById(this.id); 
        //this.y = this.obj.offsetTop;
        }else{
        if(document.getElementByTagName) { this.obj = document.getElementByTagName(this.id); this.y = this.obj.offsetTop;}
        }

    }
}
}
this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}    
};

this.callDelayed = function() {
    // utilisation de la référence vers l'objet
if(!g_stopflo){
    this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}
};
}
finally {return;}
};

// special creation des zones AREA
function eleban_createallarea(){
try{
var measur = new Array("w", "h");
measur["w"] = new Array(330,570,185,300,115,390,225);
measur["h"] = new Array(460,570,295,450,100,190,115);
var ititle = new Array("Voir les menus  et nos suggestions","Repas &agrave; emporter","R&eacute;servation d&rsquo;une table","Nous contacter","Nous rejoindre sur FaceBook","Calculer votre trajet","liste des amis");
var ihref = new Array("menus.html","emporter.html","reservation.html","contact.html","likebox.html","google.html","amis.html");
var b_map = new Array(0,1,2,3,4,5,6);
b_map[0] = "71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38";
b_map[1] = "66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92";
b_map[2] = "19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90";
b_map[3] = "60,0,216,1,226,20,225,403,168,421,42,410,45,10";
b_map[4] = "31,7,72,10,82,18,88,45,88,71,76,81,29,80,17,68,16,18";
b_map[5] = "91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94";
b_map[6] = "6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65";

if (document.getElementById){
for (var i=0; i<b_map.length;i++){
var obj = document.getElementById("pc_menu"+i);
    if(obj){
    var ct = '<img class=\"pc_menu\" src=\"'+g_preloaderhover.images[i].src+'\" alt=\"\" width=\"'+measur["w"][i]+'\" height=\"'+measur["h"][i]+'\" usemap=\"#MAP_INDEX'+i+'\" \/>';
    ct+='<map name=\"MAP_INDEX'+i+'\">';
    ct+='<area shape=\"poly\" coords=\"'+b_map[i]+'\" title=\"'+ititle[i]+'\" href=\"'+ihref[i]+'\" \/>';
    ct+='<\/map>';
    obj.innerHTML = ct;
    }
}
}
}
finally {return;}
}

//preload, creation et gestion de tous les evenements


var image_resizer = function(g_layer){


    b_org_elm = new Array("w",  "h");
    b_org_elm["w"] = new Array(330,570,185,300,115,390,225);
    b_org_elm["h"] = new Array(460,570,295,450,100,190,115);

    b_map = new Array(0,1,2,3,4,5,6);
    b_map[0] = new Array(71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38);
    b_map[1] = new Array(66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92);
    b_map[2] = new Array(19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90);
    b_map[3] = new Array(60,0,216,1,226,20,225,403,168,421,42,410,45,10);
    b_map[4] = new Array(31,6,70,10,78,18,84,23,88,44,88,70,78,80,75,81,33,82,23,76,18,69,16,22,21,13);
    b_map[5] = new Array(91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94);
    b_map[6] = new Array(6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65);


    b_layer = g_layer;

//gere mouseover
    this.mouseover = function(e){
        if (!e) var e = window.event;
        var tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                var divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.imageshover[ii].src;
                                }
                        }
                    }
                }
            }
    };

//gere mouseout
    this.mouseout = function(e){
        if (!e) var e = window.event;
        tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.images[ii].src;
                                }
                        }
                    }
                }
            }
    };

//ajout evenements entree sortie à la page web lors du chargement de la page
    this.init = function () {

        for(var i=0; i<b_org_elm["w"].length;i++){
            w = document.getElementById("pc_menu"+i).offsetWidth;
            h = document.getElementById("pc_menu"+i).offsetHeight;

            xa = w/parseFloat(b_org_elm["w"][i]);
            ya = h/parseFloat(b_org_elm["h"][i]);

            area = document.getElementById("pc_menu"+i).getElementsByTagName('area')[0];

            b_map2 = area.coords.split(",");
            yswitch = true;
                for(m=0; m<b_map2.length;m++){
                b_map2[m] = Math.round(parseFloat(b_map[i][m]) * ((yswitch)? xa: ya));
                yswitch = (yswitch)? false :  true;
                }
            area.coords = b_map2.join(',');
        }
    }; 


    this.resize = function () {
    clearTimeout(myInstOne.timeoutstop);
    g_stopflo=true;

    globalize.init();
    g_stopflo=false;
    myInstOne.obj = null;
    myInstOne.callDelayed();
    };


    nar = document.getElementsByTagName('area').length;

        for(var i=0; i<nar;i++){
            var elem = document.getElementsByTagName('area')[i];
            if (elem.addEventListener){
                    elem.addEventListener("onmouseover",this.mouseover,true);
                elem.addEventListener("onmouseout",this.mouseout,true);
            }else if (elem.attachEvent) {
                    elem.attachEvent("onmouseover", this.mouseover);
                    elem.attachEvent("onmouseout", this.mouseout);
            }else{
                    elem["onmouseover"] = this.mouseover;
                    elem["onmouseout"] = this.mouseout;
            }
        }

            window.onresize = this.resize;
        window.onmouseover = this.mouseover;
        window.onmouseout = this.mouseout;
}


//permet de temporiser et éviter les erreurs de chargement des objets
function temporise_Init(Lastdiv){
if(document.getElementById){
    if(document.getElementById(Lastdiv)){

    eleban_createallarea();

    myInstOne = new myObjfloater('b_menumap11', 'pc_menu1', 1, 0);

    globalize = new image_resizer(document.getElementById('pc_redim'));
    globalize.init();
        globalize.resize();



    }else{
    setTimeout(temporise_Init(Lastdiv), 30);
    }
}
}


window.onload = function () {
temporise_Init("pc_bandeau");
}

3
cosa fa questo?
user8408080,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.