轮廓的基本属性
轮廓的基本属性
面积
简介
- 轮廓面积是指每个轮廓中所有的像素点围成区域的面积,单位为像素
- 通过轮廓面积的大小可以进一步分析每个轮廓隐含的信息,例如通过轮廓面积区分物体大小、识别不同的物体等
API
OpenCV 4 提供了contourArea()
函数用于统计轮廓像素点围成区域的面积
double cv::contourArea(InputArray contour, bool oriented = false)
- contour:轮廓的像素点,数据类型为 vector<Point> 或者Mat
- oriented:区域面积是否具有方向性的标志,true 表示面积具有方向性,false 表示面积不具有方向性,默认为false
- 当参数为true时,表示统计的面积具有方向性,轮廓顶点顺时针给出和逆时针给出时统计的面积互为相反数;当参数取值为false时,表示统计的面积不具有方向性,输出轮廓面积的绝对值
补:相邻的两个像素点之间逐一相连构成的多边形区域即为轮廓面积的统计区域。连续的3个像素点之间的连线有可能在同一条直线上,因此,为了减少输入轮廓像素点的数目,可以只输入轮廓的顶点像素点,例如一个三角形的轮廓,轮廓中可能具有每一条边上的所有像素点,但是,在统计面积时,可以只输入三角形的3个顶点。
示例代码:
在该程序中,给出一个直角三角形轮廓的3个顶点,以及斜边的中点,统计出的轮廓面积与三角形的面积相等
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
// 用4个点表示三角形轮廓
vector<Point> contour;
contour.push_back(Point2f(0, 0));
contour.push_back(Point2f(10, 0));
contour.push_back(Point2f(10, 10));
contour.push_back(Point2f(5, 5));
double area = contourArea(contour);
cout << "area = " << area << endl;
Mat_<Vec3b> img = imread("/home/kslas/OpenCV/erode.png");
Mat_<uchar> gray;
cvtColor(img, gray, COLOR_BGR2GRAY); // 转化成灰度图
GaussianBlur(gray, gray, Size(9, 9), 2, 2); // 平滑滤波
Mat_<uchar> binary;
threshold(gray, binary, 170, 255, THRESH_BINARY | THRESH_OTSU); // 自适应二值化
vector<vector<Point>> contours; // 轮廓
vector<Vec4i> hierarchy; // 存放轮廓结构变量
findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
double area1 = contourArea(contours[i]);
cout << "第" << i << "轮廓面积" << area1 << endl;
}
return 0;
}
运行结果:
周长
简介
- 虽然轮廓的周长无法直接反映轮廓区域的大小和形状,但是可以与轮廓面积结合得到关于轮廓面积区域的更多信息,例如,当某个区域的面积与周长的平方数的比值为 1 : 16 时,该区域为正方形
API
OpenCV 4 提供了用于检测轮廓周长或者曲线长度的arcLength()
函数
double cv::arcLength(InputArray curve, bool closed)
- curve:轮廓或者曲线的二维像素点,数据类型为 vector<Point> 或 Mat
- closed:轮廓或者曲线是否闭合的标志,true表示闭合
补:该函数统计的长度是轮廓或者曲线相邻两个像素点之间连线的距离。例如,在计算三角形3个顶点A、B和C构成的轮廓长度时,若该函数的第二个参数为true,那么统计的长度是三角形3条边AB、BC、和CA的长度之和;若该参数为false,那么统计的长度是由A到C这3个点之间的依次连线的距离长度之和,即AB和BC的长度之和
示例代码:
在该程序中,给出一个直角三角形轮廓的3个顶点,以及斜边的中点,分别利用arcLength()
函数统计轮廓闭合情况下的长度和非闭合情况下的长度
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
// 用4个点表示三角形轮廓
vector<Point> contour;
contour.push_back(Point2f(0, 0));
contour.push_back(Point2f(10, 0));
contour.push_back(Point2f(10, 10));
contour.push_back(Point2f(5, 5));
double length0 = arcLength(contour, true);
double lenght1 = arcLength(contour, false);
cout << "length0 = " << length0 << endl;
cout << "length1 = " << lenght1 << endl;
Mat_<Vec3b> img = imread("/home/kslas/OpenCV/erode.png");
Mat_<uchar> gray, binary;
cvtColor(img, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(9, 9), 2, 2);
threshold(gray, binary, 170, 255, THRESH_BINARY | THRESH_OTSU);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
double length2 = arcLength(contours[i], true);
cout << "第" << i << "个轮廓长度 = " << length2 << endl;
}
return 0;
}
运行结果: