花老湿学习OpenCV:凸包检测

凸包:

凸包(Convex Hull)是一个计算几何(图形学)中常见的概念。简单来说,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它是能包含点集中所有点的。理解物体形状或轮廓的一种比较有用的方法便是计算一个物体的凸包,然后计算其凸缺陷(convexity defects)。

判断:如果在集合A内连接任意两个点的直线段都在A的内部,则称集合A是凸形的。

直观的理解,就是一个多边型,没有凹的地方,如图所示:

名词解释:

如上图所示,黑色的轮廓线为convexity hull(凸包), 而convexity hull与手掌之间的部分为convexity defects(凸包缺陷). 每个convexity defect区域有四个特征量:起始点(startPoint),结束点(endPoint),距离convexity hull最远点(farPoint),最远点到convexity hull的距离(depth)。

凸包检测原理:

思路:Graham扫描的思想和Jarris步进法类似,也是先找到凸包上的一个点,然后从那个点开始按逆时针方向逐个找凸包上的点。

操作步骤大概可分为两步

第一步:排序

第二步:扫描

步骤:

1.把所有点放在二维自然直角坐标系中(注意与图片像素坐标系区分),则纵坐标最小的点一定是凸包上的 
点,如图中的P0。

2.那么以P0作为坐标参考点,如上图所示:
计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前
面。例如上图得到的结果为 P1,P2,P3,P4,P5,P6,P7,P8。我们由定义可以知道,结果中第一个点 P1 
和最后一个点 P8 一定是凸包上的点。 
 
3.以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在栈里面,并令P2为当前点.

4.根据栈顶的前两个点作出有向直线,记PX-1->PX ,看当前点是在有向直线 L 的右边还是左边。
如果在直线的右边就执行步骤5;如果在直线上,或者在直线的左边就执行步骤6。

5.栈顶的那个元素不是凸包上的点,把栈顶元素出栈,当前点不变,执行步骤4。 

6.当前点是凸包上的点,把它压入栈,执行步骤7。

7.检查当前的点是不是步骤3那个结果的最后一个元素:当前点是最后一个元素的话就结束,如果不是的话就将下一个点作为新的当前点,返回步骤4。

 动图过程如下:


静态求解过程如下:

 

API:

凸包检测:

 

凸包缺陷:

 

代码示例:

1.程序会首先根据滑动块位置生成坐标值随机的彩色点,然后利用convexHull,对由这些点链接起来的图形求凸包。

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int pointCount = 50;
void ConvexHull_demo(int pos, void* userdata);

int main()
{
	namedWindow("Convex", WINDOW_AUTOSIZE);
	createTrackbar("pointCount", "Convex", &pointCount, 200, ConvexHull_demo);
	ConvexHull_demo(pointCount, 0);
	imshow("Convex", img);
	waitKey(0);
}


void ConvexHull_demo(int pos, void* userdata)
{
	Mat img=Mat::zeros(500,500,CV_8UC3);
	RNG rng(getTickCount());
	//随机生成目标点并绘制
	vector<Point> points;
	for (int i = 0; i < pos; i++)
	{
		Point point;
		point.x = rng.uniform(cvRound(img.cols / 4), cvRound(img.cols * 3 / 4));
		point.y = rng.uniform(cvRound(img.rows / 4), cvRound(img.rows * 3 / 4));
		circle(img, point, 2, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), FILLED, LINE_AA);
		points.push_back(point);
	}
	//凸包检测
	vector<Point> hull;
	convexHull(points, hull, false);
	//凸包绘制
	for (int i = 0; i < hull.size(); i++)
	{
		
			line(img, hull[i], hull[(i + 1)%hull.size()], Scalar(255, 0, 0), 2, LINE_AA);
			
	}
	imshow("Convex", img);
}


效果展示: 

 

2.首先对博主的手部图像进行轮廓检测,然后以轮廓中的点作为点集,找到其凸包。

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int thresholdval = 127;
int thresholdmax = 255;

int mode = 3;
void Demo_Contours(int pos, void* userdata);

Mat blursrc;
int main()
{
	//待检测图像
	Mat src = imread("F:\\visual studio\\Image\\hand4.jpg");
	if (src.empty())
	{
		cout << "Can't load the image" << endl;
		return -1;
	}
	resize(src, src, Size(), 0.5, 0.5);
	imshow("src", src);
	//转化为灰度图
	Mat graysrc;
	cvtColor(src, graysrc, COLOR_BGR2GRAY);

	//高斯模糊
	GaussianBlur(graysrc, blursrc, Size(5, 5), 3, 3);

	namedWindow("dst", WINDOW_AUTOSIZE);
	createTrackbar("Threshold", "dst", &thresholdval, thresholdmax, Demo_Contours);
	createTrackbar("mode", "dst", &mode, 3, Demo_Contours);

	Demo_Contours(0, 0);
	waitKey(0);

}

void Demo_Contours(int pos, void* userdata)
{
	//阈值化
	Mat bin;
	threshold(~blursrc, bin, thresholdval, thresholdmax, CV_THRESH_BINARY);
	imshow("bin", bin);
	
	//查找轮廓
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(bin, contours, hierarchy, mode, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
		
	RNG rng(getTickCount());
	Mat dst = Mat::zeros(blursrc.size(), CV_8UC3);
	vector<vector<Point>> hull(contours.size());
	
	//遍历每个轮廓,寻找其凸包并绘制
	for (int i = 0; i < contours.size(); i++)
	{
		convexHull(contours[i], hull[i], false);
		Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, contours, i, color, 2, LINE_AA, hierarchy);
	    color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, hull, i, color, 2, LINE_AA);
	}
	imshow("dst", dst);

}

效果如下:

 

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
凸包检测是计算机视觉中常用的图像处理技术,它用于寻找二维形状的凸包轮廓。下面是关于凸包检测原理、作用和应用的简要介绍: 1. 原理凸包是指包围一组点集的最小凸多边形或凸壳。凸包检测原理是通过寻找包含所有点的最小凸多边形来确定凸包轮廓。 2. 作用: 凸包检测在计算机视觉和图像处理中有多种作用,包括: - 物体识别和分类:通过提取物体的凸包轮廓,可以用于物体的识别和分类任务。 - 物体轮廓分析:凸包检测可以帮助分析物体的形状、边界和几何特征。 - 图像分割:基于凸包的轮廓提取可以用于图像分割,将图像中的不同物体或域分离出来。 - 缺陷检测:通过比较实际形状和其凸包之间的差异,可以检测出物体表面的缺陷或异常。 3. 应用: 凸包检测在各种计算机视觉和图像处理应用中被广泛使用,包括但不限于以下领域: - 目标检测和识别:凸包可用于提取目标的外形特征,并进行分类和识别。 - 图像分析和处理:凸包检测可用于分割图像、提取边缘、计算形状特征等。 - 视觉导航和机器人技术:凸包检测可以帮助机器人或自动导航系统识别和定位目标物体。 - 缺陷检测和质量控制:通过凸包检测可以检测产品的缺陷、判定质量。 总之,凸包检测是一种有用的图像处理技术,可以在许多计算机视觉应用中发挥重要作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值