【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓(cv.drawContours)

OpenCV 例程200篇 总目录-202205更新


【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓(cv.drawContours)


1. 轮廓

轮廓是一系列相连的像素点组成的曲线,代表了物体的基本外形。轮廓常用于形状分析和物体的检测和识别。

边缘检测根据灰度的突变检测边界,但检测到的边缘通常还是零散的片段,并未构成整体。从背景中分离目标,就要将边缘像素连接构成轮廓。也就是说,轮廓是连续的,边缘不一定都连续。边缘主要是作为图像的特征使用,而轮廓主要用来分析物体的形态。


### 1.2 轮廓的绘制

OpenCV 提供函数 cv2.drawContours() 绘制轮廓。绘制轮廓并不是绘图显示,而是修改图像添加轮廓线。

函数说明:

cv.drawContours(image, contours, contourIdx, color[, thickness=1, lineType=LINE_8, hierarchy=Mat(), maxLevel=INT_MAX, offset=Point()] ) → image

cv.findContours() 对黑色背景的二值图像操作,通常会先使用阈值分割或边缘检测得到二值图像。

参数说明:

  • image:输入/输出图像,必须是 BGR 格式的彩色图像
  • contours: 输入的轮廓列表,每个轮廓由边界点坐标 (x,y) 向量构成
  • contourIdx:所要绘制的轮廓的编号,-1 表示绘制所有轮廓
  • color:绘制轮廓的颜色,RGB
  • thickness:绘制轮廓的线宽,-1 (“CV_FILLED”)表示轮廓内部填充
  • lineType:绘制轮廓的线型
    • cv.FILLED:填充
    • cv.LINE_4:4 邻接线型
    • cv.LINE_8:8 邻接线型,默认值
    • cv.LINE_AA:抗锯齿线型
  • hierarchy: 轮廓的结构信息,可选项
  • maxLevel:绘制轮廓的最大级别,存在轮廓结构信息 hierarchy 时才适用:0 表示仅绘制指定轮廓,1 表示绘制轮廓及下一级的子轮廓, 2 表示绘制轮廓及所有各级内部轮廓
  • offset:每个轮廓点的偏移量,可选项

注意事项:

  • 在一些 OpenCV 版本中,绘制轮廓操作会改变原始图像。为了避免不同版本带来的错误,推荐都采用原始图像的 copy 作为函数的输入图像。

例程 12.2:绘制轮廓

    # 12.2 绘制轮廓
    img = cv2.imread("../images/pattern1.png", flags=1)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV)
    plt.figure(figsize=(9, 6))
    plt.subplot(131), plt.axis('off'), plt.title("Origin")
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

    # 寻找二值化图中的轮廓
    binary, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV3
    # contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV4~

    #  绘制最内层轮廓, hierarchy[0][i][2]=-1 表示没有子轮廓,即为最内层轮廓
    contourEx = img.copy()  # OpenCV3.2 之前的早期版本,查找轮廓函数会修改原始图像
    for i in range(len(contours)):  # 绘制第 i 个轮廓
        if hierarchy[0][i][2]==-1:  # 最内层轮廓
            x, y, w, h = cv2.boundingRect(contours[i])  # 外接矩形
            text = "{}({},{})".format(i, x, y)
            contourEx = cv2.drawContours(contourEx, contours, i, (205, 0, 0), thickness=-1)  # 第 i 个轮廓,内部填充
            contourEx = cv2.putText(contourEx, text, (x,y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255))
            print("i=", i, ",contours[i]:", contours[i].shape, ",hierarchy[0][i] =", hierarchy[0][i], "text=", text)

    #  绘制全部轮廓,contourIdx=-1 绘制全部轮廓
    contourTree = img.copy()
    contourTree = cv2.drawContours(contourTree, contours, -1, (0, 0, 255), 2)

    plt.subplot(132), plt.axis('off'), plt.title("External contour")
    plt.imshow(cv2.cvtColor(contourEx, cv2.COLOR_BGR2RGB))
    plt.subplot(133), plt.axis('off'), plt.title("Tree contour")
    plt.imshow(cv2.cvtColor(contourTree, cv2.COLOR_BGR2RGB))
    plt.tight_layout()
    plt.show()

在这里插入图片描述


(本节完)


版权声明:

OpenCV 例程200篇 总目录-202205更新
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/124997075)

Copyright 2022 youcans, XUPT
Crated:2022-5-25


欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中
欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中

【youcans 的 OpenCV 例程200篇】147. 图像分割之孤立点检测
【youcans 的 OpenCV 例程200篇】148. 图像分割之线检测
【youcans 的 OpenCV 例程200篇】149. 图像分割之边缘模型
【youcans 的 OpenCV 例程200篇】150. 边缘检测梯度算子
【youcans 的 OpenCV 例程200篇】151. 边缘检测中的平滑处理
【youcans 的 OpenCV 例程200篇】152. 边缘检测之 LoG 算子
【youcans 的 OpenCV 例程200篇】153. 边缘检测之 DoG 算子
【youcans 的 OpenCV 例程200篇】154. 边缘检测之 Canny 算子
【youcans 的 OpenCV 例程200篇】155. 边缘连接的局部处理方法
【youcans 的 OpenCV 例程200篇】156. 边缘连接局部处理的简化算法
【youcans 的 OpenCV 例程200篇】157. 霍夫变换直线检测
【youcans 的 OpenCV 例程200篇】158. 阈值处理之固定阈值法
【youcans 的 OpenCV 例程200篇】159. 图像分割之全局阈值处理
【youcans 的 OpenCV 例程200篇】160. 图像处理之OTSU 方法
【youcans 的 OpenCV 例程200篇】161. OTSU 阈值处理算法的实现
【youcans 的 OpenCV 例程200篇】162. 全局阈值处理改进方法
【youcans 的 OpenCV 例程200篇】163. 基于边缘信息改进全局阈值处理
【youcans 的 OpenCV 例程200篇】164.使用 Laplace 边缘信息改进全局阈值处理
【youcans 的 OpenCV 例程200篇】165.多阈值 OTSU 处理方法
【youcans 的 OpenCV 例程200篇】166.自适应阈值处理
【youcans 的 OpenCV 例程200篇】167.基于移动平均的可变阈值处理
【youcans 的 OpenCV 例程200篇】168.图像分割之区域生长
【youcans 的 OpenCV 例程200篇】169.图像分割之区域分离
【youcans 的 OpenCV 例程200篇】170.图像分割之K均值聚类
【youcans 的 OpenCV 例程200篇】171.SLIC 超像素区域分割
【youcans 的 OpenCV 例程200篇】172.SLIC 超像素区域分割算法比较
【youcans 的 OpenCV 例程200篇】173.SEEDS 超像素区域分割
【youcans 的 OpenCV 例程200篇】174.LSC 超像素区域分割
【youcans 的 OpenCV 例程200篇】175.超像素区域分割方法比较
【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法
【youcans 的 OpenCV 例程200篇】177.图像分割之 GraphCuts 图割法
【youcans 的 OpenCV 例程200篇】178.图像分割之 GrabCut 图割法(框选前景)
【youcans 的 OpenCV 例程200篇】179.图像分割之 GrabCut 图割法(掩模图像)
【youcans 的 OpenCV 例程200篇】180.基于距离变换的分水岭算法
【youcans 的 OpenCV 例程200篇】181.基于 Sobel 梯度的分水岭算法
【youcans 的 OpenCV 例程200篇】182.基于形态学梯度的分水岭算法
【youcans 的 OpenCV 例程200篇】183.基于轮廓标记的分水岭算法
【youcans 的 OpenCV 例程200篇】184.鼠标交互标记的分水岭算法
【youcans 的 OpenCV 例程200篇】185.图像金字塔之高斯金字塔
【youcans 的 OpenCV 例程200篇】186.图像金字塔之拉普拉斯金字塔
【youcans 的 OpenCV 例程200篇】187.由拉普拉斯金字塔还原图像
【youcans 的 OpenCV 例程200篇】188.基于拉普拉斯金字塔的图像融合
【youcans 的 OpenCV 例程200篇】189.基于掩模的拉普拉斯金字塔图像融合
【youcans 的 OpenCV 例程200篇】190.基于图像分割的图像融合
【youcans 的 OpenCV 例程200篇】191.基于图像分割的金字塔图像融合
【youcans 的 OpenCV 例程200篇】192.Gabor 滤波器组的形状
【youcans 的 OpenCV 例程200篇】193.基于Gabor 滤波器的特征提取
【youcans 的 OpenCV 例程200篇】194.寻找图像轮廓(cv.findContours)
【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓(cv.drawContours)

猜你喜欢

转载自blog.csdn.net/youcans/article/details/124997075