2011-12-21 7 views
12

Come una sorta di "progetto di vacanza" sto giocando con OpenCV e voglio rilevare e misurare le cose.OpenCV C++/Obj-C: rilevamento oggetto corretto

flusso di lavoro attuale (fase iniziale - rilevamento):

  1. Converti in scala di grigi (cv :: cvtColor)
  2. Applicare soglia adattiva (cv :: adaptiveThreshold)
  3. Applicare Algoritmo di Canny (cv: : Canny)
  4. Trovare contorni (cv :: findContours)

il mio risultato è un pò scadente e non sono sicuro che cosa è il righ t direzione da seguire. Ho già ottenuto cvBlob lavorando sotto la mia attuale configurazione (OSX 10.7.2, Xcode 4.2.1) è un modo migliore per andare? In tal caso, come posso implementarlo nel modo giusto?

Oppure devo prima sottrarre il background? Ci ho provato, ma non sono riuscito a trovare contorni dopo

Ecco la mia immagine: image to measure

E questa è la mia uscita, quando disegno i miei contorni di nuovo nella prima immagine: output

UPDATE

ho preso a lavorare nel mio programma e la mia uscita sembra un po 'diverso ...

- (IBAction)processImage:(id)sender 
{ 
    cv::Mat forground = [[_inputView image] CVMat]; 
    cv::Mat result = [self isolateBackground:forground]; 
    [_outputView setImage:[NSImage imageWithCVMat:result]]; 
} 

- (cv::Mat)isolateBackground:(cv::Mat &)_image 
{ 
    int rh = 255, rl = 100, gh = 255, gl = 0, bh = 70, bl = 0; 
    cv::cvtColor(_image, _image, CV_RGB2HSV_FULL); 
    cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); 
    cv::Mat bgIsolation; 
    cv::inRange(_image, cv::Scalar(bl, gl, rl), cv::Scalar(bh, gh, rh), bgIsolation); 
    bitwise_not(bgIsolation, bgIsolation); 
    erode(bgIsolation, bgIsolation, cv::Mat()); 
    dilate(bgIsolation, bgIsolation, element); 
    return bgIsolation; 
} 

risposta

10

Questo potrebbe essere una specie di hack, ma dal momento che è un "progetto di vacanza", vi posterò comunque :)

Hai provato isolare lo sfondo e poi invertire la maschera (questo sarebbe non dare niente per scontato lo sfondo è un oggetto, ma potrebbe funzionare per quello che vuoi).

seguenti è il risultato ho ottenuto utilizzando la funzione di OpenCV inRange: enter image description here

Si potrebbe voler smussare l'immagine (pre-processo) con GuassianBlur di sbarazzarsi di alcuni dei bordi frastagliati. Ho usato un kernel di dilatazione più grande del kernel di erosione (5x5 contro 3x3) per eliminare alcuni pixel rumorosi. Il livellamento potrebbe aiutare questo anche a modificare le soglie potrebbe rendere l'erosione inutile. Ma questo dovrebbe farti iniziare.

Infine, ecco il mio breve codice piccolo frammento che ho usato per trovare questa gamma:

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <vector> 

using namespace cv; 
using namespace std; 

int main(int argc, char** argv) 
{ 
    Mat src = imread("test.jpg"); 


    int rh = 255, rl = 100, gh = 255, gl = 0, bh = 70, bl = 0; 

    string windowName = "background"; 
    namedWindow(windowName); 

    createTrackbar("rh", windowName, &rh, 255); 
    createTrackbar("rl", windowName, &rl, 255); 
    createTrackbar("gh", windowName, &gh, 255); 
    createTrackbar("gl", windowName, &gl, 255); 
    createTrackbar("bh", windowName, &bh, 255); 
    createTrackbar("bl", windowName, &bl, 255); 

    // for dilation 
    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); 

    Mat bgIsolation; 
    int key = 0; 
    do 
    { 
     inRange(src, Scalar(bl, gl, rl), Scalar(bh, gh, rh), bgIsolation); 

     bitwise_not(bgIsolation, bgIsolation); 

     erode(bgIsolation, bgIsolation, Mat()); 
     dilate(bgIsolation, bgIsolation, element); 

     imshow(windowName, bgIsolation); 
     key = waitKey(33); 
    } while((char)key != 27); 

    waitKey(); 

    return 0; 
} 

Godetevi il progetto di vacanza! Sembra divertente :)

+0

Grazie mille! Puoi dare un'occhiata al mio codice? – dom

+0

@moosgummi Il motivo per cui si sta ottenendo un output diverso è perché ci si sta trasformando nello spazio colore HSV. Le mie soglie erano per lo spazio RGB. Puoi usare HSV, ma dovrai trovare gli intervalli appropriati per quello spazio. È possibile aggiungere la conversione del colore alla mia applicazione di esempio e provarla. Immagino che dovrai preoccuparti solo dei canali Tonalità e Saturazione poiché il canale Valore non contiene alcuna informazione sul colore (ad esempio, l'intervallo di valori non verrà toccato [0, 255]). Spero possa aiutare! – mevatron

+0

Ah ok, quindi dovrebbe funzionare meglio in RGB?bl, gl e rl sono valori blu, verdi e rossi. Ho ragione? – dom