图像轮廓与图像分割修复(opencv3编程入门第八章)第二节 寻找物体的凸包

图像轮廓与图像分割修复(opencv3编程入门第八章)第二节 寻找物体的凸包

凸包

  1. 借用百度百科的解释:凸包(Convex Hull)是一个计算几何(图形学)中的概念。在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,…Xn)的凸组合来构造。在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

“寻找凸包”的库函数

void convexHull(InputArray points,OutputArray hull,bool clockwise = false,bool returnPoints = true)

  • InputArray points: 得到的点集,一般是用图像轮廓函数求得的轮廓点,Mat类型或者std::vector
  • OutputArray hull: 输出的是凸包的二维xy点的坐标值,针对每一个轮廓形成的
  • bool clockwise = false: 表示凸包的方向,顺时针或者逆时针
  • bool returnPoint = true: 表示返回点还是点地址的索引

示例代码1

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	Mat image(600, 600, CV_8UC3);
	RNG& rng = theRNG();

	while(1)
	{
		char key;
		int count = (unsigned)rng % 100 + 3;   //随机生成点的数量
		vector<Point> points(count);

		//随机生成点的坐标
		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[i] = 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);
		key = (char)waitKey();
		if (key == 27)
			break;
	}
	return 0;
}

结果展示:
在这里插入图片描述

示例代码2

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

#define WINDOW_NAME1 "【原始图窗口】"
#define WINDOW_NAME2 "【效果图窗口】"
Mat g_srcImage, g_grayImage;
int g_nThresh = 50;
int g_maxThresh = 255;
RNG g_rng;
Mat srcImage_copy = g_srcImage.clone();
Mat g_thresholdImage_output;
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy;
void on_ThreshChange(int, void*);

int main()
{
	g_srcImage = imread("1.jpg");

	//将原图像转化成灰度图并模糊
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
	blur(g_grayImage, g_grayImage, Size(3, 3));

	namedWindow(WINDOW_NAME1, WINDOW_KEEPRATIO);
	imshow(WINDOW_NAME1, g_srcImage);

	createTrackbar("阈值:", WINDOW_NAME1, &g_nThresh, g_maxThresh, on_ThreshChange);
	on_ThreshChange(0, 0); //调用一次进行初始化

	waitKey(0);
	return 0;
}

void on_ThreshChange(int, void*)
{
	threshold(g_grayImage, g_thresholdImage_output, g_nThresh, 255, THRESH_BINARY);  //二值化
	findContours(g_thresholdImage_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

	//遍历每个轮廓,寻找其凸包
	vector<vector<Point> > hull(g_vContours.size());
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		convexHull(Mat(g_vContours[i]), hull[i]);
	}

	//绘出轮廓及凸包
	Mat drawing = Mat::zeros(g_thresholdImage_output.size(), CV_8UC3);
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
		drawContours(drawing, g_vContours, i, color); //画轮廓
		color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
		drawContours(drawing, hull, i, color);  //画凸包图
	}
	namedWindow(WINDOW_NAME2, WINDOW_KEEPRATIO);
	imshow(WINDOW_NAME2, drawing);
}

结果展示:
在这里插入图片描述
在这里插入图片描述

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值