Corrispondenza modello invariante di scala e rotazione


12

Sto cercando un metodo per la corrispondenza del modello invariante di scala e rotazione. Ne ho già provato alcuni, ma non hanno funzionato così bene per i miei esempi o sono stati eseguiti per sempre. Il rilevamento delle funzioni SIFT e SURF non è riuscito completamente. Ho anche cercato di implementare una funzione di abbinamento dei modelli Log-Polar, ma non ho mai finito (non sapevo esattamente come).

In questi articoli (il primo è in tedesco)

http://cvpr.uni-muenster.de/teaching/ss08/seminarSS08/downloads/Wentker-Vortrag.pdf

http://www.jprr.org/index.php/jprr/article/viewFile/355/148

Ho letto di quel metodo. La mappatura delle coordinate polari ha funzionato, ma non so se sia giusto. Le immagini sembrano così.

source_log_polar.png http://www.shareimages.com/images/pics/0/0/3/62394-pZSfl5WenZysnpyVnKg-source_log_polar.png

template_log_polar.png

E dopo aver abbinato queste 2 immagini con la funzione Matching Template di OpenCV ho ottenuto quel risultato

match_log_polar.png

Ora non so come andare avanti.

I miei modelli sono sempre semplici simboli nella costruzione dei progetti e dei progetti stessi. I simboli possono differire per dimensioni e orientamento.

Ad esempio il mio semplice progetto:

inserisci qui la descrizione dell'immagine

E il mio modello

inserisci qui la descrizione dell'immagine

In questo esempio c'è solo un modello, ma nei progetti dovrebbe trovare tutte le occorrenze, anche quelle con dimensioni e / o orientamenti.

Qualcuno ha un approccio su come ho potuto risolvere questo?

Modificare:

Un'aggiunta all'approccio di Andrey. L'algoritmo di acquisizione della distanza per un profilo radiale. (Usando EmguCV)

private float[] getRadialProfile( Image<Gray, byte> image, Point center, int resolution )
 {

 var roi = image.ROI;

 if ( !roi.Contains( center ) )
  {
   return null;
  }

 var steps = resolution;
 var degreeSteps = 360 / (double)resolution;
 var data = image.Data;
 var peak = 0.0f;
 var bottom = double.MaxValue;
 var bottomIndex = 0;
 var width = roi.Width;
 var height = roi.Height;
 var minX = roi.X;
 var minY = roi.Y;

 float[] distances = new float[resolution];
 for ( var i = 0; i < steps; i++ )
  {
   var degree = i * degreeSteps;
   var radial = degree * Math.PI / 180.0;
   var dy = Math.Sin( radial );
   var dx = Math.Cos( radial );

   var x = (double)center.X;
   var y = (double)center.Y;

   while ( true )
    {
    x += dx;
    y += dy;
    if ( x >= minX + width || y >= minY + height || x <= minX || y <= minY )
     {
      x = -1;
      y = -1;
      break;
     }
    var pixel = data[(int)y, (int)x, 0];
    if ( pixel == 0 )
     {
      break;
     }
    }

    float distance = 0.0f;
    if ( x != -1 && y != -1 )
    {
      distance = (float)Math.Sqrt( Math.Pow( (center.X - x), 2 ) + Math.Pow( (center.Y - y), 2 ) );
    }

    distances[i] = distance;
    if ( distance > peak )
    {
      peak = distance;
    }
    if ( distance < bottom )
    {
      bottom = distance;
      bottomIndex = i;
    }
   }

    // Scale invariance. Divide by peak
   for ( var i = 0; i < distances.Length; i++ )
   {
     distances[i] /= peak;
   }

    // rotation invariance, shift to lowest value
   for ( var i = 0; i < bottomIndex; i++ )
   {
     distances.ShiftLeft(); // Just rotates the array nothing special
   }

   return distances;
}

benvenuti a dsp.SE. Cercheremo di aiutarti, ma fornire informazioni più precise sarebbe bello. Cosa intendi con SIFT e SURF "totalmente fallito"? Cosa hanno rilevato / abbinato? Inoltre, personalmente non conosco Log-Polar Template Matching, ma, se hai provato, dov'era esattamente il problema?
penelope,

