2012-06-28 1 views
8

Je fais un projet qui utilise des techniques de traitement d'image pour identifier différents objets et leurs longueurs. Je passe par de nombreux exemples dans javaCV ainsi que OpenCV. Mais malheureusement, j'étais incapable d'identifier la forme en T du polygone.Comment identifier un polygone en utilisant opencv ou javacv?

J'essaie d'utiliser la méthode d'identification rectangle suivante mais je l'ai échoué.

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; 
} 

S'il vous plaît, pouvez-vous m'aider à modifier cette méthode pour identifier des formes T à partir d'une image. L'image d'entrée est comme ça.

enter image description here

C'est la forme de T que je dois identifier

enter image description here

+0

Est-ce votre image d'entrée? – ArtemStorozhuk

+0

quelle partie de cette image vous devez identifier? –

+0

J'ai mis à jour la question maintenant il contient les détails à ce sujet. –

Répondre

6

J'ai trouvé la solution à votre problème:

    l'image
  • Convertir en niveaux de gris:

grayscale image

  • Faites un seuil (convertir en image 1 bit):

2bit image

  • Trouver les contours et les remplir:

filled image

Astuce: pour remplir les contours dans OpenCV utiliser -1 comme paramètre thickness dans drawContours fonction.

  • Faites une dilatation et après cette érosion avec le même noyau:

result image

Et voilà! Après cela, ce n'est pas un problème pour vous de trouver votre T en forme de figure sur l'image!

Unfortunatelly Je ne sais pas JavaCV mais je peux partager avec vous C++ code:

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); 

Astuce: si vous voulez, vous pouvez convertir ce code JavaCV. Pour ce faire, lisez this tutorial.

+0

Alors, comment puis-je accéder aux longueurs de ce type de polygone? –

+1

@LBNCons Tout d'abord, vous devez identifier ce polygone. Il y a plusieurs façons de faire cela. Après la détection du polygone, il suffit d'utiliser la fonction 'approxPolyDP'. – ArtemStorozhuk

+0

@Astor La méthode approxPolyDP fournit-elle exactement 8 points? –

1

Vous pourriez être mieux de trouver les contours et en utilisant CvApproxPoly(). Vous pouvez trouver un bon exemple d'utilisation de cette fonction pour trouver les rectangles here et l'adapter pour trouver vos formes en T. Cet exemple est créé en utilisant OpenCV et écrit en C++.

Pour passer par tous les points dans une séquence:

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

S'il vous plaît pouvez-vous fournir un exemple de code simple pour cela –

+0

Je suis allé à travers la méthode CvApproxPoly(), mais il renvoie également un CvSeq. Mais je dois extraire les cordinates des arêtes sur le polygone –

+0

Si vous voulez faire un CvPoint sur tous les points du contour, vous pouvez utiliser une boucle for pour parcourir tous les points. J'ai ajouté ceci à ma réponse. –

0

sonne comme devoirs si

le prétraitement @Astor Provoquer est certainement utile. mais je pense encore quelque peu que cette reconnaissance de forme est fortement liée à Traitement de l'image: Morphologie

vous pouvez préparer un modèle en forme de T puis "convolute?" le modèle avec le résultat pré-traité. Je ne me souviens pas de plus de détails, juste une enquête sur TAG Morphology and Convolution

Questions connexes