opencv学习之梯度处理、边缘检测、轮廓生成、凸包生成

一、梯度处理

如果你还记得高数中用一阶导数来求极值的话,就很容易理解了:把图片想象成连续函数,因为边缘部分的像素值是与旁边像素明显有区别的,所以对图片局部求极值,就可以得到整幅图片的边缘信息了。不过图片是二维的离散函数,导数就变成了差分,这个差分就称为图像的梯度。

垂直边缘提取:

水平边缘提取:

垂直卷积核的转置就是水平卷积核,运算同上例。

cv2.filter2D(src, ddepth, kernel)

filter2D函数是用于对图像进行二维卷积(滤波)操作。它允许自定义卷积核(kernel)来实现各种图像处理效果,如平滑、锐化、边缘检测等

sobel算子:

sobel_image = cv2.Sobel(src, ddepth, dx, dy, ksize)

src:这是输入图像,通常应该是一个灰度图像(单通道图像),因为 Sobel 算子是基于像素亮度梯度计算的。在彩色图像的情况下,通常需要先将其转换为灰度图像。

ddepth:这个参数代表输出图像的深度,即输出图像的数据类型。在 OpenCV 中,-1 表示输出图像的深度与输入图像相同。

dx,dy:当组合为dx=1,dy=0时求x方向的一阶导数,在这里,设置为1意味着我们想要计算图像在水平方向(x轴)的梯度。当组合为 dx=0,dy=1时求y方向的一阶导数(如果同时为1,通常得不到想要的结果,想两个方向都处理的比较好 学习使用后面的算子)

ksize:Sobel算子的大小,可选择3、5、7,默认为3。

laplacian算子:

cv2.Laplacian(src, ddepth)

src:这是输入图像

ddepth:这个参数代表输出图像的深度,即输出图像的数据类型。在 OpenCV 中,-1 表示输出图像的深度与输入图像相同。

Laplacian算子是二阶边缘检测的典型代表,一/二阶边缘检测各有优缺点,大家可自行了解。

​二、图像边缘检测

边缘检测是一套流程包括,高斯滤波,计算图像的梯度和方向,非极大值抑制,双阈值筛选。

1.高斯滤波

就是去除噪点!

边缘检测本身属于锐化操作,对噪点比较敏感,所以需要进行平滑处理。这里使用的是一个5*5的高斯核对图像进行消除噪声。

2.计算图像的梯度和方向

这里使用了sobel算子来计算图像的梯度值

3.非极大值抑制

得到每个边缘的方向之后,其实把它们连起来边缘检测就算完了,但是为什么还有这一步与下一步呢?是因为经过第二步得到的边缘不经过处理是没办法使用的,因为高斯滤波的原因,边缘会变得模糊,导致经过第二步后得到的边缘像素点非常多,因此我们需要对其进行一些过滤操作,而非极大值抑制就是一个很好的方法,它会对得到的边缘像素进行一个排除,使边缘尽可能细一点。

在该步骤中,我们需要检查每个像素点的梯度方向上的相邻像素,并保留梯度值最大的像素,将其他像素抑制为零。假设当前像素点为(x,y),其梯度方向是0°,梯度值为G(x,y),那么我们就需要比较G(x,y)与两个相邻像素的梯度值:G(x-1,y)和G(x+1,y)。如果G(x,y)是三个值里面最大的,就保留该像素值,否则将其抑制为零。

4.双阈值筛选

当某一像素位置的幅值超过最高阈值时,该像素必是边缘像素;当幅值低于最低像素时,该像素必不是边缘像素;幅值处于最高像素与最低像素之间时,如果它能连接到一个高于阈值的边缘时,则被认为是边缘像素,否则就不会被认为是边缘。

API使用:

edges = cv2.Canny(image, threshold1, threshold2),即使读到的是彩色图也可以进行处理。

image:输入的灰度/二值化图像数据。

threshold1:低阈值,用于决定可能的边缘点。

threshold2:高阈值,用于决定强边缘点。

三、绘制图像轮廓

轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。相对于边缘,轮廓是连续的,边缘不一定连续。轮廓是一个闭合的、封闭的形状。