I rilevamenti delle funzioni SIFT e SURF non hanno trovato alcuna caratteristica nell'immagine modello. Sembra che il modello abbia troppe meno informazioni (solo quel piccolo arco e una linea). Per la corrispondenza Log-Polar ho trovato un documento in cui è descritto, ma non l'esatta matematica dietro di esso. Lo cercherò e lo aggiungerò.
Arndt Bieberstein il


Ehi, non molte persone qui capiscono il tedesco, penso: D Ma, per tutto il resto: puoi modificare il tuo post per aggiungere qualsiasi nuova informazione nel posto giusto, anziché nei commenti. E, inoltre, non hai ancora detto con cosa esattamente hai avuto problemi.
penelope,

3
L'autore di "Articolo tedesco" ha pubblicato un articolo in inglese - www-cs.engr.ccny.cuny.edu/~wolberg/pub/icip00.pdf (grazie a google)
SergV

Risposte:


6

Penso che tu possa risolvere il tuo problema in un modo molto più semplice. Considerando che hai a che fare con i progetti, non dovresti preoccuparti della connettività perimetrale, del rumore e di molte altre cose per le quali SIFT e SURF sono stati progettati per adattarsi. Il modello è una forma vuota con forme di bordo specifiche.

Pertanto, la mia raccomandazione è:

  • Cammina intorno al perimetro e trova un profilo delle distanze dei bordi attorno al centro del modello. Questo è il profilo radiale del modello. Dividi per la distanza maggiore, per essere invariante in scala. Ruota il vettore in modo che la distanza minima sia la prima, per essere invariante per rotazione. (Se il modello non ha una distanza dominante, è possibile modificare il passaggio 2 in seguito)

inserisci qui la descrizione dell'immagine

  • Trova i blob nell'immagine. Calcola il profilo radiale descritto nella parte (1) e confronta i due vettori per correlazione normalizzata. Se il modello non ha una distanza dominante, la correlazione diventa correlazione incrociata normalizzata e selezionando il massimo). Coloro che superano una certa soglia sono considerati partite.

Ecco un codice Matlab con cui iniziare: ho scritto la parte che trova il profilo della distanza per un BLOB specifico e l'ho calcolata per il modello:

function Doors
    im = imread('http://i.stack.imgur.com/Tf8EV.png');
    im = im(:,:,1);
    template = imread('http://i.stack.imgur.com/PlP4i.png');
    template = template(:,:,1);

    blobs = regionprops(template>0,'Area','Image');
    largestBlob = GetLargestBlob(blobs);
    [prof,edgeImage] = GetBlobRadialProfile(largestBlob);

    figure;
    subplot(1,2,1);plot(prof); title('Radial profile')
    subplot(1,2,2);imshow(edgeImage); title('Template');

end

function [prof,edgeImage] = GetBlobRadialProfile(blob)
    paddedImage = padarray( blob.Image,[8 8]);
    erodedImage = imerode(paddedImage,strel('disk',1));
    edgeImage = xor(erodedImage,paddedImage);

    c = regionprops(paddedImage,'Centroid');
    cx  = c.Centroid(1);
    cy  = c.Centroid(2);

    [y,x] = find(edgeImage);
    rad = (x(:)-cx).^2 + (y(:)-cy).^2;
    [~,minIndex] = min(rad);
    contour = bwtraceboundary(edgeImage, [y(minIndex), x(minIndex)],'N');
    prof = (contour(:,2)-cx).^2 + (contour(:,1)-cy).^2;
    prof = prof./max(prof);
end

function largestBlob = GetLargestBlob(blobs)    
    area = [blobs.Area];
    [~,index] = max(area);
    largestBlob = blobs(index);
end

Immagino che non funzioni con forme non chiuse? O posso semplicemente saltare questi "buchi" nella forma.
Arndt Bieberstein,

@ArndtBieberstein, Sì, funziona solo per forme chiuse. Immagino che ci dovrebbe essere un metodo per estenderlo.
Andrey Rubshtein,

Poiché OpenCV non contiene la funzione bwtraceboundary, ho scritto il mio e ho semplicemente "saltato" i buchi e riempito di zeri. Ecco un piccolo esempio di come appaiono ora i risultati. 5 grafici per ogni modello. I punti rossi sono i punti di partenza. Trama del campione
Arndt Bieberstein,

@ArndtBieberstein, molto gentile! Forse potresti condividere i risultati con noi una volta che hai finito.
Andrey Rubshtein,

