图像轮廓与图像分隔修复(3):寻找物体的凸包
一,凸包;
二,寻找凸包:convexHull()函数;
三,基础示例程序:凸包检测基础;
一,凸包
凸包(Convex Hull)是一个计算几何(图形学)中常见的概念。简单来说,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它是能包含点集中所有点的。理解物体形状或轮廓的一种比较有用的方法便是计算一个物体的凸包,然后计算其凸缺陷(convexity defects)。很多复杂物体的特性能很好地被这种缺陷表现出来。
如图8.9所示,我们用人手图来举例说明凸缺陷这一概念。手周围深色的线描画出了凸包,A到H被标出的区域是凸包的各个“缺陷”。正如看到的,这些凸度缺陷提供了手以及手状态的特征表现的方法。
新版OpenCV中,convexHull 函数用于寻找图像点集中的凸包。
二,寻找 凸包 :convexHull()函数
上文已经提到过,convexHull()函数用于寻找图像点集中的凸包,其原型声明如下。
C++: void convexHull (InputArray points,outputArray hull, boolclockwise=false,bool returnPoints=true )
·第一个参数,InputArray类型的points,输入的二维点集,可以填Mat类型或者std:vector。
·第二个参数,OutputArray类型的 hull,输出参数,函数调用后找到的凸包。
·第三个参数,bool类型的clockwise,操作方向标识符。当此标识符为真时,输出的凸包为顺时针方向。否则,就为逆时针方向。并且是假定坐标系的x轴指向右,y轴指向上方。
·第四个参数,bool类型的returnPoints,操作标志符,默认值true。当标志符为真时,函数返回各凸包的各个点。否则,它返回凸包各点的指数。当输出数组是std::vector时,此标志被忽略。
三,基础示例程序:凸包检测基础
为了理解凸包检测的运用方法,下面放出一个完整的示例程序。程序中会首先随机生成3~103个坐标值随机的彩色点,然后利用convexHull,对由这些点链接起来的图形求凸包。
代码如下:
#include <opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
cv::utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//控制台不在输出日志文件
//初始化变量和随机值
Mat image(600, 600, CV_8UC3);
RNG& rng = theRNG();
//循环,按下ESC,Q,q键程序退出,否则有键按下便一直更新
while (1)
{
//参数初始化
char key; //键值
int count = (unsigned)rng % 100 + 3; //随机生成点的数量
vector<Point> points; //点值
//随机生成点坐标
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);
}
//检测凸包
vector<int> hull;
convexHull(Mat(points), hull, true);
//绘制出随机颜色的点
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)), FILLED, LINE_AA);
}
//准备参数
int hullcount = (int)hull.size(); //凸包的边数
Point point0 = points[hull[hullcount - 1]]; //连接凸包边的坐标点
//绘制凸包的边
for (int i = 0; i < hullcount; i++)
{
Point point = points[hull[i]];
line(image, point0, point, Scalar(255, 255, 255), 2, LINE_AA);
point0 = point;
}
imshow("凸包检测示例", image);
//按下ESC,Q或q,程序退出
key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q')
break;
}
return 0;
}
运行结果:
等等。