《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(一)查找并绘制轮廓

第8章 图像轮廓与图像分割修复

8.1 查找并绘制轮廓

8.1.1 寻找轮廓:findContours()函数

1.作用:在二值图像中寻找轮廓
2.函数原型:

void findcontours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())

3.参数说明:
(1)输入图像,8位单通道图像,图像非零像素被保留为0,所以图像为二进制,可以使用cmopare()、inrange()、threshold()、adaptivethreshold()、canny()等函数由灰度图或彩色图创建二进制图像
(2)检测到的轮廓,每个轮廓存储为一个点向量,即用point类型的vector表示
(3)可选的输出向量,包含图像的拓扑信息,作为轮廓数量的表示,每个轮廓contours[i]对应4个hierarchy元素,contours[i][0]~contours[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,对应的hierarchy[i]值设为负数
(4)轮廓检索模式,取值:
            在这里插入图片描述
(5)轮廓近似办法,取值:
            在这里插入图片描述
(6)每个轮廓点的可选偏移量,默认值Point()
4.示例:

vector<vector<Point>>contours;
findContours(image,contours,RETR_EXTERNAL,CHAIN_APPROX_NONE);

8.1.2 绘制轮廓:drawContours()函数

1.作用:用于在图像中绘制外部或内部轮廓
2.函数原型:

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point())

3.参数说明:
(1)目标图像
(2)输入轮廓
(3)轮廓绘制指示变量,负值表示绘制所有轮廓
(4)轮廓颜色
(5)轮廓线条粗细度,默认值1,负值会绘制在轮廓内部
(6)线条类型,默认8,可取值:
            在这里插入图片描述
(7)可选的层次结构信息,默认值noArray()
(8)用于绘制轮廓的最大等级,默认值INT_MAX
(9)可选的轮廓偏移参数,默认Point()
4.示例:

Mat result(image.size(),CV_8U,cv::Scalar(255));
drawContours(result,contours,-1,Scalar(0),3,8);

8.1.3 示例程序

1.查找并绘制轮廓示例

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
	//以二值图模式载入并显示原图
	Mat srcImage = imread("girl.jpg",0);
	if (!srcImage.data)
	{
		printf("图片载入失败~!\n");
		return false;
	}
	imshow("【原始图】", srcImage);
	
	//srcImage取大于阈值119的部分
	srcImage = srcImage > 119;
	imshow("取阈值后的原始图", srcImage);
	
	//初始化结果图
	Mat dstImage;
	dstImage=Mat::zeros(srcImage.rows,srcImage.cols, CV_8UC3);
	
	//定义轮廓和层次结构
	vector<vector<Point>>contours;
	vector<Vec4i>hierarchy;
	
	//查找轮廓
	findContours(srcImage, contours, hierarchy,RETR_CCOMP, CHAIN_APPROX_SIMPLE);
	
	//遍历所有顶层轮廓,以随机颜色绘制每个连接组件颜色
	for (int index = 0; index >= 0; index = hierarchy[index][0])//令index等于当前轮廓的下一个轮廓来更新循环,没有下一轮廓时,hierarchy[i][0]为负值,循环结束
	{
		Scalar color(rand() & 255, rand() & 255, rand() & 255);
		drawContours(dstImage, contours, index,color, FILLED, 8,hierarchy);
	}
	//显示轮廓图
	imshow("【轮廓图】", dstImage);
	waitKey(0);
	return 0;
}

运行效果:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.综合示例

/*
效果:利用图像平滑和边缘检测,根据滑动条调节,动态检测图形轮廓
*/
#include<opencv2/opencv.hpp>
#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,g_grayImage,g_cannyMat_output,g_dstImage;
int g_nThresh = 80;
int g_nThresh_max = 255;
RNG g_rng(12345);
vector<vector<Point>>g_vContours;
vector<Vec4i>g_vHierarchy;
//全局函数
static void ShowHelpText();
static void on_ThreshChange(int, void*);
int main()
{
	//改变console字体颜色
	system("color 1F");
	ShowHelpText();

	//载入原图
	g_srcImage = imread("girl.jpg", 1);
	if (!g_srcImage.data)
	{
		printf("图片载入失败~!\n");
		return false;
	}
	//创建窗口
	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
	namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
	imshow(WINDOW_NAME1, g_srcImage);
	
	//转成灰度图并模糊化降噪
	cvtColor(g_srcImage, g_grayImage, CV_BGR2GRAY);
	blur(g_grayImage, g_grayImage, Size(3, 3));

	//创建滚动条并初始化
	createTrackbar("canny阈值", WINDOW_NAME2, &g_nThresh, g_nThresh_max, on_ThreshChange);
	on_ThreshChange(0, 0);

	waitKey(0);
	return 0;
}
static 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 g_dstImage = Mat::zeros(g_srcImage.rows, g_srcImage.cols, CV_8UC3);
	//或 for (int index = 0; index >= 0; index = g_vHierarchy[index][0])
	for (int index = 0; index < g_vContours.size(); index++)
	{
		Scalar color(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//任意值
		drawContours(g_dstImage, g_vContours, index, color, 2, 8, g_vHierarchy, 0, Point());
	}
	//显示效果图
	imshow(WINDOW_NAME2, g_dstImage);
}
static void ShowHelpText()
{
	printf("\n\n\t欢迎来到【在图形中寻找轮廓】示例程序!\n\n");
	printf("\n\n\t操作说明:\n\n");
	printf("\t\t键盘任意键-退出程序\n\n");
	printf("\t\t滑动滚动条-改变canny阈值\n");
}

运行效果:
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ccchenxi/article/details/85173243