2012-06-28 13 views
8

Sto facendo un progetto che usa tecniche di elaborazione dell'immagine per identificare oggetti diversi e le loro lunghezze. Vado attraverso molti esempi in javaCV e OpenCV. Ma sfortunatamente non ero in grado di identificare la forma T del poligono.Come identificare il poligono usando opencv o javacv?

Provo ad usare il seguente metodo di identificazione del rettangolo ma non l'ho superato.

public static CvSeq findSquares(final IplImage src, CvMemStorage storage) 
{ 

CvSeq squares = new CvContour(); 
squares = cvCreateSeq(0, sizeof(CvContour.class), sizeof(CvSeq.class), storage); 

IplImage pyr = null, timg = null, gray = null, tgray; 
timg = cvCloneImage(src); 

CvSize sz = cvSize(src.width() & -2, src.height() & -2); 
tgray = cvCreateImage(sz, src.depth(), 1); 
gray = cvCreateImage(sz, src.depth(), 1); 
pyr = cvCreateImage(cvSize(sz.width()/2, sz.height()/2), src.depth(), src.nChannels()); 

// down-scale and upscale the image to filter out the noise 
cvPyrDown(timg, pyr, CV_GAUSSIAN_5x5); 
cvPyrUp(pyr, timg, CV_GAUSSIAN_5x5); 
cvSaveImage("ha.jpg", timg); 
CvSeq contours = new CvContour(); 
// request closing of the application when the image window is closed 
// show image on window 
// find squares in every color plane of the image 
for(int c = 0; c < 3; c++) 
{ 
    IplImage channels[] = {cvCreateImage(sz, 8, 1), cvCreateImage(sz, 8, 1), cvCreateImage(sz, 8, 1)}; 
    channels[c] = cvCreateImage(sz, 8, 1); 
    if(src.nChannels() > 1){ 
     cvSplit(timg, channels[0], channels[1], channels[2], null); 
    }else{ 
     tgray = cvCloneImage(timg); 
    } 
    tgray = channels[c]; 
    // try several threshold levels 
    for(int l = 0; l < N; l++) 
    { 
    //    hack: use Canny instead of zero threshold level. 
    //    Canny helps to catch squares with gradient shading 
     if(l == 0) 
     { 
    //    apply Canny. Take the upper threshold from slider 
    //    and set the lower to 0 (which forces edges merging) 
         cvCanny(tgray, gray, 0, thresh, 5); 
    //     dilate canny output to remove potential 
    //    // holes between edge segments 
         cvDilate(gray, gray, null, 1); 
       } 
      else 
     { 
    //    apply threshold if l!=0: 
         cvThreshold(tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY); 
      } 
     //   find contours and store them all as a list 
         cvFindContours(gray, storage, contours, sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

         CvSeq approx; 

     //   test each contour 
         while (contours != null && !contours.isNull()) { 
         if (contours.elem_size() > 0) { 
          approx = cvApproxPoly(contours, Loader.sizeof(CvContour.class),storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0); 
        if(approx.total() == 4 
          && 
          Math.abs(cvContourArea(approx, CV_WHOLE_SEQ, 0)) > 1000 && 
         cvCheckContourConvexity(approx) != 0 
         ){ 
         double maxCosine = 0; 
         // 
         for(int j = 2; j < 5; j++) 
         { 
      // find the maximum cosine of the angle between joint edges 
               double cosine = Math.abs(angle(new CvPoint(cvGetSeqElem(approx, j%4)), new CvPoint(cvGetSeqElem(approx, j-2)), new CvPoint(cvGetSeqElem(approx, j-1)))); 
               maxCosine = Math.max(maxCosine, cosine); 
         } 
         if(maxCosine < 0.2){ 
           CvRect x=cvBoundingRect(approx, l); 
           if((x.width()*x.height())<5000){ 
            System.out.println("Width : "+x.width()+" Height : "+x.height()); 
          cvSeqPush(squares, approx); 
            //System.out.println(x); 
           } 
         } 
        } 
       } 
       contours = contours.h_next(); 
      } 
     contours = new CvContour(); 
    } 
} 
return squares; 
} 

Per favore qualcuno può aiutarmi a modificare questo metodo per identificare le forme T da un'immagine. L'immagine di input è come questa.

enter image description here

Questa è la forma a T che devo identificare

enter image description here

+0

È l'immagine di input? – ArtemStorozhuk

+0

quale parte di questa immagine devi identificare? –

+0

Ho aggiornato la domanda ora contiene i dettagli a riguardo. –

risposta

6

Ho trovato la soluzione al vostro problema: immagine

  • Converti in scala di grigi:

grayscale image

  • Fare una soglia (convertire l'immagine 1 bit a):

2bit image

  • Trova contorni e riempirli:

filled image

Suggerimento: per riempire i contorni in OpenCV utilizzare -1 come parametro thickness in drawContours funzione.

  • fare una dilatazione e dopo questa erosione con lo stesso kernel:

result image

E questo è tutto! Dopo questo, non è un problema per te trovare la tua figura T a forma di immagine sull'immagine!

Purtroppo non so JavaCV ma posso condividere con voi C++ codice:

Mat src = imread("in.jpg"), gray; 

cvtColor(src, gray, CV_BGR2GRAY); 

threshold(gray, gray, 230, 255, THRESH_BINARY_INV); 

vector<Vec4i> hierarchy; 
vector<vector<Point> > contours; 

findContours(gray, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

gray = Scalar::all(255); 
for (size_t i=0; i<contours.size(); i++) 
{ 
    drawContours(gray, contours, i, Scalar(0), -1); 
} 

Mat element = getStructuringElement(MORPH_RECT, Size(2, 2), Point(1, 1)); 
dilate(gray, gray, element); 
erode(gray, gray, element); 

imshow("window", gray); 

Suggerimento: se si vuole si può convertire questo codice per JavaCV. Per fare questo leggi this tutorial.

+0

Quindi, come posso accedere alle lunghezze di questo tipo di poligono? –

+1

@LBNCons Prima di tutto devi identificare questo poligono. Ci sono molti modi in cui puoi farlo. Dopo aver rilevato il poligono, basta usare la funzione 'approxPolyDP'. – ArtemStorozhuk

+0

@Astor Il metodo approxPolyDP fornisce esattamente 8 punti? –

1

Si potrebbe essere meglio di trovare contorni e utilizzare CvApproxPoly(). Puoi trovare un buon esempio di come usare questa funzione per trovare i rettangoli here e adattarlo per trovare le forme T. Questo esempio è stato creato usando OpenCV e scritto in C++.

di passare attraverso tutti i punti in sequenza:

for (int i = 0; i < cornerPoints->total; i++) { 
CvPoint *cornerPoints = (CvPoint*) cvGetSeqElem(cornerPoints, i); 
} 
+4

Si prega di fornire un semplice esempio di codice per questo –

+0

Sono passato al metodo CvApproxPoly() ma restituisce anche un CvSeq. Ma devo estrarre le coordinate di spigoli sul poligono –

+0

Se si desidera creare un CvPoint tra tutti i punti del contorno, è possibile utilizzare un ciclo for per passare attraverso tutti i punti. Ho aggiunto questo alla mia risposta. –

0

suona come compiti a casa anche se

il pre-processing @Astor portare è sicuramente utile. ma in qualche modo penso ancora che questo riconoscimento di forma sia fortemente connesso con Image Processing: Morfology

potresti preparare un modello a forma di T e poi "convoluto?" il modello con il risultato pre-elaborato. Non ricordo altri dettagli, basta un sondaggio su TAG Morphology and Convolution

Problemi correlati