- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
1.功能描述
该函数cv::convexHull用于寻找一组二维点集的凸包,采用的是Sklansky算法[242],当前实现中具有O(N logN)的时间复杂度。
1.1什么是凸包?
让我们先从术语的两部分来理解——“凸”和“包”。
一个“凸”对象是指没有内角大于180度的对象。非凸的对象称为非凸的或凹的,下图展示了凸对象和非凸对象的例子。
包指的是物体的外部或轮廓。
因此,一组点或形状的凸包是一个紧贴着这些点或形状的最紧凑的凸边界。如图2所示,两个黑色形状的凸包用红色线条描绘。对于凸对象,其凸包就是其边界本身;而对于凹形状,凸包则是一个最紧致地包围它的凸边界。
2.函数原型
void cv::convexHull (
InputArray points,
OutputArray hull,
bool clockwise = false,
bool returnPoints = true
)
3.参数
- 参数 points 输入的二维点集,存储在std::vector或Mat中.
- 参数 hull 输出的凸包。它可以是一个索引的整数向量或点的向量。在第一种情况下,凸包元素是原数组中凸包点的基于0的索引(因为凸 包点的集合是原点集的子集)。在第二种情况下,凸包元素即凸包点本身.
- 参数 clockwise 方向标志。如果该标志为真,输出的凸包按顺时针方向排列。否则,它按照逆时针方向排列。所采用的坐标系统其X轴指向右侧,Y轴指向上方。.
- 参数 returnPoints 操作标志。当输入为矩阵且该标志为真时,函数返回凸包的点坐标。否则,它返回凸包点在原点集中的索引。如果输出数组是std::vector,该标志将被忽略,输出类型依据vector的实际类型而定:std::vector意味着returnPoints=false(返回索引),std::vector意味着returnPoints=true(返回点坐标)。
注意
points(输入点集)和hull(输出凸包)应该是不同的数组,不支持原地处理。这意味着cv::convexHull函数不会直接修改输入的点集数 组来存储结果,你需要提供一个独立的变量来接收计算出的凸包信息。
4.代码示例
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
Mat img( 500, 500, CV_8UC3 );
RNG& rng = theRNG();
for ( ;; )
{
int i, count = ( unsigned )rng % 100 + 1;
vector< Point > points;
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 );
}
vector< Point > hull;
convexHull( points, hull, true );
img = Scalar::all( 0 );
for ( i = 0; i < count; i++ )
circle( img, points[ i ], 3, Scalar( 0, 0, 255 ), FILLED, LINE_AA );
imshow( "original", img );
polylines( img, hull, true, Scalar( 0, 255, 0 ), 1, LINE_AA );
imshow( "hull", img );
char key = ( char )waitKey();
if ( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
break;
}
return 0;
}
5.运行结果
根据随机生成的点,然后根据这些点去进行运算,再把这些凸包点连接起来,如下图所示: