opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包
查找并绘制轮廓
寻找轮廓(findContours)函数




绘制轮廓(drawContours()函数)



基础实例程序:轮廓查找
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	// 【1】载入原始图,且必须以二值图模式载入
	Mat srcImage = imread("1.jpg", 0);
	imshow("原始图", srcImage);
	//【2】初始化结果图
	Mat dstImage = Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3);
	//【3】srcImage取大于阈值119的那部分
	srcImage = srcImage > 119;
	imshow("取阈值后的原始图", srcImage);
	//【4】定义轮廓和层次结构
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	//【5】查找轮廓
	//此句代码的OpenCV3版为:
	findContours(srcImage, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
	// 【6】遍历所有顶层的轮廓, 以随机颜色绘制出每个连接组件颜色
	int index = 0;
	for (; index >= 0; index = hierarchy[index][0])
	{
		Scalar color(rand() & 255, rand() & 255, rand() & 255);
		drawContours(dstImage, contours, index, color, FILLED, 8, hierarchy);
	}
	//【7】显示最后的轮廓图
	imshow("轮廓图", dstImage);
	waitKey(0);
}
综合实例程序(加blur,canny和滑动条):
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
//-----------------------------------【宏定义部分】--------------------------------------------
//		描述:定义一些辅助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME1 "【原始图窗口】"			//为窗口标题定义的宏
#define WINDOW_NAME2 "【轮廓图】"					//为窗口标题定义的宏 
//-----------------------------------【全局变量声明部分】--------------------------------------
//		描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage;
Mat g_grayImage;
int g_nThresh = 80;
int g_nThresh_max = 255;
RNG g_rng(12345);
Mat g_cannyMat_output;
vector<vector<Point>> g_vContours;
vector<Vec4i> g_vHierarchy;
//-----------------------------------【全局函数声明部分】--------------------------------------
//		描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
static void ShowHelpText();
void on_ThreshChange(int, void*);
//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	//【0】改变console字体颜色
	system("color 1F");
	//【0】显示欢迎和帮助文字
	ShowHelpText();
	// 加载源图像
	g_srcImage = imread("1.jpg", 1);
	if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }
	// 转成灰度并模糊化降噪
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
	blur(g_grayImage, g_grayImage, Size(3, 3));
	// 创建窗口
	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
	imshow(WINDOW_NAME1, g_srcImage);
	//创建滚动条并初始化
	createTrackbar("canny阈值", WINDOW_NAME1, &g_nThresh, g_nThresh_max, on_ThreshChange);
	on_ThreshChange(0, 0);
	waitKey(0);
	return(0);
}
//-----------------------------------【on_ThreshChange( )函数】------------------------------
//      描述:回调函数
//----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void*)
{
	// 用Canny算子检测边缘
	Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh * 2, 3);
	// 寻找轮廓
	findContours(g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	// 绘出轮廓
	Mat drawing = Mat::zeros(g_cannyMat_output.size(), CV_8UC3);
	for (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, 2, 8, g_vHierarchy, 0, Point());
	}
	// 显示效果图
	imshow(WINDOW_NAME2, drawing);
}
//-----------------------------------【ShowHelpText( )函数】----------------------------------
//      描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
	printf("\n\n  ----------------------------------------------------------------------------\n");
	//输出一些帮助信息
	printf("\n\n\t欢迎来到【在图形中寻找轮廓】示例程序~\n\n");
	printf("\n\n\t按键操作说明: \n\n"
		"\t\t键盘按键任意键- 退出程序\n\n"
		"\t\t滑动滚动条-改变阈值\n");
}
寻找物体的凸包

寻找凸包(convexHull()函数)

基础示例程序:凸包检测基础
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
//-----------------------------------【ShowHelpText( )函数】----------------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
	printf("\n\n  ----------------------------------------------------------------------------\n");
	//输出一些帮助信息
	printf("\n\t欢迎来到【凸包检测】示例程序~\n\n");
	printf("\n\t按键操作说明: \n\n"
		"\t\t键盘按键【ESC】、【Q】、【q】- 退出程序\n\n"
		"\t\t键盘按键任意键 - 重新生成随机点,并进行凸包检测\n");
}
//--------------------------------------【main( )函数】-----------------------------------------
//          描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
	//改变console字体颜色
	system("color 1F");
	//显示帮助文字
	ShowHelpText();
	//初始化变量和随机值
	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;
}
综合实例程序:寻找和绘制物体的凸包
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
//-----------------------------------【宏定义部分】--------------------------------------------
//  描述:定义一些辅助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME1 "【原始图窗口】"					//为窗口标题定义的宏
#define WINDOW_NAME2 "【效果图窗口】"					//为窗口标题定义的宏 
//-----------------------------------【全局变量声明部分】--------------------------------------
//  描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage; Mat g_grayImage;
int g_nThresh = 50;
int g_maxThresh = 255;
RNG g_rng(12345);
Mat srcImage_copy = g_srcImage.clone();
Mat g_thresholdImage_output;
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy;
//-----------------------------------【全局函数声明部分】--------------------------------------
//   描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void*);
//-----------------------------------【main( )函数】------------------------------------------
//   描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
	// 加载源图像
	g_srcImage = imread("1.jpg", 1);
	// 将原图转换成灰度图并进行模糊降
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
	blur(g_grayImage, g_grayImage, Size(3, 3));
	// 创建原图窗口并显示
	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
	imshow(WINDOW_NAME1, g_srcImage);
	//创建滚动条
	createTrackbar(" 阈值:", WINDOW_NAME1, &g_nThresh, g_maxThresh, on_ThreshChange);
	on_ThreshChange(0, 0);//调用一次进行初始化
	waitKey(0);
	return(0);
}
//-----------------------------------【thresh_callback( )函数】----------------------------------
//      描述:回调函数
//----------------------------------------------------------------------------------------------
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, Point(0, 0));
	// 遍历每个轮廓,寻找其凸包
	vector<vector<Point> >hull(g_vContours.size());
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		convexHull(Mat(g_vContours[i]), hull[i], false);
	}
	// 绘出轮廓及其凸包
	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, 1, 8, vector<Vec4i>(), 0, Point());
		drawContours(drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
	}
	// 显示效果图
	imshow(WINDOW_NAME2, drawing);
}
HSV学习链接https://blog.csdn.net/coldwindha/article/details/82080176
opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包的更多相关文章
- opencv 6 图像轮廓与图像分割修复 2 使用多边形将轮廓包围
		
使用多边形将轮廓包围 返回外部矩阵边界(boundingRect()函数) 寻找最小包围矩形(minAreaRect()函数) 寻找最小包围圆形(minEnclosingCircle函数) 用椭圆拟合 ...
 - opencv 6 图像轮廓与图像分割修复 3 图像的矩,分水岭,图像修补
		
图像的矩 矩的计算:moments()函数 计算轮廓面积:contourArea()函数 #include "opencv2/highgui/highgui.hpp" #inclu ...
 - 查找并绘制轮廓[OpenCV 笔记XX]
		
好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...
 - 查找并绘制轮廓 opencv
		
findContours(): 第二个参数为一个检测到的轮廓,函数调用后的运算结果都放在这里,每个轮廓存储为1个点向量,用point类型的vector表示. 第三个参数表示轮廓数量,包含了许多元素.每 ...
 - OpenCV——查找、绘制轮廓
		
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
 - 寻找物体的凸包 opencv
		
凸包的含义: 在二维平面上给定点集,凸包就是将最外层的点连接起来构成的凸多边形.并且这个凸多边形能包含点集中所有的点.OPENCV中: convexHull函数用于寻找图像点集中的凸包.它有六个输入参 ...
 - opencv学习之路(23)、轮廓查找与绘制(二)——访问轮廓每个点
		
一.简介 二.画出每个轮廓的每个点 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat src= ...
 - Opencv分水岭算法——watershed自动图像分割用法
		
分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特 ...
 - 图像分割之(五)活动轮廓模型之Snake模型简介
		
在"图像分割之(一)概述"中咱们简单了解了目前主流的图像分割方法.下面咱们主要学习下基于能量泛函的分割方法.这里学习下Snake模型简单的知识,Level Set(水平集)模型会在 ...
 
随机推荐
- vue——前端跨域
			
***针对的是不同域名.不同协议的跨域: 1.找到config文件中开发环境的配置文件——dev.env.js,在里面将要跨域的域名配置进去 2.找到config文件中线上环境的配置文件——prod. ...
 - 实践开发:vue框架重点知识分析
			
一个VUE项目的主树: assets文件夹是放静态资源: components是放组件: router是定义路由相关的配置; view视图: app.vue是一个应用主组件: main.js是入口文件 ...
 - FastDFS集群-安装说明
			
一.简介 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以文件为载体的在线 ...
 - Kerberos kinit crontab定时任务不生效的问题解决
			
问题 有这样一个定时任务 1 */12 * * * kinit -kt xxxxxx.keytab principle 这样写每天 12点,执行一次. 但是服务器的应用程序报错: GSS initia ...
 - 基于AOP和Redis实现对接口调用情况的监控及IP限流
			
目录 需求描述 概要设计 代码实现 参考资料 需求描述 项目中有许多接口,现在我们需要实现一个功能对接口调用情况进行统计,主要功能如下: 需求一:实现对每个接口,每天的调用次数做记录: 需求二:如果某 ...
 - 来玩一局CS吗?UE4射击游戏的独立服务器构建
			
前言 根据UE4官方文档的介绍,UE4引擎在架构时就已经考虑到了多人游戏的情景,多人游戏基于客户端-服务器模式(CS模式).也就是说,会有一个服务器担当游戏状态的主控者,而连接的客户端将保持近似的 ...
 - java常用类String
			
String: String类: 代表字符串 是一个final类,代表不可变的字符序列 字符串是常量,用双引号引起来表示.值在创建后不可更改 String对象的字符内容是存储在一个字符数组Value[ ...
 - Java 用双向循环链表实现 遍历
			
package day2; /** * 构建双向循环链表,实现遍历功能 */public class DoubleLB { public static void main(String[] args) ...
 - 刷题翻车:python 布尔运算操作符的优先级
			
前两天在 xue.cn 体验答题挑战,我有道题做错了,却不明白错在哪里.题目大概如下,代码运行后将打印什么? if True or False and False: print('1') else: ...
 - TensorFlow如何提高GPU训练效率和利用率
			
前言 首先,如果你现在已经很熟悉tf.data+estimator了,可以把文章x掉了╮( ̄▽ ̄””)╭ 但是!如果现在还是在进行session.run(..)的话!尤其是苦恼于GPU显存都塞满了利用 ...