【opencv学习笔记】029 之轮廓发现

目录

一、前言

二、轮廓发现

1、轮廓发现

2、发现轮廓API

3、绘制轮廓API

4、代码展示

5、执行结果


一、前言

继续更新有关于opencv的基础博客,即将更新完毕,想想有点开心呢!

如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

如果你想了解更多有关于计算机视觉、OpenCV、机器学习、深度学习等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!

二、轮廓发现

1、轮廓发现

轮廓我想大家都知道是个啥玩意了。主要是这个轮廓发现,单从字面意思理解,我们也知道,就是我们要发现物体的轮廓。

那对于opencv计算机视觉来说,轮廓发现就是通过对图像进行处理之后,提取物体的轮廓的操作。想要提取图像的轮廓,我们就肯定要先找到图像的边缘。

在opencv中,我们想要获得图像的轮廓,分为两部分操作:

(1)发现轮廓

(2)绘制轮廓

2、发现轮廓API

接下来我们先讲一下发现轮廓的API。

void findContours( 
    InputArray image, 
    OutputArrayOfArrays contours,
    OutputArray hierarchy,
    int mode,
    int method,                              
    Point offset = Point()
);

函数参数含义如下:

(1)InputArray类型的image,8位单通道图像。非零像素被视为1。零像素保持为0,因此图像被视为二进制。

(2)OutputArrayOfArrays类型的contours,检测到的轮廓。每个轮廓都存储为点的矢量。

(3)OutputArray类型的hierarchy,图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。

(4)int类型的mode,轮廓检索模式,参见cv::RetrievalModes

(5)int类型的method,轮廓近似法,参加cv::ContourApproximationModes。

(6)Point类型的offset,每个轮廓点的偏移量。如果从图像感兴趣区域中提取轮廓,然后在整个图像上下文中对其进行分析,这将非常有用。默认(0, 0)没有位移。

在opencv中,有该函数的一个重载函数,两个函数的区别在于是否有第三个参数:

void findContours( 
    InputArray image, 
    OutputArrayOfArrays contours,
    int mode,
    int method,                              
    Point offset = Point()
);

这两个函数的真正区别在于:

需不需要输出hierarchy层次结构(可用于分析轮廓间关系,一般比较少用到)。

3、绘制轮廓API

接下来我们讲一下绘制轮廓的API。

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

函数参数含义如下:

(1)InputArray类型的image,目标图像。

(2)OutputArrayOfArrays类型的contours,所有输入轮廓。每个轮廓都存储为点向量。

(3)int类型的courtolidx,表示要绘制的轮廓的参数。如果为负数,则绘制所有轮廓。

(4)Scalar类型的color,轮廓的颜色。

(5)int类型的thickness,绘制轮廓线的厚度。如果为负值(例如,thickness=CV_FILLED),则绘制轮廓内部。

(6)int类型的lineType,线连接性。

(7)InputArray类型的hierarchy,关于层次结构的可选信息。只有当您只想绘制一些轮廓时才需要它(请参见maxLevel)。

(8)int类型的maxLevel,线连接性。绘制轮廓的最大级别。如果为0,则仅绘制指定的轮廓。如果为1,则函数将绘制轮廓和所有嵌套轮廓。如果是2,则函数将绘制等高线、所有嵌套等高线、所有嵌套到嵌套等高线等。只有当存在可用的层次结构时才考虑此参数。

(9)Point类型的offset,可选轮廓移动参数。按指定的偏移量移动所有绘制的等高线。

drawContours

4、代码展示

我们进行轮廓发现,主要有如下几步流程:

(1)输入图像转为灰度图像cvtColor

(2)使用Canny进行边缘提取,得到二值图像

(3)使用findContours寻找轮廓

(4)使用drawContours绘制轮廓

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

Mat src, dst;
const char* input_win = "【输入图像】";
const char* output_win = "【输出图像】";
int threshold_value = 100;
int threshold_max = 255;
RNG rng;

void Demo_Contours(int, void*);

int main()
{
	src = imread("E:/个人/学习/编程/C++/CPlusPlusTestProgram/LearnOpenCV/image/girl2.png");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	namedWindow(input_win, CV_WINDOW_AUTOSIZE);
	namedWindow(output_win, CV_WINDOW_AUTOSIZE);
	imshow(input_win, src);
	cvtColor(src, src, CV_BGR2GRAY);

	const char* trackbar_title = "Threshold Value:";
	createTrackbar(trackbar_title, output_win, &threshold_value, threshold_max, Demo_Contours);
	Demo_Contours(0, 0);

	waitKey(0);
	return 0;
}

void Demo_Contours(int, void*) {
	Mat canny_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	Canny(src, canny_output, threshold_value, threshold_value * 2, 3, false);
	findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	dst = Mat::zeros(src.size(), CV_8UC3);
	RNG rng(12345);
	for (size_t i = 0; i < contours.size(); i++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
	}
	imshow(output_win, dst);
}

5、执行结果

原图
轮廓获取
轮廓获取

大家也可以自己尝试一下呀,一定要多做练习!

发布了274 篇原创文章 · 获赞 545 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/104604849
今日推荐