前言:
笔者目前在校本科大二,有志于进行计算机视觉、计算机图形学方向的研究,准备系统性地、扎实的学习一遍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的标识符如下:
method的标识符如下:
另外,给出官方文档对这些参数的介绍:
注:从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官方文档:https://docs.opencv.org/4.x/
- 《OpenCV3编程入门》毛星云、冷雪飞等编著