OpenCV学习笔记(七)——图像梯度及边缘检测
图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯度值也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。一般情况下,图像梯度计算的是图像的边缘信息。
Canny 边缘检测是一种使用多级边缘检测算法检测边缘的方法。1986 年,John F. Canny 发表了著名的论文A Computational Approach to Edge Detection,在该论文中详述了如何进行边缘检测。OpenCV提供了函数cv2.Canny()实现Canny边缘检测。
《OpenCV轻松入门:面向Python》学习笔记(七)
- 一. 图像梯度
- 1.1 Sobel理论基础
- 1.1.1 水平方向偏导数近似值计算
- 1.1.2 垂直方向偏导数近似值计算
- 1.2 Sobel算子及函数应用
- 1.2.1 参数ddepth
- 1.2.2 方向
- 1.3 Scharr 算子及函数使用
- 1.4 Sobel算子和Scharr算子的比较
- 1.5 Laplacian算子及函数使用
- 二. 边缘检测
- 2.1 边缘检测基础
- 2.2 Canny函数及使用
一. 图像梯度
1.1 Sobel理论基础
Sobel 算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。
1.1.1 水平方向偏导数近似值计算
如果要计算像素点P5 的水平方向偏导数P5x,则需要利用Sobel 算子及P5邻域点,所使用的公式为:
P5x = (P3-P1) + 2·(P6-P4) + (P9-P7)
1.1.2 垂直方向偏导数近似值计算
如果要计算像素点P5 的垂直方向偏导数P5y,则需要利用Sobel 算子及P5 邻域点,所使用的公式为:
P5y = (P7-P1) + 2·(P8-P2) + (P9-P3)
1.2 Sobel算子及函数应用
dst = cv2.Sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] )
- dst 代表目标图像。
- src 代表原始图像。
- ddepth 代表输出图像的深度。其具体对应关系如表所示。
- dx 代表x方向上的求导阶数。
- dy 代表y方向上的求导阶数。
- ksize 代表Sobel核的大小。该值为-1时,则会使用Scharr算子进行运算。
- scale 代表计算导数值时所采用的缩放因子,默认情况下该值是1,是没有缩放的。
- delta 代表加在目标图像dst 的值,该值是可选的,默认为0。
- borderType 代表边界样式。
1.2.1 参数ddepth
在实际操作中,计算梯度值可能会出现负数。通常处理的图像是8 位图类型,如果结果也是该类型,那么所有负数会自动截断为0,发生信息丢失。所以,为了避免信息丢失,我们在计算时使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U(8位图)类型。
在 OpenCV 中,使用函数cv2.convertScaleAbs()对参数取绝对值,该函数的语法格式为:
dst = cv2.convertScaleAbs( src [, alpha[, beta]] )
- dst 代表处理结果。
- src 代表原始图像。
- alpha 代表调节系数,该值是可选值,默认为1。
- beta 代表调节亮度值,该值是默认值,默认为0。
1.2.2 方向
参数 dx和参数dy可以有多种形式的组合,主要包含:
计算x方向边缘(梯度):dx=1, dy=0。
计算y方向边缘(梯度):dx=0, dy=1。
参数dx与参数dy的值均为1:dx=1, dy=1。
计算x方向和y方向的边缘叠加
dx= cv2.Sobel( src , ddepth , 1 , 0 )
dy= cv2.Sobel( src , ddepth , 0 , 1 )
dst=cv2.addWeighted( src1 , alpha , src2 , beta , gamma )
1.3 Scharr 算子及函数使用
OpenCV 提供了Scharr 算子,该算子具有和Sobel 算子同样的速度,且精度更高。可以将Scharr 算子看作对Sobel 算子的改进。
dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
- 参数及使用方法与Sobel算子相同。
- 需要注意的是,参数dx和dy的值不能都为1。
1.4 Sobel算子和Scharr算子的比较
Sobel 算子的缺点是,当其核结构较小时,精确度不高,而Scharr 算子具有更高的精度。
import cv2
o = cv2.imread('lena.bmp',cv2.IMREAD_GRAYSCALE)
Sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
Sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
Sobelx = cv2.convertScaleAbs(Sobelx)
Sobely = cv2.convertScaleAbs(Sobely)
Sobelxy = cv2.addWeighted(Sobelx,0.5,Sobely,0.5,0)
Scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
Scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
Scharrx = cv2.convertScaleAbs(Scharrx)
Scharry = cv2.convertScaleAbs(Scharry)
Scharrxy = cv2.addWeighted(Scharrx,0.5,Scharry,0.5,0)
cv2.imshow("original",o)
cv2.imshow("Sobelxy",Sobelxy)
cv2.imshow("Scharrxy",Scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()
1.5 Laplacian算子及函数使用
Laplacian(拉普拉斯)算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测)的要求。通常情况下,其算子的系数之和需要为零。
计算像素点P5 的近似导数值,如下:
P5lap = (P2 + P4 + P6 + P8) - 4·P5
需要注意,在上述图像中,计算结果的值可能为正数,也可能为负数。所以,需要对计算结果取绝对值,以保证后续运算和显示都是正确的。
dst = cv2.Laplacian( src, ddepth[, ksize[, scale[, delta[, borderType]]]] )
- dst 代表目标图像。
- src 代表原始图像。
- ddepth 代表目标图像的深度。
- ksize 代表用于计算二阶导数的核尺寸大小。该值必须是正的奇数。
- scale 代表计算Laplacian值的缩放比例因子,该参数是可选的。默认情况下,该值为1,表示不进行缩放。
- delta 代表加到目标图像上的可选值,默认为0。
- borderType 代表边界样式。
import cv2
o = cv2.imread('Laplacian.bmp',cv2.IMREAD_GRAYSCALE)
Laplacian = cv2.Laplacian(o,cv2.CV_64F)
Laplacian = cv2.convertScaleAbs(Laplacian)
cv2.imshow("original",o)
cv2.imshow("Laplacian",Laplacian)
cv2.waitKey()
cv2.destroyAllWindows()
二. 边缘检测
2.1 边缘检测基础
Canny 边缘检测分为如下几个步骤。
- 去噪。噪声会影响边缘检测的准确性,因此首先要将噪声过滤掉。
由于图像边缘非常容易受到噪声的干扰,因此为了避免检测到错误的边缘信息,通常需要对图像进行滤波以去除噪声。滤波的目的是平滑一些纹理较弱的非边缘区域,以便得到更准确的边缘。在实际处理过程中,通常采用高斯滤波去除图像中的噪声。
- 计算梯度的幅度与方向。
前面我们介绍了如何计算图像梯度的幅度。在这里,我们关注梯度的方向,梯度的方向与边缘的方向是垂直的,通常就近取值为水平(左、右)、垂直(上、下)、对角线(右上、左上、左下、右下)等8 个不同的方向。因此,在计算梯度时,我们会得到梯度的幅度和角度(代表梯度的方向)两个值。
- 非极大值抑制,即适当地让边缘“变瘦”。
在获得了梯度的幅度和方向后,遍历图像中的像素点,去除所有非边缘的点。在具体实现时,逐一遍历像素点,判断当前像素点是否是周围像素点中具有相同梯度方向的最大值,并根据判断结果决定是否抑制该点。通过以上描述可知,该步骤是边缘细化的过程。针对每一个像素点:
(1) 如果该点是正/负梯度方向上的局部最大值,则保留该点。
(2) 如果不是,则抑制该点(归零)。
经过比较判断可知,A 点具有最大的局部值,所以保留A 点(称为边缘),其余两点(B和C)被抑制(归零)。
经过上述处理后,对于同一个方向的若干个边缘点,基本上仅保留了一个,因此实现了边缘细化的目的。
- 确定边缘。使用双阈值算法确定最终的边缘信息。
设置两个阈值,其中一个为高阈值maxVal,另一个为低阈值minVal。根据当前边缘像素的梯度值(指的是梯度幅度,下同)与这两个阈值之间的关系,判断边缘的属性。具体步骤为:
(1)如果当前边缘像素的梯度值大于或等于maxVal,则将当前边缘像素标记为强边缘。
(2)如果当前边缘像素的梯度值介于maxVal 与minVal 之间,则将当前边缘像素标记为虚
边缘(需要保留)。
(3)如果当前边缘像素的梯度值小于或等于minVal,则抑制当前边缘像素。
在上述过程中,我们得到了虚边缘,需要对其做进一步处理。一般通过判断虚边缘与强边
缘是否连接,来确定虚边缘到底属于哪种情况。通常情况下,如果一个虚边缘:
(1)与强边缘连接,则将该边缘处理为边缘。
(2)与强边缘无连接,则该边缘为弱边缘,将其抑制。
2.2 Canny函数及使用
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
- edges 为计算得到的边缘图像。
- image 为8位输入图像。
- threshold1 表示处理过程中的第一个阈值。
- threshold2 表示处理过程中的第二个阈值。
- apertureSize 表示Sobel算子的孔径大小。
- L2gradient 为计算图像梯度幅度(gradient magnitude)的标识。其默认值为False。如果为True,则使用更精确的L2 范数进行计算(即两个方向的导数的平方和再开方),否则使用L1 范数(直接将两个方向导数的绝对值相加)。
import cv2
o=cv2.imread("lena.bmp",cv2.IMREAD_GRAYSCALE)
r1=cv2.Canny(o,128,200)
r2=cv2.Canny(o,32,128)
cv2.imshow("original",o)
cv2.imshow("result1",r1)
cv2.imshow("result2",r2)
cv2.waitKey()
cv2.destroyAllWindows()
从程序运行结果可知,当函数cv2.Canny()的参数threshold1和threshold2的值较小时,能够捕获更多的边缘信息。
OpenCV学习笔记(七)——图像梯度及边缘检测相关推荐
- Opencv学习笔记七(梯度算子、锐化)
Sobel算子 卷积的作用除了实现图像模糊或者去噪,还可以寻找一张图像上所有梯度信息,这些梯度信息是图像的最原始特征数据,进一步处理之后就可以生成一些比较高级.抽象的特征用来表示一张图像实现基于图像特 ...
- python怎么计算图像梯度_Opencv-Python学习笔记十——图像梯度、边缘检测 Gradient, Edge Detection...
图像梯度 边缘检测 图像梯度,图像边界 使用到的函数有: cv2.Sobel(), cv2.Schar(), cv2.Laplacian() 梯度简单来说就是求导,OpenCV 提供了三种不同的梯度滤 ...
- opencv学习笔记(六)---图像梯度
图像梯度的算法有很多方法:sabel算子,scharr算子,laplacian算子,sanny边缘检测(下个随笔)... 这些算子的原理可参考:https://blog.csdn.net/poem_q ...
- Opencv学习笔记(八) -- 图像色彩空间转换
1.常见图像色彩空间 RGB RGB色彩模式是工业界的一种颜色标准,是通过对红(R).绿(G).蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红.绿.蓝三个通道 ...
- OpenCV中的图像处理 —— 图像梯度+Canny边缘检测+图像金字塔
OpenCV中的图像处理 -- 图像梯度+Canny边缘检测+图像金字塔 目录 OpenCV中的图像处理 -- 图像梯度+Canny边缘检测+图像金字塔 1. 图像梯度 1.1 Sobel和Schar ...
- C++下opencv学习笔记(一)(图像的简单读取丶显示与存储)
C++下opencv学习笔记(一)(图像的简单读取丶显示与存储) 前言 学习C++ OpenCV,第一需要具备面向对象语言的基础,第二要对图像处理机器学习有基础了解,容易入门.觉得自己基础已经有了可以 ...
- OpenCV学习笔记(九)——图像轮廓(下)
<OpenCV轻松入门:面向Python>学习笔记(九) 1-3 查找并绘制轮廓.矩特性及Hu矩 4-5 轮廓拟合及凸包 6. 利用形状场景算法比较轮廓 6.1 计算形状场景距离 6.2 ...
- opencv学习笔记18:canny算子边缘检测原理及其函数使用
canny边缘检测原理 去噪:边缘检测容易受到噪声的影响,在此之间,先去噪,通常采用高斯滤波器.opencv学习笔记11:图像滤波(均值,方框,高斯,中值) 梯度:对去噪后的图像采用sobel算子计算 ...
- opencv学习笔记17:梯度运算之laplacian算子及其应用
laplacian算子理论 前文介绍了sobel算子及其函数使用 和scharr算子及其函数使用 使用方法 不同算子比较 sobel,和scharr算子:右边121列-左边121列.右边-3,10,3 ...
最新文章
- 【嵌入式】openmv与stm32的串口通信
- 智能硬件这5大领域竞争升级,将迎发展新模式
- 分布式计算Hadoop系列之如何修改Eclipse插件
- Java-Web 编码和路径
- 使用tensorflow书写逻辑回归
- Java8 HashMap 扩容机制与线程安全分析
- MySql - GROUP BY 和 HAVING关键字
- matlab cell向量匹配向量,根据2个cell格式数据中的某二列进行匹配并合并
- Vim设置支持鼠标,光标定位,滚轮上下移动
- Linux学习私人笔记-Vim
- docker-compose+postsql多容器部署django-vue项目
- 审计小trick结合
- Elasticsearch Guide[7.15]翻译 Aliases
- 佛罗里达大学计算机科学,佛罗里达大学计算机工程硕士专业排名最全内幕详尽分析...
- Python爬取京东:价格、商品ID、标题、评价、店名、是否自营
- Spring boot集成Redis实现sessions共享时,sessions过期时间问题分析
- 计算机网络知识(看这篇就够啦)
- Proteus8.12 基于51单片机的家用供暖系统
- 数据解读:都知道《隐秘的角落》火了,它到底怎么火的?
- 【ELT.ZIP】OpenHarmony啃论文俱乐部——人工智能短字符串压缩
热门文章
- 友善之臂NanoPC-T4嵌入式开发板 开箱
- 全国计算机等级考试二级教程——c语言程序设计》,格式为doc.,《全国计算机等级考试二级教程C语言程序设计》汇编.doc...
- 有关BlackBerry app 数字签名
- 紫光展锐的春天来了吗?
- python 设置精度_在python中以全微秒精度设置文件的mtime
- nano的CAN通信
- 一个简单的电梯状态模型
- [软件] 装机员Ghost Win10 RS1 1067 64位纯净贺岁版2017
- android屏幕适配的目的,剖析Android屏幕适配及各方案
- 计算机毕业设计各种题目总结