OpenCV学习笔记(十八):凸包,最小包围区域算子:convexHull(),minAreaRect(),minEnclosingTriangle(),minEnclosingCircle()
1、convexHull()函数
计算出图像点集的凸包,根据图像的轮廓点,通过函数convexhull转化成凸包的点坐标,从而画出图像的凸包。
void convexHull(
InputArray points, // 输入的点集,一般是用图像轮廓函数求得的轮廓点
OutputArray hull, // 输出的是凸包的二维xy点的坐标值,针对每一个轮廓形成的。
bool clockwise = false, // 表示凸包的方向,true顺时针 flase 逆时针
bool returnPoints = true // true表示返回点,false返回点地址的索引值
==returnPoints 标识符==
当输出数组"hull" 是std::vector时,忽略该标志,输出取决于向量的类型:
std::vector<int>表示 returnPoints=false, 返回索引值
std::vector<Point>表示 returnPoints=true。返回点
)
2、boundingRect()函数
该函数计算并返回指定点集的最小右上界矩形。
Rect cv::boundingRect(InputArray points)
3、minAreaRect()函数
对给定的2D 点集,寻找可旋转的最小面积包围矩形
RotatedRect cv::minAreaRect(InputArray points)
4、minEnclosingCircle()函数
找到包围2D点集的最小面积的圆。
void cv::minEnclosingCircle(
InputArray points,
Point2f & center,
float & radius
)
5、minEnclosingTriangle()函数
找到一个包含2D点集的最小面积三角形,并返回其面积。
double cv::minEnclosingTriangle(
InputArray points,
OutputArray triangle
)
6、minEnclosingTriangle()函数
在一组二维点周围拟合一个椭圆。
RotatedRect cv::fitEllipse(
InputArray points
)
7、approxPolyDP()函数
以指定的精度近似生成多边形曲线。
函数逼近一条曲线或另一条曲线/顶点较少的多边形,使它们之间的距离小于或等于指定的精度。它使用Douglas-Peucker算法
void approxPolyDP(
InputArray curve, // 输入的点集(存储在std::vector或Mat中的二维点的输入向量)
OutputArray approxCurve, // 输出的点集,当前点集是能最小包容指定点集的。draw出来即是一个多边形;
double epsilon, // 指定的精度,也即是原始曲线与近似曲线之间的最大距离。
bool closed // 若为true,则说明近似曲线是闭合的,它的首位都是相连,反之,若为false,则断开。
);
8、示例一: (凸包)
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{// 1、初始化变量和随机值Mat image(600, 600, CV_8UC3);RNG& rng = theRNG(); // 生成单个均匀分布的随机数或随机数数组。// 2、循环,按下ESC,Q,q键程序退出,否则有键按下便一直更新while(1){// 2.1 参数初始化char key;//键值int count = (unsigned)rng%100 + 3;//随机生成点的数量(最少3个点)vector<Point> points; //点值// 2.2 随机生成点坐标for(int i = 0; i < count; i++ ){Point point;point.x = rng.uniform(image.cols/4, image.cols*3/4); // 一定范围内点坐标point.y = rng.uniform(image.rows/4, image.rows*3/4);points.push_back(point);}// 2.3 检测凸包// 操作方向为 顺市时针vector<Point> hull; // 输出凸包点集 坐标索引值convexHull(Mat(points), hull, true);// 2.4 绘制出随机颜色的点image = Scalar::all(0); // 背景清零(设为黑色)for(int i = 0; i < count; i++ )// 绘制点circle(image, points[i], 3, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), CV_FILLED, CV_AA);// // 根据凸包点集的索引 绘制凸包线
// int hullcount = (int)hull.size(); //凸包的边数(点数)
// for(int i = 0; i < hullcount; i++ )
// {
// Point point = points[hull[i]]; // 第一个点坐标 // 方式一:从最后一个点为起点绘制
Point point_last = points[hull[hullcount-1]]; //连接凸包边的坐标点(hull[hullcount-1]:凸包最后一个点 索引值)
line(image, point_last, point, Scalar(255, 255, 255), 1, CV_AA);
point_last = point;// // 方式二:第一个点为起点绘制
// Point point1= points[hull[(i+1)%hullcount]]; // 第二个点
// line(image, point, point1, Scalar(255, 255, 255), 1, CV_AA);
// }// 2.5 根据凸包点集 绘制凸包线int hullcount = (int)hull.size();for(int i = 0; i < hullcount; i++ ){Point point = hull[i]; // 第一个点坐标Point point1= hull[(i+1)%hullcount]; // 第二个点line(image, point, point1, Scalar(255, 255, 255), 1, CV_AA);}// 2.6 显示效果图imshow("凸包检测示例", image);//按下ESC,Q,或者q,程序退出key = (char)waitKey();if( key == 27 || key == 'q' || key == 'Q' )break;}waitKey(0);return 0;
}
9、示例二: (最小包围区域)
这个程序演示了如何使用函数minAreaRect() minEnclosingTriangle() minEnclosingCircle()找到一组点的最小包围矩形、三角形、圆形。随机点生成,然后封闭。按ESC,'Q’或’q’退出和任何其他键重新生成点集。
#include <opencv2/opencv.hpp>
#include<vector>using namespace cv;
using namespace std;//using std::vector;int main()
{// 1、创建背景图片Mat img(500, 500, CV_8UC3,Scalar::all(0));// 2、返回默认的随机数生成器RNG& rng = theRNG(); for(;;){// 随机生成一些点// 首先就是随机生成点的总数量int i, count = rng.uniform(1, 101);vector<Point> points;// 3、生成一组随机的点for( i = 0; i < count; i++ ){Point pt;pt.x = rng.uniform(img.cols/4, img.cols*3/4);pt.y = rng.uniform(img.rows/4, img.rows*3/4);points.push_back(pt);}// 4、找出随机点所在区域的最小包围矩形RotatedRect box = minAreaRect(points); // 获得旋转矩形 box// 将box变量中存储的坐标值放到 fourPoint的数组中Point2f fourPoint[4];box.points(fourPoint);// 5、找出最小包围三角形vector<Point2f> triangle;minEnclosingTriangle(points, triangle);// 6、找出最小包围圆的圆心center和半径radiusPoint2f center;float radius = 0;minEnclosingCircle(points, center, radius);///7、绘制所生产的随机点for( i = 0; i < count; i++ )circle( img, points[i], 3, Scalar(0, 0, 255), FILLED, LINE_AA );// 8、绘制最小包围矩形for( i = 0; i < 4; i++ )line(img, fourPoint[i], fourPoint[(i+1)%4], Scalar(0, 255, 0), 1, LINE_AA);///9、绘制最小包围三角形for( i = 0; i < 3; i++ )line(img, triangle[i], triangle[(i+1)%3], Scalar(255, 255, 0), 1, LINE_AA);// 10、绘制最小包围圆circle(img, center, cvRound(radius), Scalar(0, 255, 255), 1, LINE_AA);// 11、显示imshow( "Rectangle, triangle & circle", img );// 键盘命令输入char key = (char)waitKey();if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'break;elseimg = Scalar::all(0); // 背景清空}return 0;
}
结果: