本文分享内容来自图书《学习OpenCV 4:基于Python的算法实战》,该书内容如下:
第1章 OpenCV快速入门; 第2章 图像读写模块imgcodecs; 第3章 核心库模块core; 第4章 图像处理模块imgproc(一); 第5章 图像处理模块imgproc(二); 第6章 可视化模块highgui; 第7章 视频处理模块videoio; 第8章 视频分析模块video; 第9章 照片处理模块photo; 第10章 2D特征模块features2d; 第11章 相机标定与三维重建模块calib3d; 第12章 传统目标检测模块objdetect; 第13章 机器学习模块ml; 第14章 深度神经网络模块dnn
欢迎关注图书《深度学习计算机视觉实战》与《学习OpenCV4:基于Python的算法实战》。
Canny边缘检测算法可以很好的检测出目标的边缘,但是没有将这些边缘作为一个整体进行处理。而轮廓是一系列连续的点组成的曲线,可以表达物体的基本外形,在目标识别中有着重要作用。
案例65:轮廓查找
OpenCV中提供了轮廓查找的函数findContours,该函数处理的图像可以是Canny边缘检测的结果,也可以是使用阈值化得到的图像,函数定义如下:
contours, hierarchy = findContours(image, mode, method, contours=None, hierarchy=None, offset=None)
参数说明如下:
u image,输入图像,需传入二值图像;
u mode,轮廓查找的模式,由RetrievalModes定义(见4.1节);
u method,轮廓近似方式,由ContourApproximationModes定义(见4.1节);
u contours,检测到的轮廓的坐标点(返回值);
u hierarchy,轮廓层次(返回值);
u offset,每个轮廓点移动的偏移量。
本案例使用的源图像如图5.39所示。
图5.39
轮廓查找的案例代码如下: import cv2 import numpy as np #读取图像,转为灰度图像 img = cv2.imread('contour_src.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #阈值化 ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) # 寻找二值图像的轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #打印轮廓数量 print("Contour Numbers:", len(contours)) #打印层次关系 print("hierarchy\n", hierarchy)
执行后的打印信息如下:
Contour Numbers: 4 hierarchy [[[-1 -1 1 -1] [-1 -1 2 0] [-1 -1 3 1] [-1 -1 -1 2]]]
轮廓数量为4个,包括五边形、圆形,四边形和整个图像最外围的轮廓。
hierarchy为轮廓的层次关系,每一个轮廓中的四个元素的含义对应为:[下一个轮廓索引,上一个轮廓索引,第一个子轮廓索引,父轮廓索引],如果对应的关系不存在则对应位置的值为-1。hierarchy与参数mode有关,不同的mode对应的hierarchy不同。
案例66:轮廓绘制
对于查找到的轮廓,可以使用OpenCV中提供的轮廓绘制函数drawContours进行绘制,函数定义如下:
image = drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
参数说明如下:
u image,输入图像,在该图像上绘制轮廓(返回值);
u contours,查找到的轮廓;
u contourIdx,绘制的轮廓编号,全部绘制则编号为负数;
u color,绘制颜色;
u thickness,绘制线的粗细;
u lineType,绘制线的线型,由LineTypes定义(见4.1节);
u hierarchy,绘制轮廓的层次;
u maxLevel,轮廓绘制级别;
u offset,绘制轮廓偏移。
轮廓查找与轮廓绘制的完整案例代码如下:
import cv2 import numpy as np #读取图像,转为灰度图像 img = cv2.imread('contour_src.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #阈值化 ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) # 寻找二值图像的轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #打印轮廓数量 print("Contour Numbers:", len(contours)) #打印层次关系 print("hierarchy\n", hierarchy) #创建白底图像 contours_img = np.zeros(img.shape[:], dtype=np.uint8) contours_img[:] = 255 #绘制轮廓 cv2.drawContours(contours_img, contours, -1, (0, 0, 255), 2) cv2.imshow('contours_result', contours_img) cv2.waitKey(0) cv2.destroyAllWindows()
本案例中绘制了所有的轮廓,绘制结果如图5.40所示。
图5.40
如果想绘制某个轮廓,则传入对应的轮廓编号即可,本案例中包括四个轮廓,从外到内的轮廓编号分别为0,1,2,3,轮廓2的绘制的结果如图5.41所示。
图5.41
OpenCV中提供了轮廓面积的计算函数contourArea,函数定义如下:
retval = contourArea(contour, oriented=None)
参数说明如下:
contour,待计算面积的轮廓。
oriented,带方向的面积标志。如果为true,函数将根据轮廓方向(顺时针或逆时针)返回带符号的面积值,这样可以通过获取某个面积的符号来确定轮廓的方向。默认情况下,参数为false,这意味着返回面积的绝对值;
u retval,计算的面积结果。
在轮廓绘制案例代码的基础上,计算面积的案例代码如下:
area = cv2.contourArea(contours_list[1]) print("Contour 1 Area is: ", area)
计算结果输出如下:
Contour 1 Area is: 219110.0