从零开始学cv-13:图像的轮廓处理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

在这个信息化时代,图像处理技术已经成为我们日常生活中不可或缺的一部分。无论是人脸识别、车辆检测,还是医学影像分析,都离不开图像处理技术的应用。而在图像处理领域,轮廓检测作为一种基础且关键的技术,扮演着举足轻重的角色。今天,我将为大家带来一篇关于图片轮廓与OpenCV轮廓操作的详细介绍博客。希望通过本文,能让您对轮廓检测技术有更深入的了解,并学会运用OpenCV进行轮廓操作,为您的图像处理之旅添砖加瓦。


一、图像轮廓是什么?

轮廓是图像处理中的一个基本概念,它指的是图像中物体边缘的连续曲线或线条。这些线条代表了物体与背景之间的分界线,是识别物体形状、大小和位置的关键特征。在更技术性的描述中,轮廓可以被视为一系列相连的像素点,这些点在图像中具有相同的颜色或亮度,并且它们相邻点之间的方向变化不超过特定的阈值。
轮廓携带着丰富的特征信息,如面积、周长、质心位置和角度等,这些特征显著提升了图像内容的分析深度。在图像处理领域,轮廓检测扮演着多种关键角色:它是图像分割的核心,能够将图像划分为多个独立区域,每个区域代表一个特定的物体或其结构部分。通过轮廓检测,图像处理过程得以简化,因为它筛选出了关键的像素信息,减少了后续处理的计算量。此外,轮廓提取过程将二维图像数据简化为一维轮廓线,这不仅降低了数据的维度,也使得问题处理更为简洁。

二、opencv检测并绘制图像轮廓:

在OpenCV中,轮廓检测是一个重要的功能,用于识别图像中的物体边界。以下是OpenCV中进行轮廓检测的常用过程:首先,将彩色图像转换为灰度图像,因为在这种格式下轮廓检测更为有效。然后,将灰度图像转换为二值图像,这样做有助于更清晰地描绘出物体的轮廓。此外,为了进一步提升轮廓检测的效果,可以选择进行边缘检测,这有助于突出图像中的关键边界。最后,使用opencv的轮廓检测工具来识别二值图像中的所有轮廓,并根据它们的层次结构进行组织,从而为后续的分析和处理打下基础。
opencv的轮廓检测工具contours, hierarchy = cv2.findContours(image, mode, method):

输入:
image:输入图像,通常是经过二值化处理的图像。
mode:轮廓检索模式,有以下几种:
cv2.RETR_EXTERNAL:只检测最外层的轮廓。
cv2.RETR_LIST:检测所有轮廓,但不建立轮廓间的层次关系。
cv2.RETR_CCOMP:检测所有轮廓,并将它们组织为两个等级的层次结构。
cv2.RETR_TREE:检测所有轮廓,并重构嵌套轮廓的完整层次结构。
method:轮廓逼近方法,有以下两种:
cv2.CHAIN_APPROX_NONE:存储所有轮廓点。
cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角线段,只保留它们的端点。
输出:
contours: 这是一个列表,其中每个元素都是一个轮廓,表示为一个点的 numpy 数组。每个点都是一个 (x, y) 坐标对,表示轮廓上的一个点。
hierarchy: 这是一个可选的输出数组,包含有关图像中轮廓层次结构的信息。它是一个 numpy 数组,其中的每个元素都是一个包含四个值的数组,分别表示下一个轮廓、前一个轮廓、子轮廓和父轮廓的索引。

需要注意的是,OpenCV 3.x 和 OpenCV 4.x 在 findContours 函数的返回值上有所不同。在 OpenCV 3.x 中,findContours 函数的返回值顺序是 (contours, hierarchy),而在 OpenCV 4.x 中,如果不需要层次信息,可以只返回 contours。

opencv轮廓绘制工具cv2.drawContours(image, contours, contourIdx, color, thickness),用于在图像上绘制轮廓。这个函数在图像处理和计算机视觉中非常有用,尤其是在需要可视化轮廓检测结果时。

