加强版 第六节 图像轮廓几何属性分析
轮廓面积与周长
最大/最小外接矩形
boundingrect
boundingRect主要用于计算轮廓(contour)的边界矩形。轮廓通常是由一系列的点构成的曲线,通过这个函数可以得到一个能够刚好包围这个轮廓的最小矩形。这个矩形是一个直立(非旋转)的矩形。
它的语法一般是cv2.boundingRect(array),参数array通常是一个轮廓点的数组(例如通过findContours函数得到的轮廓)。返回值是一个包含四个值的元组,分别是矩形左上角的x坐标、y坐标,以及矩形的宽度和高度((x, y, w, h))。
例如,在目标检测或者物体识别场景中,当你已经通过边缘检测等方式获得了物体的轮廓后,使用boundingRect可以快速确定物体在图像中的位置和大小范围,方便后续进一步处理,比如提取物体所在区域的图像块等。
RotatedRect
1. 定义与用途
• 在OpenCV中,RotatedRect(旋转矩形)是一个用于表示旋转后的矩形的数据结构。与boundingRect返回的非旋转矩形不同,RotatedRect可以更好地贴合具有一定角度的物体轮廓,尤其在处理倾斜物体时非常有用。
2. 结构成员
• 它主要包含三个成员:中心坐标(center),表示旋转矩形的中心位置,是一个Point2f类型(包含x和y坐标);尺寸(size),是一个Size2f类型,用于表示矩形的宽度和高度;旋转角度(angle),是一个浮点数,表示矩形相对于水平方向的旋转角度,以逆时针方向为正。
3. 获取旋转矩形的方式
• 例如,使用minAreaRect函数可以获取轮廓的最小旋转包围矩形。假设contours是通过findContours函数得到的轮廓集合,对于其中的一个轮廓contours[i],可以这样获取其旋转包围矩形:
RotatedRect rotated_rect = minAreaRect(contours[i]);
4. 绘制旋转矩形
• 要绘制旋转矩形,可以使用Point2f数组来获取矩形的四个顶点,然后用line函数逐个连接顶点来绘制。以下是一个简单的示例代码片段:
RotatedRect rotated_rect = minAreaRect(contours[i]);
Point2f vertices[4];
rotated_rect.points(vertices);
for (int j = 0; j < 4; j++)
{
line(src, vertices[j], vertices[(j + 1) % 4], Scalar(0, 255, 0), 2);
}
• 这里src是目标图像,Scalar(0, 255, 0)是绘制线条的颜色(绿色),2是线条的宽度。points函数用于获取旋转矩形的四个顶点,然后通过循环连接这些顶点来绘制旋转矩形。
ellipse
在 OpenCV 中,ellipse函数用于绘制椭圆。
一、函数语法
void ellipse(InputOutputArray img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
二、参数解释
1. img:要在其上绘制椭圆的图像。
2. center:椭圆的中心坐标。
3. axes:椭圆的长轴和短轴长度,以Size(w, h)的形式给出,其中w是长轴的一半长度,h是短轴的一半长度。
4. angle:椭圆的旋转角度,以度为单位。
5. startAngle:椭圆弧的起始角度,以度为单位。
6. endAngle:椭圆弧的结束角度,以度为单位。
7. color:椭圆的颜色。
8. thickness:椭圆轮廓的线宽。如果为负数,则绘制实心椭圆。
9. lineType:线条类型,如LINE_8、LINE_4等。
10. shift:坐标点的小数位数。
首先计算每个关键像素点的面积和周长方便后续的操作
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat sqw, swe, ser;
Mat src = imread("C:/newword/image/5.png");
if (src.empty()) {
printf("no");
return -1;
}
namedWindow("abc", WINDOW_AUTOSIZE);
GaussianBlur(src,sqw,Size(3,3),0);
cvtColor(sqw, swe, COLOR_BGR2GRAY);
threshold(swe, ser, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("abc", ser);
vector<vector<Point>>sky;
vector<Vec4i>sea;
findContours(ser, sky, sea, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
for (size_t t = 0; t < sky.size(); t++) {
double are = contourArea(sky[t]);计算每个轮廓的面积
double len = arcLength(sky[t],true);计算每个轮廓的周长,是否为封闭图形
if (are > 150 || len < 40)continue;
printf("are:=%.2f,len:=%.2f\n",are, len);
drawContours(src, sky, -1, Scalar(0, 0, 255), 2, 8);
}
imshow("abcd", src);
waitKey(0);
return 0;
}
绘制最小直立外接矩形
double are = contourArea(sky[t]);
double len = arcLength(sky[t],true);
if (are < 50 || len < 40)continue;
printf("are:=%.2f,len:=%.2f\n",are, len);
Rect box = boundingRect(sky[t]);
rectangle(src, box, Scalar(0, 255, 0), 2, 8,0);
绘制外接(重要的是rotaedrect这个函数)
RotatedRect min_area = minAreaRect(sky[t]);
ellipse(src, min_area, Scalar(0, 0, 255), 2, 8);
之后就是带有角度的最小外接矩形
RotatedRect min_area = minAreaRect(sky[t]);
//ellipse(src, min_area, Scalar(0, 0, 255), 2, 8);
Point2f pts[4];//四个点的格式为Point2f
min_area.points(pts);
for (int i = 0; i < 4; i++) {
line(src, pts[i], pts[(i + 1) % 4], Scalar(0, 0, 255), 2, 8);
}