C++求轮廓内最大矩形,要求避开内轮廓
时间: 2023-07-11 21:44:11 浏览: 131
实现轮廓内最大矩形的方法如下:
1. 根据轮廓信息,使用 `cv::boundingRect` 函数计算轮廓的最小外接矩形。
2. 将最小外接矩形旋转回原始角度。
3. 从最小外接矩形的四个顶点出发,沿着矩形边缘向内搜索,找到轮廓内部的点,并记录下这些点的索引。
4. 对于每一个内部点,求出它到最外层轮廓边界的距离,并计算以该点为中心、以该距离为宽度的最大矩形的面积。
5. 找到面积最大的矩形,并返回其顶点坐标。
为了避开内轮廓,可以使用 `cv::findContours` 函数的 `mode` 参数设置为 `CV_RETR_EXTERNAL`,只检测最外层的轮廓。
示例代码如下:
```c++
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
// 读取图像并转为灰度图像
Mat img = imread("test.jpg");
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// 二值化处理
Mat bin;
threshold(gray, bin, 0, 255, THRESH_BINARY | THRESH_OTSU);
// 查找轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(bin, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 对每个轮廓求最大矩形
for (size_t i = 0; i < contours.size(); i++)
{
// 计算最小外接矩形
RotatedRect rect = minAreaRect(contours[i]);
// 将矩形旋转回原始角度
float angle = rect.angle;
if (angle < -45)
angle += 90;
Size2f size = rect.size;
Point2f center = rect.center;
Mat rot_mat = getRotationMatrix2D(center, angle, 1.0);
warpAffine(img, img, rot_mat, img.size());
// 查找轮廓内部的点
vector<int> indices;
for (size_t j = 0; j < contours[i].size(); j++)
{
Point2f pt = contours[i][j];
int dx = pt.x - center.x;
int dy = pt.y - center.y;
if (dx >= -size.width/2 && dx <= size.width/2 && dy >= -size.height/2 && dy <= size.height/2)
indices.push_back(j);
}
// 计算每个内部点到边界的距离,并求最大的矩形面积
double max_area = 0;
vector<Point2f> max_rect(4);
for (size_t j = 0; j < indices.size(); j++)
{
Point2f pt = contours[i][indices[j]];
int dx = pt.x - center.x;
int dy = pt.y - center.y;
double dist = sqrt(dx*dx + dy*dy);
double width = dist * 2;
double height = 0;
for (size_t k = 0; k < contours[i].size(); k++)
{
Point2f pt2 = contours[i][k];
int dx2 = pt2.x - pt.x;
int dy2 = pt2.y - pt.y;
double dist2 = sqrt(dx2*dx2 + dy2*dy2);
if (dist2 > height)
{
height = dist2;
Point2f dir(-dy2, dx2);
dir *= width / height;
Point2f pt3 = pt + dir;
if (pt3.x >= 0 && pt3.x < img.cols && pt3.y >= 0 && pt3.y < img.rows)
{
vector<Point2f> rect_points(4);
rect_points[0] = pt + dir;
rect_points[1] = pt - dir;
rect_points[2] = pt - dir + Point2f(dy2, -dx2);
rect_points[3] = pt + dir + Point2f(dy2, -dx2);
double area = contourArea(rect_points);
if (area > max_area)
{
max_area = area;
max_rect = rect_points;
}
}
}
}
}
// 绘制最大矩形
for (size_t j = 0; j < 4; j++)
line(img, max_rect[j], max_rect[(j+1)%4], Scalar(0, 0, 255), 2, LINE_AA);
// 绘制最小外接矩形
Point2f vertices[4];
rect.points(vertices);
for (size_t j = 0; j < 4; j++)
line(img, vertices[j], vertices[(j+1)%4], Scalar(0, 255, 0), 2, LINE_AA);
}
// 显示图像
imshow("image", img);
waitKey();
return 0;
}
```
阅读全文