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