如何掌握opencv图像梯度,有哪些知识点
Admin 2022-08-13 群英技术资讯 335 次浏览
图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯度值也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。图像梯度计算需要求导数,但是图像梯度一般通过计算像素值的差来得到梯度的近似值(近似导数值)。(差分,离散)
Sobel算子、Scharr算子和Laplacian算子的使用。
Sobel算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。
滤波器通常是指由一幅图像根据像素点(x, y)临近的区域计算得到另外一幅新图像的算法。
滤波器是由邻域及预定义的操作构成的,滤波器规定了滤波时所采用的形状以及该区域内像素值的组成规律。滤波器也被称为“掩模”、“核”、“模板”、“窗口”、“算子”等。一般信号领域将其称为“滤波器”,数学领域将其称为“核”。
线性滤波器: 滤波的目标像素点的值等于原始像素值及其周围像素值的加权和。这种基于线性核的滤波,就是所熟悉的卷积。
将Sobel算子与原始图像src进行卷积计算,可以计算水平方向上的像素值变化情况。
例如,当Sobel算子的大小为3×3时,水平方向偏导数Gx的计算方式为:
当Sobel算子的大小为3×3时,垂直方向偏导数Gy的计算方式为:
使用函数cv2.Sobel()实现Sobel算子运算,其语法形式为:
dst = cv2.Sobel( src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]] )
注意点:参数ddepth
在函数cv2.Sobel()的语法中规定,可以将函数cv2.Sobel()内ddepth参数的值设置为-1,让处理结果与原始图像保持一致。但是,如果直接将参数ddepth的值设置为-1,在计算时得到的结果可能是错误的。
在实际操作中,计算梯度值可能会出现负数。如果处理的图像是8位图类型,则在ddepth的参数值为-1时,意味着指定运算结果也是8位图类型,那么所有负数会自动截断为0,发生信息丢失。为了避免信息丢失,在计算时要先使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U(8位图)类型。
通常要将函数cv2.Sobel()内参数ddepth的值设置为“cv2.CV_64F”。要将偏导数取绝对值,以保证偏导数总能正确地显示出来。在OpenCV中,使用函数cv2.convertScaleAbs()对参数取绝对值,
该函数的语法格式为:
dst = cv2.convertScaleAbs( src [, alpha[, beta]] )
该函数的作用是将原始图像src转换为256色位图,其可以表示为:
dst=saturate(src*alpha+beta)
式中,saturate()表示计算结果的最大值是饱和值,例如: 当“src*alpha+beta”的值超过255时,其取值为255。
**例子:**使用函数cv2.convertScaleAbs()对一个随机数组取绝对值。
import cv2 import numpy as np img=np.random.randint(-256,256, size=[4,5], dtype=np.int16) rst=cv2.convertScaleAbs(img) print("img=\n", img) print("rst=\n", rst)
在函数cv2.Sobel()中,参数dx表示x轴方向的求导阶数,参数dy表示y轴方向的求导阶数。参数dx和dy通常的值为0或者1,最大值为2。如果是0,表示在该方向上没有求导。当然,参数dx和参数dy的值不能同时为0。
参数dx和参数dy可以有多种形式的组合,主要包含:
例子
“dx=1, dy=0”。当然,也可以设置为“dx=2, dy=0”。此时,会仅仅获取垂直方向的边缘信息,
此时的语法格式为:
dst = cv2.Sobel( src , ddepth , 1 , 0 )
“dx=0, dy=1”。当然,也可以设置为“dx=0, dy=2”。此时,会仅仅获取水平方向的边缘信息,
此时的语法格式为:
dst = cv2.Sobel( src , ddepth , 0 , 1 )
“dx=1, dy=1”,也可以设置为“dx=2, dy=2”,或者两个参数都不为零的其他情况。此时,会获取两个方向的边缘信息,
此时的语法格式为:
dst = cv2.Sobel( src , ddepth , 1 , 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 )
例子:
使用函数cv2.Sobel()获取图像水平方向的完整边缘信息
将参数ddepth的值设置为cv2.CV_64F,并使用函数cv2.convertScaleAbs()对cv2.Sobel()的计算结果取绝对值。
import cv2 o = cv2.imread('Sobel4.bmp', cv2.IMREAD_GRAYSCALE) Sobelx = cv2.Sobel(o, cv2.CV_64F,0,1) Sobelx = cv2.convertScaleAbs(Sobelx) cv2.imshow("original", o) cv2.imshow("x", Sobelx) cv2.waitKey() cv2.destroyAllWindows()
计算函数cv2.Sobel()在水平、垂直两个方向叠加的边缘信息。
import cv2 o = cv2.imread('Sobel4.bmp', cv2.IMREAD_GRAYSCALE) Sobelx = cv2.Sobel(o, cv2.CV_64F,1,0) Sobely = cv2.Sobel(o, cv2.CV_64F,0,1) Sobelx = cv2.convertScaleAbs(Sobelx) Sobely = cv2.convertScaleAbs(Sobely) Sobelxy = cv2.addWeighted(Sobelx,0.5, Sobely,0.5,0) cv2.imshow("original", o) cv2.imshow("xy", Sobelxy) cv2.waitKey() cv2.destroyAllWindows()
在离散的空间上,有很多方法可以用来计算近似导数,在使用3×3的Sobel算子时,可能计算结果并不太精准。
OpenCV提供了Scharr算子,该算子具有和Sobel算子同样的速度,且精度更高。
可以将Scharr算子看作对Sobel算子的改进,其核通常为:
OpenCV提供了函数cv2.Scharr()来计算Scharr算子,其语法格式如下:
dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
在函数cv2.Sobel()中,如果ksize=-1,则会使用Scharr滤波器。
如下语句:
dst=cv2.Scharr(src, ddepth, dx, dy)
和
dst=cv2.Sobel(src, ddepth, dx, dy, -1)
是等价的。函数cv2.Scharr()和函数cv2.Sobel()的使用方式基本一致。参数ddepth的值应该设置为“cv2.CV_64F”,并对函数cv2.Scharr()的计算结果取绝对值,才能保证得到正确的处理结果。
具体语句为:
dst=Scharr(src, cv2.CV_64F, dx, dy) dst= cv2.convertScaleAbs(dst)
在函数cv2.Scharr()中,要求参数dx和dy满足条件:
参数dx和参数dy的组合形式有:
例子
计算x方向边缘(梯度):dx=1, dy=0
dst=Scharr(src, ddpeth, dx=1, dy=0)
计算y方向边缘(梯度):dx=0, dy=1
dst=Scharr(src, ddpeth, dx=0, dy=1)
计算x方向与y方向的边缘叠加
将两个方向的边缘相加
dx=Scharr(src, ddpeth, dx=1, dy=0) dy=Scharr(src, ddpeth, dx=0, dy=1) Scharrxy=cv2.addWeighted(dx,0.5, dy,0.5,0)
参数dx和dy的值不能都为1
Sobel算子的缺点是,当其核结构较小时,精确度不高,而Scharr算子具有更高的精度。
Sobel算子和Scharr算子的核结构:
Laplacian(拉普拉斯)算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测)的要求。
通常情况下,其算子的系数之和需要为零。
一个3×3大小的Laplacian算子
Laplacian算子类似二阶Sobel导数,需要计算两个方向的梯度值。
计算结果的值可能为正数,也可能为负数。所以,需要对计算结果取绝对值,以保证后续运算和显示都是正确的。
在OpenCV内使用函数cv2.Laplacian()实现Laplacian算子的计算,该函数的语法格式为:
dst = cv2.Laplacian( src, ddepth[, ksize[, scale[, delta[, borderType]]]] )
该函数分别对x、y方向进行二次求导,具体为:
上式是当ksize的值大于1时的情况。当ksize的值为1时,Laplacian算子计算时采用的3×3的核如下:
通过从图像内减去它的Laplacian图像,可以增强图像的对比度,此时其算子为:
例子: 使用函数cv2.Laplacian()计算图像的边缘信息。
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()
Sobel算子、Scharr算子、Laplacian算子都可以用作边缘检测
Sobel算子和Scharr算子计算的都是一阶近似导数的值。通常情况下,可以将它们表示为:
Laplacian算子计算的是二阶近似导数值,可以将它表示为:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
第一种,利用functools工具,调用reduce()函数求阶乘。||第二种,使用for循环来求阶乘。||第三种,直接定义一个阶乘函数func(),利用递归的方式来求阶乘即可。
文中详细整理了关于Python模块和包的相关知识点,刚入门Python的小伙伴们可以学习一下,有助于加深Python基础的理解.而且有详细说明及代码示例,需要的朋友可以参考下
playwright-python是一个强大的Python库,仅用一个API即可自动执行Chromium、Firefox、WebKit等主流浏览器自动化操作,本文就详细的介绍一下如何使用,感兴趣的可以了解一下
python的jieba库干什么的?一些刚接触Python的朋友可能对jieba库不是很了解,因此这篇文章就给大家来介绍一下,jieba库的作用、jieba库的安装以及jieba库的使用,感兴趣的朋友就继续往下看吧。
Python函数-complex()。complex() 函数用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008