OPENCV-C++ 找到最大内接矩形(正方形)

这源代码本来是检测最大内接圆形的,本人想要矩形,所以变成了正方形;谨慎使用;不是严格意义上的最大内接矩形;

cv::Mat map_one_label = cv::imread("src.png",cv2.IMREAD_GRAYSCALE); //默认灰度图
std::vector<Rect> max_in_quare_rect  = get_max_in_quare_rec(map_one_label);
std::vector<Rect> get_max_in_quare_rec(Mat &map_one_label){

    std::vector<Rect> results;
    Rect ccomp;
    cv::Point center(map_one_label.cols / 2, map_one_label.rows / 2);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(map_one_label, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    for (int i = 0; i < contours.size(); i++)
    {
        Mat  dist = Mat::zeros(map_one_label.size(), CV_32F);		//定义一个Mat对象,存放原图中每个点到该轮廓的距离,为浮点型数据
        //遍历每个点,计算该点到轮廓距离
        for (int row = 0; row < map_one_label.rows; row++)
        {
            for (int col = 0; col < map_one_label.cols; col++)
            {
                //通过点多边形检测计算获得点到轮廓距离,并存放至dist中
                dist.at<float>(row, col) = pointPolygonTest(contours[i], Point(col, row), true);
            }
        }

        //计算dist中,最大值和最小值,以及其位置坐标
        double minVal, maxVal;
        Point maxloc, minloc;
        minMaxLoc(dist, &minVal, &maxVal, &minloc, &maxloc);
        int radio = abs(maxVal);			//对最大值求绝对值,即为内接圆半径
        cout << "haha " << radio << endl;
        Point center;

        center = maxloc;	//某点与轮廓距离为最大值,则该点为内接圆圆心
        cv::Point point_tl(center.x-radio , center.y-radio);
        cv::Point point_dr(center.x+radio , center.y+radio);
        cv::Rect rect1(point_dr , point_tl );
        results.push_back(rect1);

    }
    imshow("src", map_one_label);
    cv::waitKey(0);
    return results;

}

原图
在这里插入图片描述

检测结果:
在这里插入图片描述

加速版本可尝试

std::vector<Rect> get_max_in_quare_rec(Mat &map_one_label) {
    std::vector<Rect> results;
    std::vector<std::vector<Point>> contours;
    std::vector<Vec4i> hierarchy;

    // 使用 RETR_EXTERNAL 方式找到所有轮廓
    findContours(map_one_label, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    // 遍历每个轮廓
    for (int i = 0; i < contours.size(); i++) {
        // 获取当前轮廓的边界框
        Rect boundingBox = boundingRect(contours[i]);

        // 只在bounding box内计算距离
        Mat dist = Mat::zeros(boundingBox.size(), CV_32F);
        
        #pragma omp parallel for
        for (int row = 0; row < boundingBox.height; row++) {
            for (int col = 0; col < boundingBox.width; col++) {
                Point pt(col + boundingBox.x, row + boundingBox.y);
                dist.at<float>(row, col) = pointPolygonTest(contours[i], pt, true);
            }
        }

        // 找到距离最大的点
        double minVal, maxVal;
        Point maxloc, minloc;
        minMaxLoc(dist, &minVal, &maxVal, &minloc, &maxloc);
        int radius = std::abs(static_cast<int>(maxVal));

        // 确定内接圆的圆心及其矩形框
        Point center = maxloc + Point(boundingBox.x, boundingBox.y);
        cv::Point point_tl(center.x - radius, center.y - radius);
        cv::Point point_dr(center.x + radius, center.y + radius);
        cv::Rect rect1(point_tl, point_dr);
        results.push_back(rect1);
    }

    // 可视化结果
    imshow("src", map_one_label);
    cv::waitKey(0);

    return results;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