OpenCV:如何找到所有封闭的形状,无论是圆形,方形,三角形,还是其他什么?

时间:2015-02-20 16:43:44

标签: ios opencv

如何识别照片中的形状?我想用iOS应用程序实现它,但目前唯一被认可的是填充的红色方块。

我在iOS 8上使用OpenCV版本2.4.9。

enter image description here

// Convert to grayscale
cv::Mat gray;
cv::cvtColor(src, gray, CV_BGR2GRAY);

// Convert to binary image using Canny
cv::Mat bw;
cv::Canny(gray, bw, 0, 50, 5);

imageView.image = [UIImage fromCVMat:gray];

// Find contours
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

// The array for storing the approximation curve
std::vector<cv::Point> approx;

// We'll put the labels in this destination image
cv::Mat dst = src.clone();

for (int i = 0; i < contours.size(); i++)
{
    // Approximate contour with accuracy proportional
    // to the contour perimeter
    cv::approxPolyDP(
                     cv::Mat(contours[i]),
                     approx,
                     cv::arcLength(cv::Mat(contours[i]), true) * 0.02,
                     true
                     );

    BOOL area = std::fabs(cv::contourArea(contours[i])) < 10;
    BOOL convex = false; // !cv::isContourConvex(approx);

    // Skip small or non-convex objects
    if (area || convex) {
        if (area) {
            NSLog(@"contourarea : %f", std::fabs(cv::contourArea(contours[i])));
        } else {
            NSLog(@"convex : %i", !cv::isContourConvex(approx));
        }
        NSLog(@"=========");
        continue;
    }

    if (approx.size() == 1) {
        setLabel(dst, "TRI", contours[i]);    // Triangles
    } else if (approx.size() >= 4 && approx.size() <= 6) {
        // Number of vertices of polygonal curve
        int vtc = approx.size();

        // Get the degree (in cosines) of all corners
        std::vector<double> cos;
        for (int j = 2; j < vtc+1; j++) {
            cos.push_back(angle(approx[j%vtc], approx[j-2], approx[j-1]));
        }

        // Sort ascending the corner degree values
        std::sort(cos.begin(), cos.end());

        // Get the lowest and the highest degree
        double mincos = cos.front();
        double maxcos = cos.back();

        // Use the degrees obtained above and the number of vertices
        // to determine the shape of the contour
        if (vtc == 4 && mincos >= -0.1 && maxcos <= 0.3)
        {
            // Detect rectangle or square
            cv::Rect r = cv::boundingRect(contours[i]);
            double ratio = std::abs(1 - (double)r.width / r.height);

            setLabel(dst, ratio <= 0.02 ? "SQU" : "RECT", contours[i]);
        }
        else if (vtc == 5 && mincos >= -0.34 && maxcos <= -0.27)
            setLabel(dst, "PENTA", contours[i]);
        else if (vtc == 6 && mincos >= -0.55 && maxcos <= -0.45)
            setLabel(dst, "HEXA", contours[i]);
    }
    else
    {
        // Detect and label circles
        double area = cv::contourArea(contours[i]);
        cv::Rect r = cv::boundingRect(contours[i]);
        int radius = r.width / 2;

        if (std::abs(1 - ((double)r.width / r.height)) <= 0.2 &&
            std::abs(1 - (area / (CV_PI * std::pow(radius, 2)))) <= 0.2) {
        }
    }
} // end of for() loop

0 个答案:

没有答案