在OpenCV中检测三角形

时间:2014-03-02 17:46:51

标签: java android opencv computer-vision

我尝试使用OpenCV4Android SDK和我的Android手机相机检测形状(三角形和正方形)。 到目前为止,我需要修改代码的这一部分,但我不确定如何使用openCv Aboutpoly函数来检测这些形状 任何帮助将不胜感激。

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 个答案:

答案 0 :(得分:3)

由于轮廓检测返回的类型略有不同以及aboutPolyDP预期的类型,它有点繁琐。看看我开发的这个函数几乎可以满足您的需求:

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

好的,所以要在你的代码中使用这个函数,我会使用这样的东西:

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

所以在你的代码中,之后:

 Imgproc.findContours(mDilatedMask, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
你可以这样打电话:

List<MatOfPoint> squareContours = getSquareContours(contours);

squareContours将只有正方形轮廓(或者如果你说的话是三角形,你在检查approxContour.size()。height时使用值3)

然后您可以继续使用其余代码,如下所示:

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