0

I wanted to find the convex hull in order to even the edges of a hand-drawn triangle on paper. Smoothing using image processing was not enough because i needed to detect this triangle too and a hand drawn triangle tends to have more than three points if the approxPolyDP function is used. A convex hull of a triangle is correctly identified by the approxPolyDP function.

The problem is, i have other shapes in the image too on which a convex hull is created.

Before convex hull is used: Notice the contour labelled 3

After convex hull is used: the end points have been joined and the contour labelled 3 forms a triangle

Now i wanted to somehow exclude contour 3 from being detected as a triangle. To do this my strategy was to remove this contour altogether from the ArrayList named hullMop. This is because my triangle detection function uses the contours from hullMop and so it wouldnt even check the contour labelled 3.

extcontours are the contours before convex hull is used. This function checks if a point from hullMop is inside extcontours. If it isn't, then that must be removed from hullMop because they are the extra set of points generated because of the convex hull, or in other words, the red line in the second image.

Now at this point I feel there is a hole in my concept. The openCV documentation says that the convex Hull returns the subset of the points of the original array, in other words, subset of the points of extcontours.

My question is, how do i get the points of the red line created by the convexHull function. I dont want to use findContours because i feel there is a better way.

private void RemoveFalseHullTriangles(ArrayList<MatOfPoint> extcontours, ArrayList<MatOfPoint> hullMop, int width, int height) {
    //if every single point of hullmop doesnt touch or isn't inside extcontours, then that point must be the red line
    MatOfPoint2f Contours2f = new MatOfPoint2f();
    double [] newA = new double[2];
    int hullCounter = 0;
    A: for(int i =0;i<extcontours.size();i++) {
        MatOfPoint ExtCnt = extcontours.get(i);
        MatOfPoint HullCnt = hullMop.get(hullCounter);
        ExtCnt.convertTo(Contours2f, CvType.CV_32F);
        B: for (int j = 0; j < HullCnt.rows(); j++) {
            double[] pt = new double[2];
            pt[0] = HullCnt.get(j,0)[0];
            pt[1] = HullCnt.get(j,0)[1];

            if (Math.abs(Imgproc.pointPolygonTest(Contours2f, new Point(pt), true)) > 40) {
                    //Remove index from HullMop
                hullMop.remove(hullCounter);
                hullCounter--;
                break B;
            }


        }
        hullCounter++;
    }
}

Because the hullMop only has a subset of the points of extcontours, i may never know the points of the red line of the contour labelled 3 after convex hull is used. Is there anyway to get coordinates of that red line generated by convex hull other than using findContours?

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
  • I think [this question/answer](https://stackoverflow.com/questions/22240746/recognize-open-and-closed-shapes-opencv) may help answer your question. The real question here isn't how to get the points of the convex hull (the points are as you say subset of your contour points), but how to test whether the contour is closed or not (the convex hull always closes contours). – alkasm Dec 03 '17 at 23:25
  • By the way just to expand on that answer I linked above: when the answerer says "child contour", they mean that there is a contour which is the exterior of the shape and a contour which is the interior of the shape. A child contour is a contour contained completely within another one---so closed shapes are defined as a contour which has another contour inside it. – alkasm Dec 04 '17 at 00:36
  • I would draw the convex hull and use distanceTransform to find allpixel positions that don't have a correspondence in your input image. – Micka Dec 04 '17 at 06:30

1 Answers1

0

As referenced by Alexandar Reynolds, the problem really was detecting open contours first and excluding those contours before finding the convex hull. The method to find open contours is explained here: Recognize open and closed shapes opencv

Basically, if an outer contour has no child contour in the hierarchy, then it is an open contour and must be excluded before finding convex hull ( for my case).