轮廓面积是轮廓重要的统计特性之一,通过轮廓面积的大小可以进一步分析每个轮廓隐含的信息,例如通过轮廓面积区分物体大小识别不同的物体。轮廓面积是指每个轮廓中所有的像素点围成区域的面积,单位为像素。OpenCV 4提供了检测轮廓面积的**contourArea()**函数,该函数的函数原型在代码清单7-15中给出。
double cv::contourArea(InputArray contour,bool oriented = false )
该函数用于统计轮廓像素点围成区域的面积,函数的返回值是统计轮廓面积的结果,数据类型为double。函数第一个参数表示轮廓的像素点,数据类型为vector或者Mat,相邻的两个像素点之间逐一相连构成的多边形区域即为轮廓面积的统计区域。连续的三个像素点之间的连线有可能在同一条直线上,因此为了减少输入轮廓像素点的数目,可以只输入轮廓的顶点像素点,例如一个三角形的轮廓,轮廓中可能具有每一条边上的所有像素点,但是在统计面积时可以只输入三角形的三个顶点。函数第二个参数是区域面积是否具有方向的标志,参数为true时表示统计的面积具有方向性,轮廓顶点顺时针给出和逆时针给出时统计的面积互为相反数;参数为false时表示统计的面积不具有方向性,输出轮廓面积的绝对值。
为了了解该函数的使用方法,在代码清单7-16中给出了统计轮廓面积的示例程序。程序中给出一个直角三角形轮廓的三个顶点以及斜边的中点,统计出的轮廓面积与三角形的面积相等,同时统计图7-16中每个轮廓的面积,程序的运行结果在图7-18给出。
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
system("color F0"); //更改输出界面颜色
//用四个点表示三角形轮廓
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 img = imread("coins.jpg");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
imshow("原图", img);
Mat 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, Point());
//输出轮廓面积
for (int t = 0; t < contours.size(); t++)
{
double area1 = contourArea(contours[t]);
cout << "第" << t << "轮廓面积=" << area1 << endl;
}
return 0;
}
轮廓的周长也是轮廓重要的统计特性之一,轮廓的周长虽然无法直接反应轮廓区域的大小和形状,但是可以与轮廓面积结合得到关于轮廓区域的更多信息,例如某个区域的面积与周长平方的比值为十六分之一时该区域为正方形。OpenCV 4提供了用于检测轮廓周长或者曲线长度的**arcLength()**函数,该函数的函数原型在代码清单7-17中给出。
double cv::arcLength(InputArray curve,bool closed )
该函数能够统计轮廓或者曲线的长度,函数返回值为统计长度,单位为像素,数据类型为double。函数的第一个参数是轮廓或者曲线的2D像素点,数据类型为vector或者Mat。函数的第二个参数是轮廓或者曲线是否闭合的标志,true表示闭合。
函数统计的长度是轮廓或者曲线相邻两个像素点之间连线的距离,例如计算三角形三个顶点A、B和C构成的轮廓长度时,并且函数第二个参数为true时,统计的长度是三角形三个边AB、BC和CA的长度之和;当参数为false时,统计的长度是由A到C三个点之间依次连线的距离长度之和,即AB和BC的长度之和。
为了了解该函数的使用方法,在代码清单7-18中给出统计轮廓长度的示例程序。程序中给出一个直角三角形轮廓的三个顶点以及斜边的中点,分别利用arcLength()函数统计轮廓闭合情况下的尺度和非闭合情况下的长度,同时统计图7-16中每个轮廓的长度,程序的运行结果在图7-19给出。
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
system("color F0"); //更改输出界面颜色
//用四个点表示三角形轮廓
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 length1 = arcLength(contour, false);
cout << "length0 =" << length0 << endl;
cout << "length1 =" << length1 << endl;
Mat img = imread("coins.jpg");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
imshow("原图", img);
Mat 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, Point());
//输出轮廓长度
for (int t = 0; t < contours.size(); t++)
{
double length2 = arcLength(contours[t], true);
cout << "第" << t << "个轮廓长度=" << length2 << endl;
}
return 0;
}