目录

  • 前言:
  • 本篇学习内容:
  • 1.绘制图像轮廓
  • 参考文献:


前言:

笔者目前在校本科大二,有志于进行计算机视觉、计算机图形学方向的研究,准备系统性地、扎实的学习一遍OpenCV的内容,故记录学习笔记,同时,由于笔者同时学习数据结构、机器学习等知识,会尽量根据自己的理解,指出OpenCV的应用,并在加上自己理解的前提下进行叙述。
若有不当之处,希望各位批评、指正。


本篇学习内容:

1.绘制图像轮廓


1.绘制图像轮廓

虽然之前提到,通过计算图像的形态学梯度可以用于保留图像边缘轮廓,但是实际上OpenCV提供了专门用于计算轮廓的函数。

用findContours()函数和drawContours()函数来寻找并绘制图像轮廓。

void cv::findContours	(	
InputArray 	image,				//输入图像
OutputArrayOfArrays contours,	//输出轮廓
OutputArray 	hierarchy,		//包含图像拓扑信息
int 	mode,					//轮廓检索模式
int 	method,					//轮廓近似方法
Point 	offset = Point() 		//偏移量
)

对部分参数进行进一步介绍:
image: 只接受二值图像(实际上接受8位单通道图像,但非0元素视为1)。可以用一系列其他的函数(如threshold(),Canny()等)来获得这个输入图像。
contours: 输出的轮廓。每一个轮廓被储存为一个Point型的vector。所以需要准备一个二维的Point型的vector。
hierarchy: 输出轮廓之间的层次关系。这是一个四维的vector。它的元素数量和contours的元素数量一样多。对于每一个轮廓contours[i],hierarchy的四维分别储存了该轮廓的:同层次下一轮廓、同层次上一轮廓、第一个子轮廓、父轮廓。如果没有同层次下一轮廓、同层次上一轮廓、第一个子轮廓、父轮廓,该值会设为负值。

//所以,如果想绘制顶层轮廓,可以这样设置:
for(int i = 0 ; i >= 0 ; i = hierarchy[i][0]){
	drawContours(dst,contours,i,color,1,8);
}

mode的标识符如下:

opencv 人体轮廓 opencv轮廓绘制_c++


method的标识符如下:

opencv 人体轮廓 opencv轮廓绘制_学习_02


另外,给出官方文档对这些参数的介绍:

opencv 人体轮廓 opencv轮廓绘制_opencv_03


注:从opencv 3.2 开始,这个函数不会改变输入图像

我们通过findContours()获得了图像轮廓,接下来要处理这些轮廓,也就是用drawContours()来个性化地绘制轮廓。

void cv::drawContours	(	
InputOutputArray 	image,			//目标图像
InputArrayOfArrays 	contours,		//输入的轮廓
int 	contourIdx,					//要绘制的轮廓的参数
const Scalar & 	color,				//绘制轮廓的颜色
int 	thickness = 1,				//绘制轮廓的线条宽度
int 	lineType = LINE_8,			//线连通度
InputArray 	hierarchy = noArray(),	//可选,输入的轮廓层次信息
int 	maxLevel = INT_MAX,			//绘制哪些轮廓
Point 	offset = Point() 			//轮廓偏移度
)

对部分参数进行进一步介绍:
contourIdx: 如果设为负值,则绘制所有轮廓。
hierarchy: 只当你只想绘制部分轮廓时,才需要设置它。这个参数和maxLevel结合使用。
maxLevel: 绘制轮廓的最大等级。如果是0,则只绘制指定的轮廓线。如果它是1,函数会绘制一个或多个轮廓和所有嵌套的轮廓。如果是2,函数绘制轮廓,所有嵌套的轮廓,所有嵌套到嵌套的轮廓,等等。只有当存在可用的层次结构(hierarchy)时,才会考虑此参数。

接下来介绍一个例子:

Mat img = imread("E:/program/image/1.jpg",0);
img = img > 100;
Mat dst = Mat::zeros(img.rows, img.cols, CV_8UC3);
imshow("src", img);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(img, contours,hierarchy, RETR_CCOMP,CHAIN_APPROX_SIMPLE);
drawContours(dst, contours, -1, Scalar(255, 255, 0), 1, 8);
imshow("dst", dst);
waitKey();

上面的代码绘制了所有的轮廓。
如果想绘制顶层轮廓,可以这样写:

Mat img = imread("E:/program/image/1.jpg",0);
img = img > 100;
Mat dst = Mat::zeros(img.rows, img.cols, CV_8UC3);
imshow("src", img);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(img, contours,hierarchy, RETR_CCOMP,CHAIN_APPROX_SIMPLE);
for(int i = 0 ; i >=0 ; i = hierarchy[i][0])
{
	drawContours(dst, contours, i, Scalar(255, 255, 0), 1, 8);
}
imshow("dst", dst);
waitKey();

输出结果:(下面那个代码)

opencv 人体轮廓 opencv轮廓绘制_opencv 人体轮廓_04

参考文献:

  1. OpenCV官方文档:https://docs.opencv.org/4.x/
  2. 《OpenCV3编程入门》毛星云、冷雪飞等编著