6

Voglio identificare i mattoncini lego per la costruzione di un lego smistatore (io uso C++ con opencv). Ciò significa che devo distinguere tra oggetti che sembrano molto simili.distingue gli oggetti con opencv

I mattoni arrivano alla mia fotocamera individualmente su un trasportatore piatto. Ma potrebbero trovarsi in ogni modo possibile: a testa in giù, di lato o "normale".

Il mio approccio è quello di insegnare alla macchina di smistamento i mattoni fissandoli con la fotocamera in molte posizioni e rotazioni diverse. Le caratteristiche di ciascuna vista sono calcolate dal surf-algorythm.

void calculateFeatures(const cv::Mat& image, 
     std::vector<cv::KeyPoint>& keypoints, 
     cv::Mat& descriptors) 
{ 
    // detector == cv::SurfFeatureDetector(10) 
    detector->detect(image,keypoints); 
    // extractor == cv::SurfDescriptorExtractor() 
    extractor->compute(image,keypoints,descriptors); 
} 

Se c'è un mattone sconosciuta (il mattone che voglio ordinare) le sue caratteristiche anche ottenere calcolati e combinati con quelli noti. Per informazioni sulle funzionalità erroneamente abbinate ho procedere come descritto nel libro OpenCV 2 Cookbook:

  1. con il matcher (= cv :: BFMatcher (cv :: NORM_L2)) i due vicini più prossimi in entrambe le direzioni vengono ricercati

    matcher.knnMatch(descriptorsImage1, descriptorsImage2, 
        matches1, 
         2); 
    matcher.knnMatch(descriptorsImage2, descriptorsImage1, 
        matches2, 
        2); 
    
  2. ho controllare il rapporto tra le distanze dei vicini più vicini trovati. Se le due distanze sono molto simili, è probabile che venga utilizzato un valore falso.

    // loop for matches1 and matches2 
    for(iterator matchIterator over all matches) 
        if(((*matchIterator)[0].distance/(*matchIterator)[1].distance) > 0.65) 
        throw away 
    
  3. Infine sono accettate solo coppie di combinazioni simmetriche. Si tratta di corrispondenze in cui non solo n1 è il vicino più vicino a feature f1, ma anche f1 è il prossimo più vicino a n1.

    for(iterator matchIterator1 over all matches) 
        for(iterator matchIterator2 over all matches) 
        if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx && 
        (*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx) 
         // good Match 
    

Ora solo le partite abbastanza buone rimangono. Per filtrare alcune partite più cattive, controlla quali corrispondenze corrispondono alla proiezione di img1 su img2 usando la matrice fondamentale.

std::vector<uchar> inliers(points1.size(),0); 
cv::findFundamentalMat(
    cv::Mat(points1),cv::Mat(points2), // matching points 
    inliers, 
    CV_FM_RANSAC, 
    3, 
    0.99); 

std::vector<cv::DMatch> goodMatches 
// extract the surviving (inliers) matches 
std::vector<uchar>::const_iterator itIn= inliers.begin(); 
std::vector<cv::DMatch>::const_iterator itM= allMatches.begin(); 
// for all matches 
for (;itIn!= inliers.end(); ++itIn, ++itM) 

    if (*itIn) 
    // it is a valid match 

good matches Il risultato è abbastanza buono. Ma in casi di estrema somiglianza si verificano ancora errori.
Nella figura sopra si vede che un mattone simile è riconosciuto bene.

bad matches Tuttavia nella seconda foto un mattone sbagliata è riconosciuto altrettanto bene.

Ora la domanda è come migliorare l'abbinamento.

ho avuto due idee diverse:

All possible brick views

  • Le partite della seconda traccia immagine indietro alle caratteristiche davvero di montaggio, ma solo se il campo visivo è intensamente cambiato. Per riconoscere un mattone devo comunque confrontarlo in molte posizioni diverse (almeno come mostrato nella figura 3). Ciò significa che so che mi è consentito solo di cambiare minimamente il campo visivo. Le informazioni su come viene modificato intensamente il campo visivo dovrebbero essere nascoste nella matrice fondamentale. Come posso leggere da questa matrice fino a che punto è cambiata la posizione nella stanza?Soprattutto la rotazione e il forte ridimensionamento dovrebbero essere di interesse; se il mattone è annegato una volta più lontano sul lato sinistro, ciò non dovrebbe avere importanza.

  • seconda idea:
    ho calcolato la matrice fondamentale su 2 immagini e filtrati caratteristiche che non si adattano le proiezioni - non ci dovrebbe essere un modo per fare la stessa cosa con tre o più immagini? (parola chiave Tensore trifocale). In questo modo la corrispondenza dovrebbe diventare più stabile. Ma non so nemmeno come farlo usando OpenCV né potrei trovare alcuna informazione su questo su google.

risposta

2

Non ho una risposta completa, ma ho alcuni suggerimenti.

Sul lato di analisi di immagine:

  • sembra che l'impostazione della fotocamera è abbastanza costante. Facile separare semplicemente il mattone dallo sfondo. Vedo anche il tuo sistema che trova funzionalità in background. Questo non è necessario. Imposta tutti i pixel non di mattoni in nero per rimuoverli dall'analisi.
  • Quando hai individuato solo il mattone, il primo passaggio dovrebbe essere semplicemente filtrare i probabili candidati in base alla dimensione (ovvero il numero di pixel) nel mattone. In questo modo l'esempio errato che hai mostrato è già meno probabile.
  • Si può prendere altre caratteristiche in considerazione, come il rapporto di aspetto del rettangolo di selezione del mattone, i major and minor axes (eigevectors della matrice di covarianza dei momenti centrali) del mattone ecc

Queste caratteristiche più semplici ti fornirà un primo filtro ragionevole per limitare il tuo spazio di ricerca.

Sul lato meccanico:

  • Se mattoni sono effettivamente scendendo un trasportatore si dovrebbe essere in grado di "raddrizzare" i mattoni lungo un regolo usando qualcosa come una canna che si trova ad un angolo rispetto alla direzione del nastro trasportatore attraverso la cintura in modo che i mattoni arrivino in modo più uniforme alla tua fotocamera like so.
  • Simile al punto precedente, è possibile utilizzare qualcosa come un pennello molto largo sospeso sulla cintura per rovesciare i mattoni in piedi mentre passano.

Ancora una volta entrambi questi punti limiteranno lo spazio di ricerca.