目录
一、前言
二、轮廓发现
1、轮廓发现
2、发现轮廓API
3、绘制轮廓API
4、代码展示
5、执行结果
继续更新有关于opencv的基础博客,即将更新完毕,想想有点开心呢!
如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:
【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855
如果你想了解更多有关于计算机视觉、OpenCV、机器学习、深度学习等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!
轮廓我想大家都知道是个啥玩意了。主要是这个轮廓发现,单从字面意思理解,我们也知道,就是我们要发现物体的轮廓。
那对于opencv计算机视觉来说,轮廓发现就是通过对图像进行处理之后,提取物体的轮廓的操作。想要提取图像的轮廓,我们就肯定要先找到图像的边缘。
在opencv中,我们想要获得图像的轮廓,分为两部分操作:
(1)发现轮廓
(2)绘制轮廓
接下来我们先讲一下发现轮廓的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层次结构(可用于分析轮廓间关系,一般比较少用到)。
接下来我们讲一下绘制轮廓的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,可选轮廓移动参数。按指定的偏移量移动所有绘制的等高线。
我们进行轮廓发现,主要有如下几步流程:
(1)输入图像转为灰度图像cvtColor
(2)使用Canny进行边缘提取,得到二值图像
(3)使用findContours寻找轮廓
(4)使用drawContours绘制轮廓
#include
#include
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> contours;
vector 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);
}
大家也可以自己尝试一下呀,一定要多做练习!