2011-01-21 16 views
24

In che modo OpenCV gestisce la trasparenza nell'immagine durante la corrispondenza dei modelli?Corrispondenza modello OpenCV e trasparenza

Il problema è che l'immagine modello deve avere parti trasparenti, perché nell'immagine originale potrebbe esserci qualcosa in quei luoghi.

Ho provato tutti i metodi e nessuno di questi ha prodotto risultati positivi (ad esempio, la posizione del modello nell'immagine originale non è stata rilevata correttamente).

Modifica: OK, vedo che è necessario fornire esempi.

Original image

Template image

Come si può vedere, è quasi impossibile per abbinare come modello per l'immagine del genere. Il "background" in giro per l'oggetto potrebbe avere qualsiasi colore (come questo, o bianco, marrone ...)

Sobel on grayscaled image & template + cvConvertScaleAbs

Additional original image

Edit 2: soluzione di Misha funziona anche con un po 'di ostacoli intorno (la "trasparenza" funziona). Esempio:

Template match sucessful

Modifica 3 - più occorrenze:

che ho fatto una soluzione rapida e sporca di trovare più occorrenze di un modello, tuttavia quando modello non viene trovata ottengo " lotto "di falsi positivi. Principalmente a causa della mia realizzazione:

  • iterare oltre i dati di immagine
  • se (imageData [y, x, 0]> = maxValue * 0.95f) allora conta [x, y] come un fiammifero (maxValue è da cvMinMaxLoc)

E works per le immagini, quando c'è almeno un risultato positivo, tuttavia risultati in situazione terribile per immagini, su cui isn't such template.

+0

Inserire una soglia sul valore massimo.Se è inferiore alla soglia, l'immagine non contiene il modello. Dovrai determinare empiricamente la misura della soglia. – misha

+4

Le immagini non sono state trovate. = ( –

+0

@anatolytechtonik Scusa, non li ho più (sono passati 5 anni) – mnn

risposta

15

Non sembra che OpenCV gestisca l'alpha nel modo desiderato.

Sono disponibili due opzioni:

  1. Scrivi la tua metodo di correlazione incrociata che utilizzerà il canale alfa
  2. trasformare la vostra foto in modo che il canale alfa diventa irrilevante

Dal momento che la prima opzione è semplice, esplorerò la seconda opzione qui. Ho intenzione di riutilizzare il codice di esempio fornito a a similar question in precedenza. Se si applica la correlazione incrociata direttamente alle immagini, lo sfondo interferisce con la corrispondenza del modello (in particolare, le parti dello sfondo chiare). Se giochi con i canali di colore, troverai che la corrispondenza nel canale blu dà il risultato corretto. Questo dipende dal contenuto dell'immagine e non è un modo coerente per risolvere il problema.

Un'altra opzione consiste nell'effettuare il rilevamento dei bordi (ad esempio Sobel) sull'immagine e nel modello e quindi eseguire una correlazione incrociata. Ecco le immagini rilevate ai bordi (ho usato il rilevatore di bordi Sobel sul canale Luma in GIMP, e poi un certo allungamento dell'intensità).

map

building

Come si può vedere, il canale alfa qui è diventato irrilevante, come la maggior parte del terreno è diventato intensità zero e non contribuirà al calcolo correlazione incrociata. Così ora correlazione incrociata può essere applicato direttamente, dando il risultato desiderato:

[email protected]:~/Desktop/stackoverflow$ python cross-correlation.py map-blue.png building-maskz-blue.png 
(163, 244) 

Infine, ecco another related question.

PS. Che gioco è questo?

+0

Grazie, ma non ho ottenuto gli stessi risultati usando Sobel su immagini e template grigi (vedi domanda). L'immagine proviene da un vecchio gioco DOS - Earth 2140. – mnn

+0

Il motivo per cui le immagini non funzionavano è perché le aree dove non ci sono bordi sono ** non nere ** (sono 127 grigio neutro). Confrontali con le mie immagini. È necessario che le aree senza bordi siano ** zero ** in modo che non interferiscano con il calcolo della correlazione incrociata. – misha

+0

OK, ho usato cvConvertAbsScale per ottenere aree senza margini a zero. (vedi domanda) Tuttavia, il mio Sobel non è uguale al tuo (specialmente il modello). Potrebbe essere il fatto che io abbia usato OpenCV e tu abbia usato GIMP per Sobel? – mnn

0

Penso che stai provando a fare ciò che in OpenCV è chiamato modello che corrisponde a una maschera. Penso che potresti provare a impostare una ROI (regione di interesse) sul modello. This SO question shows how to do it. (nota che in quella domanda la ROI è impostata sull'immagine di destinazione, non il modello, ma la procedura è la stessa).

+0

Interessante, ma in realtà non aiuta, perché non riesco a restringere la ricerca fino a tale regione (l'immagine del modello potrebbe trovarsi in qualsiasi punto dell'immagine originale). – mnn

+0

Giusto. Ma nel modello stesso ci sono pixel che sono trasparenti (cioè che non dovrebbero essere nella ROI del modello) e pixel che non sono trasparenti (cioè che dovrebbero essere nel ROI del modello). La cosa peggiore che può accadere (come dice @Utkarsh Shinha è che devi scrivere la tua funzione di corrispondenza del modello per ignorare i pixel non nel ROI) – carlosdc

+0

Guarda le immagini di esempio.La regione trasparente non è un rettangolo in alcun modo e ROI è un rettangolo. – mnn

0

Non sono sicuro, ma il canale di trasparenza viene trattato come qualsiasi altro canale. Se un pixel in un modello è "trasparente", dovrebbe essere "trasparente" anche sull'immagine principale. Sto solo indovinando qui.

+0

E questo è il problema. Ho bisogno di template che corrisponda a _ignore_ pixels con transpa renza nell'immagine modello. Altrimenti non sarò mai in grado di trovare il modello nell'immagine originale, perché nell'immagine originale potrebbe esserci qualcosa intorno all'oggetto che sto cercando. – mnn

+0

Elimina il canale di trasparenza in entrambi. Potrebbe funzionare. O potresti scrivere la tua funzione di corrispondenza dei modelli. La documentazione di OpenCV elenca le formule utilizzate per i vari metodi. Puoi modificarli in modo da "rispettare" la quantità di trasparenza su un pixel. –

+0

Utkarash, hai ragione: stai solo indovinando. Ma il mondo reale è molto più complicato di quanto tu possa immaginare. Quando scrivi la tua funzione di confronto confrontando l'immagine con il modello pixel per pixel usando le formule indicate, questo sarà inaccettabile lento (fino a un minuto) anche in C++ ottimizzato per la velocità. La ragione per cui OpenCV è così estremamente veloce è che usa DFT (trasformata di Fourier) in matchTemplate(). Ma il codice è estremamente complicato (e privo di commenti) che solo un matematico lo capirà. Quindi dimentica di scrivere la tua propria funzione matchTemplate()! – Elmue

1

L'opzione SQDIFF/SQDIFF_N sarebbe una soluzione se si tentasse di sostituire il canale alfa con il colore RGB nero. Almeno questa era la mia soluzione allo stesso problema. Dal mio risultato è ovvio che questo metodo è sensibile a valori di pixel più luminosi, e ne ho approfittato.

-1

Mi sono imbattuto nello stesso problema e ho pensato a una soluzione. Assumendo che referenceImageMask e templateMask abbiano 1s nei buoni pixel e 0 in quelli cattivi. E quel referenceImage e templateImage sono già stati mascherati e hanno lo 0 anche nei pixel difettosi.

Quindi, il primo risultato della corrispondenza del modello darà la correlazione incrociata non normalizzata tra le immagini. Tuttavia, un mucchio di pixel era zero.

La seconda corrispondenza del modello fornirà per ogni offset possibile il numero di pixel che erano contemporaneamente diversi da zero (non mascherato) in entrambe le immagini.

Quindi, la normalizzazione della correlazione per quel numero dovrebbe fornire il valore desiderato (e io). Il prodotto medio per i pixel che non sono mascherati in entrambe le immagini.

Image<Gray, float> imCorr = referenceImage.MatchTemplate(templateImage,  Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR); 
Image<Gray, float> imCorrMask = referenceImageMask.MatchTemplate(templateMask, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR); 
_imCorr = _imCorr.Mul(_imCorrMask.Pow(-1)); 

AGGIORNAMENTO: in realtà, questa soluzione non funziona. Poiché l'implementazione della correlazione incrociata in opencv utilizza la DFT ci saranno problemi numerici e non è possibile utilizzare la seconda crosscorrelation per correggere la prima.

+0

Grazie per l'informazione. Ma non ci sto più lavorando. Spero che questo sia utile per le altre persone. – mnn

9

Ho una soluzione un po 'più cerebrale a questo problema che sembra funzionare abbastanza bene: Sostituire il canale alfa dell'immagine del modello con il rumore, che rende più o meno statisticamente insignificanti le regioni trasparenti durante il processo di abbinamento.

Ad esempio, il mio caso d'uso riguardava la ricerca di caratteri emoji in catture di schermo da iOS. Lo sfondo della tastiera iOS cambia i colori in base al contesto, il che rende problematico il processo di corrispondenza se si esegue il commit su un particolare colore di sfondo nell'immagine modello.

Ecco dell'immagine grezza modello su alpha:
raw template image on alpha

Ecco il modello trasformato con il rumore compilando per l'alfa canale:
enter image description here

mandai l'immagine modello elaborati attraverso il Template Matching sample code prevista la documentazione di OpenCV. Su uno sfondo scuro o chiaro, la partita viene trovata con ragionevole sicurezza.

Ricerca su sfondi scuri:

matched on dark

ricerca su fondi chiari:

matched on light

In confronto, lasciando il canale alfa del modello trasparente - o di impegnarsi in uno sfondo scuro o chiaro - non ha restituito corrispondenze accettabili.

+1

La soluzione è una soluzione che funziona male. Mentre normalmente matchTemplate() restituisce certezze del 99% o anche del 100% se le immagini sono identiche, la soluzione con le immagini campione restituisce una certezza del 23% per l'immagine corrispondente. La prossima immagine non corrispondente (una delle faccine) è all'11%. Questa è una pessima distanza tra immagini corrispondenti (23%) e non corrispondenti (11%). E una faccina è COMPLETAMENTE un'altra cosa rispetto alla tua immagine modello. Quindi questa soluzione alternativa dipende fortemente dalla soglia che si utilizza per distinguere tra corrispondenza e non corrispondenza.La soluzione fornisce risultati molto deboli – Elmue

+2

Quindi una soluzione migliore sarebbe la seguente: Utilizzare il metodo (modello notificato) in una prima fase per trovare le possibili posizioni delle corrispondenze con matchTemplate() e quindi in una seconda fase mascherare le parti trasparenti in nero in entrambi: il modello e l'immagine principale nelle posizioni trovate nel primo passaggio per ottenere le vere certezze (fino al 100%). – Elmue

+1

Si otterrebbero risultati di certezza migliore se si rimuovesse il rumore inutile attorno all'emoji. Hai sopra e sotto 16 pixel di rumore e 5 pixel su ciascun lato. Dopo averli rimossi, la certezza aumenta dal 23% al 57%. Più rumore e più cattivo è il riconoscimento! – Elmue

6

OpenCV 3.0 offre supporto nativo per la corrispondenza dei modelli con i modelli mascherati. Fare riferimento alla new documentation:

Parametri:

immagine ...

templ ...

risultato ...

metodo ...

maschera Maschera del modello cercato. Deve avere lo stesso tipo di dati e dimensioni con templ. Non è impostato di default.

[Leggero Digression]

noti che template matching con immagini di riferimento mascherate (l'immagine) non è possibile però. E questo ha senso, dato che OpenCV utilizza la corrispondenza dei modelli basati su FFT.

Pertanto, se è necessario eseguire la corrispondenza dei modelli solo in regioni specifiche delle immagini di riferimento, sarà necessario implementare il proprio metodo o mascherare l'output di cv :: matchTemplate.

L'implementazione da zero dovrebbe compensare i casi in cui si desidera cercare il modello solo in regioni molto specifiche (ad es. Angoli di harris).

+0

Grazie! Ogni altra risposta è solo matematica quando si cerca il metodo corretto per usarlo. – Zoey

Problemi correlati