0

I'm trying to detect shapes (triangles and squares) using the OpenCV4Android SDK and my Android phone Camera. So far, I need to modify this part of the code but I'm not sure how to use the openCv Approxpoly function in order to detect those shapes Any help would be greatly appreciated.

public void process(Mat rgbaImage) 
        {
            Imgproc.pyrDown(rgbaImage, mPyrDownMat);
            Imgproc.pyrDown(mPyrDownMat, mPyrDownMat);

        Imgproc.cvtColor(mPyrDownMat, mHsvMat, Imgproc.COLOR_RGB2HSV_FULL);

        Core.inRange(mHsvMat, mLowerBound, mUpperBound, mMask);
        Imgproc.dilate(mMask, mDilatedMask, new Mat());

        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();

        Imgproc.findContours(mDilatedMask, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

        // Find max contour area
        double maxArea = 0;
        Iterator<MatOfPoint> each = contours.iterator();
        while (each.hasNext()) 
        {
            MatOfPoint wrapper = each.next();
            double area = Imgproc.contourArea(wrapper);
            if (area > maxArea)
                maxArea = area;
        }

        //Imgproc.approxPolyDP(mSpectrum, approxCurve, epsilon, closed);

        // Filter contours by area and resize to fit the original image size
        mContours.clear();
        each = contours.iterator();

        while (each.hasNext()) 
        {
            MatOfPoint contour = each.next();
            if (Imgproc.contourArea(contour) > mMinContourArea*maxArea) 
            {
                Core.multiply(contour, new Scalar(4,4), contour);
                mContours.add(contour);
            }
        }
    }

1 Answer 1

3

It's a bit fiddly because of the slightly different types that the contour detection returns and what approxPolyDP is expecting. Have a look at this function that I developed to do pretty much what you are looking for:

public static boolean isContourSquare(MatOfPoint thisContour) {

    Rect ret = null;

    MatOfPoint2f thisContour2f = new MatOfPoint2f();
    MatOfPoint approxContour = new MatOfPoint();
    MatOfPoint2f approxContour2f = new MatOfPoint2f();

    thisContour.convertTo(thisContour2f, CvType.CV_32FC2);

    Imgproc.approxPolyDP(thisContour2f, approxContour2f, 2, true);

    approxContour2f.convertTo(approxContour, CvType.CV_32S);

    if (approxContour.size().height == 4) {
        ret = Imgproc.boundingRect(approxContour);
    }

    return (ret != null);
}

Ok, so to use this function in your code I would use something like this:

public static List<MatOfPoint> getSquareContours(List<MatOfPoint> contours) {

    List<MatOfPoint> squares = null;

    for (MatOfPoint c : contours) {

        if ((ContourUtils.isContourSquare(c)) {

            if (squares == null)
                squares = new ArrayList<MatOfPoint>();
            squares.add(c);
        }
    }

    return squares;
}

so in your code, after:

 Imgproc.findContours(mDilatedMask, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

you can make a call like this:

List<MatOfPoint> squareContours = getSquareContours(contours);

squareContours will then just have the square contours (or triangular if as you say, you use the value 3 when checking approxContour.size().height)

you can then continue with the remaining code as follows:

// Filter contours by area and resize to fit the original image size
    mContours.clear();
    each = squareContours.iterator();

    while (each.hasNext()) 
    {
        MatOfPoint contour = each.next();
        if (Imgproc.contourArea(contour) > mMinContourArea*maxArea) 
        {
            Core.multiply(contour, new Scalar(4,4), contour);
            mContours.add(contour);
        }
    }
Sign up to request clarification or add additional context in comments.

1 Comment

I think I understand what the code is doing, but how do I implement on the code above? I guess that in order to detect triangles the contour size should be 3.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.