6
votes

I'm using android openCV and I want to detect triangle, rectangle and circle in an image. So I do it as follow: Canny => findContours => approxPolyDP and get this image: Image Hosted by ImageShack.us http://imageshack.us/a/img839/8100/device20130114224716.png

However, the result of approxPolyDP contains so many vertices so I can't determine which shape is it. To eliminate the vertices, I want to detect lines in each contours and find their intersections. How can I do that for a single contour?

1
do the red circles also count as circles? I am asking this coz they have open contours that's why and hence ideally don't qualify as circles...rotating_image
The "red circles" are actually the C letter :), I draw it using Core.putText, we don't have to worry about it.quacker

1 Answers

4
votes

For circles detection, use HoughCircles.

Then here you are just looking for simplified polygons (triangles and squares). Have you tried tweaking epsilon in approxPolyDP?

Here is an example snippet from the openCV squares.cpp sample code - see how approximation accuracy (epsilon, the third parameter of approxPolyDP), is set relative to the size of the contour.

C++ code, but the openCV interface should be the same, so I'm sure it's straightforward to adapt to your environment.

 // test each contour
  for( size_t i = 0; i < contours.size(); i++ )
      {
          // approximate contour with accuracy proportional
          // to the contour perimeter
      approxPolyDP(Mat(contours[i]), approx, 
                        arcLength(Mat(contours[i]), true)*0.02, true);

          // square contours should have 4 vertices after approximation
          // relatively large area (to filter out noisy contours)
          // and be convex.
          // Note: absolute value of an area is used because
          // area may be positive or negative - in accordance with the
          // contour orientation
      if( approx.size() == 4 &&
         fabs(contourArea(Mat(approx))) > 1000 &&
         isContourConvex(Mat(approx)) )
          {
          double maxCosine = 0;

          for( int j = 2; j < 5; j++ )
              {
                  // find the maximum cosine of the angle between joint edges
              double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
              maxCosine = MAX(maxCosine, cosine);
              }

              // if cosines of all angles are small
              // (all angles are ~90 degree) then write quandrange
              // vertices to resultant sequence

          if( maxCosine < 0.3 )
              squares.push_back(approx);
          }
      }