寻找轮廓需要将图像做一个二值化处理,并且根据图像的不同选择不同的二值化方法来将图像中要绘制轮廓的部分置为白色,其余部分置为黑色。也就是说,我们需要对原始的图像进行灰度化、二值化的处理,令目标区域显示为白色,其他区域显示为黑色。

寻找轮廓函数:

contours,hierarchy = cv2.findContours(image,mode,method)

返回值:[ 轮廓点坐标 ] 和 [ 层级关系 ]。

contours:表示获取到的轮廓点的列表。检测到有多少个轮廓,该列表就有多少子列表,每一个子列表都代表了一个轮廓中所有点的坐标。

hierarchy:表示轮廓之间的关系。对于第i条轮廓,​, ​ , ​ ,​分别表示其后一条轮廓、前一条轮廓、(同层次的第一个)子轮廓、父轮廓的索引(如果没有相应的轮廓,则对应位置为-1)。该参数的使用情况会比较少。

image:表示输入的二值化图像。

mode:表示轮廓的检索模式。

method:轮廓的表示方法。

轮廓检索模式。mode参数共有四个选项分别为:RETR_LIST( 表示列出所有的轮廓。并且在hierarchy里的轮廓关系中,每一个轮廓只有前一条轮廓与后一条轮廓的索引,而没有父轮廓与子轮廓的索引),RETR_EXTERNAL(表示只查找最外层的轮廓。并且在hierarchy里的轮廓关系中,每一个轮廓只有前一条轮廓与后一条轮廓的索引,而没有父轮廓与子轮廓的索引. ),RETR_CCOMP(表示列出所有的轮廓。并且在hierarchy里的轮廓关系中,轮廓会按照成对的方式显示。 ),RETR_TREE(表示列出所有的轮廓。并且在hierarchy里的轮廓关系中,轮廓会按照树的方式显示,其中最外层的轮廓作为树根,其子轮廓是一个个的树枝.)。

轮廓存储方法。轮廓近似方法。决定如何简化轮廓点的数量。就是找到轮廓后怎么去存储这些点。

method参数有三个选项:CHAIN_APPROX_NONE、CHAIN_APPROX_SIMPLE、CHAIN_APPROX_TC89_L1。

CHAIN_APPROX_NONE表示将所有的轮廓点都进行存储

CHAIN_APPROX_SIMPLE表示只存储有用的点,比如直线只存储起点和终点,四边形只存储四个顶点,默认使用这个方法;

对于mode和method这两个参数来说,一般使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE这两个选项。

绘制轮廓函数:

cv2.drawContours(image, contours, contourIdx, color, thickness)

image:原始图像,一般为单通道或三通道的 numpy 数组。

contours:包含多个轮廓的列表,每个轮廓本身也是一个由点坐标构成的二维数组(numpy数组)。

contourIdx:要绘制的轮廓索引。如果设为 -1,则会绘制所有轮廓。根据索引找到轮廓点绘制出来。默认是-1。

color:绘制轮廓的颜色,可以是 BGR 值或者是灰度值(对于灰度图像)。

thickness:轮廓线的宽度,如果是正数,则画实线;如果是负数,则填充轮廓内的区域。

四、凸包检测

通俗的讲,凸包其实就是将一张图片中物体的最外层的点连接起来构成的凸多边形,它能包含物体中所有的内容。

一般来说,凸包都是伴随着某类点集存在的,也被称为某个点集的凸包。

对于一个点集来说,如果该点集存在凸包,那么这个点集里面的所有点要么在凸包上,要么在凸包内。

凸包检测常用在物体识别、手势识别、边界检测等领域。

获取凸包点:

cv2.convexHull(points)

points:输入参数,图像的轮廓

凸包绘制函数:

cv2.polylines(image, pts, isClosed, color, thickness=1)

image:要绘制线条的目标图像,它应该是一个OpenCV格式的二维图像数组(如numpy数组)。

pts:一个二维 numpy 数组,每个元素是一维数组,代表一个多边形的一系列顶点坐标。

isClosed:布尔值,表示是否闭合多边形,如果为 True,会在最后一个顶点和第一个顶点间自动添加一条线段,形成封闭的多边形。

color:线条颜色,可以是一个三元组或四元组,分别对应BGR或BGRA通道的颜色值,或者是灰度图像的一个整数值。

thickness(可选):线条宽度,默认值为1。

