2012-06-28 17 views
8

Estoy haciendo un proyecto que utiliza técnicas de procesamiento de imágenes para identificar diferentes objetos y sus longitudes. Repaso muchos ejemplos en javaCV y en OpenCV. Pero desafortunadamente no pude identificar la forma en T del polígono.¿Cómo identificar el polígono usando opencv o javacv?

Intento usar el siguiente método de identificación de rectángulo pero no lo logré.

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

Por favor, algunos me pueden ayudar a modificar este método para identificar las formas T de una imagen. La imagen de entrada es así.

enter image description here

Esta es la forma de T que tengo para identificar

enter image description here

+0

¿Esa es tu imagen de entrada? – ArtemStorozhuk

+0

¿qué parte de esta imagen debe identificar? –

+0

He actualizado la pregunta ahora contiene los detalles al respecto. –

Respuesta

6

he encontrado la solución a su problema: Imagen

  • Convertir a escala de grises:

grayscale image

  • hacer un umbral (convertir una imagen de 1 bit a):

2bit image

  • Encuentra contornos y llenarlos:

filled image

Consejo: para llenar los contornos en OpenCV use -1 como parámetro thickness en drawContours función.

  • Haz una dilatación y después de esta erosión con el mismo núcleo:

result image

Y eso es todo! Después de esto, no es un problema para usted encontrar su T-figura en forma de la imagen!

Desafortunadamente no sé JavaCV pero puedo compartir con ustedes C++ código:

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

Consejo: si lo desea, puede convertir este código para JavaCV. Para hacerlo, lea this tutorial.

+0

Entonces, ¿cómo puedo acceder a las longitudes de este tipo de polígono? –

+1

@LBNCons Antes que nada debes identificar este polígono. Hay muchas maneras en que puedes hacer eso. Después de detectar el polígono, simplemente usa la función 'approxPolyDP'. – ArtemStorozhuk

+0

@Astor ¿El método approxPolyDP proporciona 8 puntos exactos? –

1

Usted podría ser mejor contornos de encontrar y usar CvApproxPoly(). Puede encontrar un buen ejemplo de cómo usar esta función para encontrar rectángulos here y adaptarlo para encontrar sus formas en T. Este ejemplo se crea utilizando OpenCV y escrito en C++.

que pasar por todos los puntos en una secuencia:

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

Puede proporcionar un ejemplo de código simple para este –

+0

Pasé por el método CvApproxPoly() pero también devuelve un CvSeq. Pero tengo que extraer los cordinates de los bordes en el polígono –

+0

Si quiere hacer un CvPoint de todos los puntos del contorno, puede usar un ciclo for para recorrer todos los puntos. Agregué esto a mi respuesta. –

0

suena como tarea aunque

el pre-procesamiento @Astor provocar es definitivamente útil. pero todavía creo que este reconocimiento de forma está fuertemente relacionado con el procesamiento de imágenes: morfología

podría preparar una plantilla en forma de T y luego "convolute?" la plantilla con el resultado preprocesado. No puedo recordar más detalles, solo encuesta en TAG Morphology and Convolution

Cuestiones relacionadas