参数说明:
image: 要在其上绘制轮廓的图像。这个图像会被函数直接修改,因此在调用此函数之前,应确保已经复制了原始图像,以防原始数据被覆盖。
contours: 一个列表,其中每个元素都是一个轮廓,表示为一个点的 numpy 数组。这些轮廓通常是由 cv2.findContours 函数返回的。
contourIdx: 整数或整数列表,指定要绘制哪些轮廓。如果这个参数是 -1,则函数会绘制所有轮廓。如果提供的是单个整数,则只绘制该索引对应的轮廓。如果是列表,则绘制列表中所有索引对应的轮廓。
color: 轮廓的颜色,以 RGB 格式表示。例如,color=(0, 255, 0) 表示绿色。
thickness: 轮廓线的厚度。如果这个参数是 -1,则轮廓内部会被填充。如果厚度是正数,则指定轮廓线的宽度。默认值是 1。
lineType: 轮廓线的类型。默认情况下,这个参数是 None,表示 8 连接线。也可以设置为 4 连接线或其他类型的线。
hierarchy: 可选的层次结构信息,通常由 cv2.findContours 返回。这个参数用于绘制轮廓的层次结构。
maxLevel: 可选参数,用于绘制轮廓的层次结构。如果这个参数是 0,则只绘制指定的轮廓。如果是 1,则绘制轮廓及其子轮廓。如果是 2,则绘制轮廓及其子轮廓和子轮廓的子轮廓,依此类推。
offset: 可选参数,用于轮廓的所有点的一个偏移量。这通常用于在图像中的特定位置绘制轮廓。

例子:

import cv2

# 读取图像
image = cv2.imread(r'D:\AI_tool\GFPGAN-master\1.jpg')

# 将图像转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 应用二值化,这里使用简单的全局阈值
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)

# 查找轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 按照轮廓的面积进行排序,并取面积最大的轮廓
contours = sorted(contours, key=cv2.contourArea, reverse=True)

# 检查是否找到轮廓
if contours:
    # 获取面积最大的轮廓
    max_contour = contours[0]

    # 绘制最大轮廓
    cv2.drawContours(image, [max_contour], -1, (0, 255, 0), 3)