<think>嗯,用户问的是轮廓检测和边缘检测的区别以及它们的应用场景。首先我需要回顾一下这两个概念的基本定义。边缘检测通常指的是在图像中识别亮度变化明显的点,这些点通常对应物体的边界。常见的算法有Canny、Sobel、Laplacian等,这些都是通过计算梯度来找到边缘的。而轮廓检测则更侧重于找到连续的边缘点,连接成闭合的曲线,通常用于识别物体的形状。OpenCV中的findContours函数就是用来做这个的。 接下来,我需要比较它们的区别。处理对象方面,边缘检测是针对像素级别的变化,可能得到很多不连续的边缘线,而轮廓检测需要处理的是已经存在的边缘,将它们连接成有意义的轮廓处理流程上,边缘检测通常是图像预处理的一步,之后可能需要进行二值化、去噪等操作,才能进行轮廓检测。结果输出上,边缘检测输出的是边缘像素的集合,而轮廓检测输出的是结构化的轮廓数据,比如点序列。应用场景方面,边缘检测更多用于初步的特征提取,轮廓检测则用于物体识别、形状分析等高级任务。 然后要举一些实际应用的例子。比如,边缘检测在医学影像中用于器官边界识别,轮廓检测在工业检测中用于零件尺寸测量。同时,要提到它们的优缺点,比如边缘检测可能受噪声影响大,而轮廓检测依赖于前面的边缘检测质量。 还要注意用户提到的参考资料,引用中的内容提到边缘检测的不同方法适用不同场景,轮廓检测应用于人脸识别、车辆检测等。需要把这些信息整合进去,确保引用正确。 最后,生成相关问题时要围绕两者的技术细节、优化方法、结合使用场景来提问,帮助用户深入理解。例如,询问如何提高轮廓检测的准确性,或者边缘检测算法的选择因素。</think>### 轮廓检测与边缘检测的区别及应用场景 #### 1. **定义与目标** - **边缘检测**:通过算法识别图像中亮度或颜色显著变化的区域(即边缘),例如使用Canny、Sobel等算子。其输出为离散的边缘像素点集合,例如: $$ \text{梯度计算:} \nabla f = \left( \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \right) $$ 目标是提取图像中物体边界的局部特征[^1]。 - **轮廓检测**:在边缘检测基础上,通过连接连续边缘点形成闭合的曲线(轮廓),常用于描述物体的形状。例如OpenCV中的`findContours`函数,输出为结构化的轮廓点序列[^2]。 #### 2. **核心区别** | **维度** | **边缘检测** | **轮廓检测** | |-----------------|---------------------------------------|---------------------------------------| | **处理对象** | 像素级亮度变化(局部特征) | 已存在的边缘(全局结构) | | **输出形式** | 离散边缘点集合 | 闭合曲线或点序列(如多边形近似) | | **依赖关系** | 独立完成 | 需先进行边缘检测或二值化预处理 | | **应用侧重点** | 特征提取(如纹理、边界) | 物体识别、形状分析(如计算面积/周长) | #### 3. **典型应用场景** - **边缘检测**: - 医学影像中器官边界定位(如X光片骨骼边缘)。 - 自动驾驶中的车道线检测(通过Canny算法提取道路梯度变化)。 - 文本识别预处理(分离文字与背景)。 - **轮廓检测**: - **工业检测**:测量零件尺寸(通过轮廓计算面积和周长)。 - **人脸识别**:提取人脸外轮廓以对齐特征点。 - **运动追踪**:在视频中跟踪物体的动态轮廓(如手势识别)。 #### 4. **优缺点对比** - **边缘检测**: - **优点**:计算速度快,适合实时处理。 - **缺点**:易受噪声干扰(需高斯滤波预处理),输出为非结构化数据。 - **轮廓检测**: - **优点**:输出结构化数据,支持几何分析(如计算凸包)。 - **缺点**:依赖边缘检测质量,复杂场景中可能产生断裂轮廓(需形态学操作修复)。 #### 5. **技术关联性** - 边缘检测常作为轮廓检测的预处理步骤(例如先使用Canny检测边缘,再通过二值化连接轮廓)。 - 在OpenCV中,完整的轮廓检测流程通常为: ```python edges = cv2.Canny(image, threshold1, threshold2) contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值