Certo, il codice non è così bello o performante, ma funziona. Lo allego sotto la mia domanda. È scritto in C # (sto usando EmguCV)
Arndt Bieberstein il

3

Ecco l'idea di base di ciò che so possa essere fatto, basato su un discorso del professor Anurag Mittal dell'IIT Madras.

L'idea è di rilevare oggetti basati sulla forma, ma ovviamente può essere estesa anche altrove.

  1. Calcola i bordi utilizzando il rilevatore di bordi Berkeley.
  2. Collegare i bordi ottenuti. "Rilevamento dei confini degli oggetti globali".
  3. Abbinamento della forma usando la distanza di smusso o la distanza di Houstoff.

Il suo documento sullo stesso è disponibile su: Rilevazione di oggetti deformabili basata su contorni a più stadi.

D'altra parte, penso che SIFT dovrebbe funzionare come gli algoritmi di rilevamento degli angoli funzionerebbero sulla funzione modello che hai laggiù.

Nota: SIFT non è completamente invariante per rotazione. Non è in grado di far fronte a rotazioni> 60 gradi circa. Quindi formare più template è una buona idea.

Come nei Transfrom di Fourier-Mellin basati su log-polari: causano la perdita di informazioni a causa di come avviene il campionamento per le trasformazioni.


Questo metodo sembra davvero promettente! Non riesco ad aprire il tuo link, ma ho cercato su Google il tuo approccio. Non sapevo che SIFT che SIFT non fosse completamente ivariant a rotazione! Ottima risposta! +1
Arndt Bieberstein il

1
Non ho trovato quasi nulla su Chamfer Distance e su come funziona, per coloro che sono anche alla ricerca di questo provare questo link.
Arndt Bieberstein,

@Naresh SIFT non è invariante alla rotazione per grandi rotazioni fuori dal piano. Non sullo stesso piano.
a-Jays

1

Non ci ho pensato molto, ma sono abbastanza sicuro che si possa avere una soluzione robusta senza troppi problemi usando i classici descrittori di Fourier (FD). Penso che il tuo problema potrebbe essere un ottimo candidato per questo. Non pensare di dover fare il rilevamento dei bordi in b / c hai disegni a tratteggio neri. Avvia la scansione raster fino a quando non raggiungi i pixel, quindi procedi come segue:

Tratta semplicemente i perimetri della tua stanza come se fossero un segnale 1D, dove l'ampiezza del segnale è la normale distanza dal centroide dell'oggetto, campionata a una velocità costante. Quindi, fai un semplice modello FD per la porta. Quindi, scansiona i parametri di ogni stanza con una sorta di filtro convesso in cerca di un fronte di salita, un picco e una caduta, che imposta una finestra di avvio / arresto del "segnale" da catturare. Esegui un algo FFT o FD simile su quel "segnale" acquisito e confrontalo con il modello FD. Forse il passaggio di confronto del modello può essere una semplice correlazione con una soglia per attivare una corrispondenza. Dal momento che solo le tue porte hanno bordi arrotondati che dovrebbero essere un problema di abbinamento FD abbastanza semplice.

Pensalo come se usassi FD per recuperare immagini o musica da un database. Ci sono un sacco di libri bianchi su questo.

Questo è un buon tutorial sull'uso di FD per approssimare le forme: dubito che ne avrai bisogno, ma puoi anche prima trasformare le tue immagini in un quadro di coordinate polari per gestire le rotazioni, come proposto in questo documento: Recupero di immagini basato su forme usando descrittore generico di Fourier

vedi come FD parametrizza il rilevamento del perimetro della mela? Stessa idea della tua porta.

A proposito, sono abbastanza sicuro che mappare l'intero schema a coordinate polari non aiuterà l'invarianza rotazionale - dovresti farlo sul centroide di ogni porta, che è esattamente il tuo problema con cui cominciare. Questo è il motivo per cui penso che tu voglia catturare solo i candidati delle porte e magari mapparli su coordinate polari per abbinarli al modello di porta FD, come fatto in quel documento collegato sopra.

fammi sapere come va se provi questo approccio.


0

Forse troverai questo codice Matlab che ho scritto utile: Fractal Mosaics

Implementa il documento "Robust Image Registration Using Log-Polar Transform" ( pdf ) in un'applicazione artistica che ha richiesto una maggiore robustezza rispetto ai metodi tradizionali che ho trovato.

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.