凸包检测
有时物体的形状太过复杂,用多边形逼近处理起来依然较为复杂,例如人手、海星等
对于形状较为复杂的物体,可以利用凸包近似表示,凸包是图形学中常见的概念
将二维平面上的点集最外层的点连接起来构成的凸包多边形称为凸包
OpenCV4提供了用于物体检测的convexHull()函数
convexHull()函数原型:
void convexHull(InputArray points,
OutputArray hull,
bool clockwise = false,
bool returnPoints = true
)
- points:输入的二维点集或轮廓坐标
- hull:输出凸包的顶点
- clockwise:方向标志,当参数为true时,凸包顺序为顺时针方向;当参数为false时,凸包顺序为逆时针方向
- returnPoints:输出数据的类型标志,当参数为true时,第二个参数输出结果是凸包顶点的坐标
当参数为false时,第二个参数输出结果是凸包顶点的索引
该函数用于寻找二维点集或者轮廓的凸包
第一个参数是输入的二维点集或者轮廓坐标,数据类型是vector< Point >或者Mat
第二个参数是凸包顶点的坐标或者索引,数据类型是vector< Point >或者vector< int >
第三个参数是凸包方向的标志,当参数为true时,凸包顺序为顺时针方向;当参数为false时,凸包顺序为逆时针方向
最后一个参数是输出数据的类型标志,当参数为true时,第二个参数输出结果是凸包顶点的坐标,数据类型是vector< Point >或者Mat
当参数为false时,第二个参数输出结果是凸包顶点的索引,数据类型是vector< int >
示例程序:首先对图像二值化,并利用开运算消除二值化过程中产生的较小区域,之后寻找图像的轮廓,最后对图像中每个轮廓进行
凸包检测,并绘制凸包的顶点和每一条边
示例:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("E:\\CLion\\opencv_xin\\SG\\SG_Approx.png");
if (img.empty())
{
cout << "error" << endl;
return -1;
}
imshow("img",img);
Mat gray,binary;
cvtColor(img,gray,COLOR_BGR2GRAY); //转化成灰度图
GaussianBlur(gray,gray,Size(9,9),2,2); //平滑滤波
threshold(gray,binary,50,255,THRESH_BINARY);
//开运算消除细小区域
Mat k = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));
morphologyEx(binary,binary,MORPH_OPEN,k);
imshow("binary",binary);
//轮廓发现
vector<vector<Point>> contours; //轮廓
vector<Vec4i> hierarchy; //存放轮廓结构变量
findContours(binary,contours,hierarchy,0,2,Point());
for (int i = 0; i < contours.size(); ++i)
{
//计算凸包
vector<Point> hull;
convexHull(contours[i],hull);
//绘制凸包
for (int j = 0; j < hull.size(); ++j)
{
//绘制凸包顶点
circle(img,hull[j],4,Scalar(255,0,0),2,8,0);
//连接凸包
if (j == hull.size() - 1)
{
line(img,hull[j],hull[0],Scalar(0,0,255),2,8,0);
break;
}
line(img,hull[j],hull[j+1],Scalar(0,0,255),2,8,0);
}
}
imshow("hull",img);
waitKey(0);
return 0;
}