# 显示结果图像
cv2.imshow('binary', binary)
cv2.imshow('Image with Largest Contour', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

三、轮廓处理

3.1 多边形逼近与凸包

在计算机视觉和图像处理中,多边形近似和凸包是两种常用的技术,常用于简化轮廓的形状表示并提取有用的几何特征。以下是关于这两种技术的介绍:
多边形近似 (Polygon Approximation)
多边形近似是一种技术,它将复杂的轮廓或形状简化为具有较少顶点的多边形。这种简化保留了原始形状的基本特征,同时减少了数据量,便于后续处理和分析。
多边形近似通常通过迭代过程来实现,该过程逐步减少轮廓上的点数,同时尽量保持原始形状。常用的方法是 Douglas-Peucker算法,它通过计算轮廓上每一点与近似线段的距离,并在距离超过预设阈值时将该点加入到近似多边形中。
凸包 (Convex Hull)
凸包是包含一组点的最小凸多边形。换句话说,它是所有给定点的边界,使得任何内部点与边界上的任意两点形成的线段完全位于多边形内部。凸包的计算通常使用几种算法,如 Graham扫描、Jarvis步进或快速凸包算法(QuickHull)。
这些算法通过选择一些关键点(如最左、最右、最高、最低点)作为凸包的起始点,然后逐步添加或删除点来构建凸包。
在OpenCV中,多边形近似(Polygon Approximation)和凸包(Convex Hull)是用于简化轮廓形状的两个概念,它们通常通过cv2.approxPolyDP和cv2.convexHull函数来实现。以下是这两个API的详细介绍:
approx = cv2.approxPolyDP(curve, epsilon, closed)

参数:
curve: 输入的曲线,通常是一个由cv2.findContours返回的轮廓点列表。
epsilon: 近似误差,它定义了曲线上的点到其近似多边形边的最大距离。
closed: 布尔值,如果为True,则curve被认为是闭合的;如果为False,则curve被认为是开放的。
返回值:
如果成功,返回一个近似的多边形点列表。
如果失败,返回None。

hull = cv2.convexHull(points)

参数:
points: 输入的点列表,通常是一个由cv2.findContours返回的轮廓点列表。
返回值:
如果成功,返回一个凸包的点列表。
如果失败,返回None。

示例代码:

import cv2

# 读取图像
image = cv2.imread(r'D:\AI_tool\GFPGAN-master\shenshoushoushitupiansucai_3889318.jpg')

# 将图像转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 应用二值化,这里使用简单的全局阈值
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

# 查找轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 按照轮廓的面积进行排序,并取面积最大的轮廓
contours = sorted(contours, key=cv2.contourArea, reverse=True)

# 检查是否找到轮廓
if contours:
    # 获取面积最大的轮廓
    max_contour = contours[0]
    approx = cv2.approxPolyDP(max_contour, 0.02 * cv2.arcLength(max_contour, True), True)
    hull = cv2.convexHull(max_contour)
    # 绘制最大轮廓
    cv2.drawContours(image, [approx], -1, (0, 255, 0), 3)
    cv2.drawContours(image, [hull], -1, (0, 0, 255), 3)
# 显示结果图像
cv2.imshow('Image with Largest Contour', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果红色为凸包绿色为近似多边形:在这里插入图片描述

3.2 外接矩形与最小外接矩形

在计算机视觉和图像处理中,外接矩形(Bounding Rectangle)是指包含给定形状的最小矩形。这个矩形定义了形状在图像中的边界框,其中形状的每个点都在矩形的边界上或者矩形的内部。外接矩形通常用于对象检测和识别,因为它可以提供关于形状大小和位置的有用信息。在OpenCV中,可以使用cv2.boundingRect函数来计算一个形状的外接矩形。
函数:(x, y, w, h) = cv2.boundingRect(points)

参数:
points: 输入的点列表,通常是一个由cv2.findContours返回的轮廓点列表。
返回值:
(x, y): 矩形的左上角坐标。
w: 矩形的宽度。
h: 矩形的高度。

最小外接矩形(Minimum Enclosing Rectangle,MER)是一种用于描述二维形状的矩形,它与形状的最外边缘相接触,且没有额外的空隙。这种矩形可以用来确定形状的大小和位置,并且在计算机视觉和图像处理中非常有用。
在OpenCV中,可以使用cv2.minAreaRect函数来计算最小外接矩形。
函数原型:
(center, size, angle) = cv2.minAreaRect(points)

参数:
points: 输入的点列表,通常是一个由cv2.findContours返回的轮廓点列表。
返回值:
(center, size, angle): 最小外接矩形的中心坐标、尺寸(宽度和高度)和旋转角度。

使用代码:

import cv2
import numpy as np

# 读取图像
image = cv2.imread(r'D:\AI_tool\GFPGAN-master\shenshoushoushitupiansucai_3889318.jpg')

# 将图像转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 应用二值化,这里使用简单的全局阈值
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

# 查找轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 按照轮廓的面积进行排序,并取面积最大的轮廓
contours = sorted(contours, key=cv2.contourArea, reverse=True)

# 检查是否找到轮廓
if contours:
    # 获取面积最大的轮廓
    max_contour = contours[0]
    x, y, w, h = cv2.boundingRect(max_contour)
    # 绘制外接矩形
    cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)
    
    # 绘制最小外接矩形
    box = cv2.boxPoints(cv2.minAreaRect(max_contour))
    box = np.int0(box)
    cv2.drawContours(image, [box], 0, (0, 0, 255), 2)
# 显示结果图像
cv2.imshow('Image with Largest Contour', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:
在这里插入图片描述

  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值