opencv入门:Sobel算子

图像梯度

图像梯度计算的是图像变化的速度。图像边缘部分灰度值变化大,梯度值也较大,图像中平滑的部分梯度小。一般来说图像梯度计算的是图像的边缘信息。

若图像的某个线条左侧和右侧的像素值的差值不为零,那就是边界,相同就是边界。将这个运算关系进一步优化就可以获得更复杂的边缘信息。

Sobel 理论基础

Sobel 算子是一种离散的微分算子,结合高斯平滑和微分求导运算。该算子利用局部差分寻找边缘(近似等于微分),计算所得的是一个梯度的近似值。这个就是用来边缘检测的。

滤波器通常指由一幅图像根据像素点(x,y) 临近的区域计算得到另外一副新图像的算法。滤波器是由邻域及预定义的操作构成,规定了滤波时采用的形状和该区域内像素值的组成规律。滤波器也成为 掩模 ,核,模板,窗口,算子等。我们之前看到的卷积就是一种线性滤波器,滤波的目标像素值等于原始像素值及其周围像素值的加权和。这里我们用算子来表示各种滤波器。Sobel 算子就是Sobel 滤波器。
在这里插入图片描述

  1. 计算水平方向偏导数的近似值
    将 sobel算子与原始图像进行卷积计算,可以计算水平方向上像素值的变化情况。我高数学的偏导到底有什么用。。。。
    在这里插入图片描述
    计算像素点P5 的水平方向的频道上,需要实用 sobel算子及 P5 邻域点P5x = (P3-P1) + 2·(P6-P4) + (P9-P7)

就是P5右边的值减去左边的值,中间的像素点距离像素点P5近,权重较大。相关原理,女少口阿
在这里插入图片描述
2. 垂直方向偏导的近似值P5y = (P7-P1) + 2·(P8-P2) + (P9-P3)
在这里插入图片描述

Sobel算子及函数使用

dst = cv2.Sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] )

  • ddepth 输出图像的深度
  • dx, dy 代表 ,x,y 方向上的求导阶数
  • ksize Sobel 核的大小,值为-1 时,会使用 Scharr 算子进行运算
  • scale 代表计算导数值时采用的缩放因子,默认1,没有缩放
  • delta 代表加在目标图像dst 上的值,可选,默认0
参数ddepth

在这里插入图片描述
这个参数可以设置为-1,让处理几个与原图保持一致,但是这种结果可能是错误的。实际中,计算梯度值可能为负数,如果处理的图像是8位图类型,ddepth 为-1 嗲表指定运算结果是8位图类型,所有负数会自动截断为0,发生信息丢失,在计算时要先使用更高的数据类型 cv2.CV_64F,再通过取绝对值将其映射为 cv2.CV_8U 八位图类型,所以这个参数通常设置为cv2.CV_64F。

在这里插入图片描述
一个二值图,黑0白1. 当右侧像素值减去左侧像素值始得到的近似偏导数的值为-1 时就是A线条所在的列。值为1就是B线条所在的列。如果直接计算,A位置的值为负数,自动处理为0,就跟非边缘的部分一样,如果加个绝对值,就处理成1,那就可以了。

dst = cv2.convertScaleAbs( src [, alpha[, beta]] ) 位深转化函数,使用这个对参数取绝对值

  • alpha 调节系数,可选默认1
  • beta调节亮度值,默认0
  • 这个函数的作用是将原始图像是转换为256位图 dst=saturate(src*alpha+beta) saturate 表示计算结果的最大值是饱和值,

具体数据处理方式如下:

(1). 对于src*alpha+beta的结果如果是负值且大于-255,则直接取绝对值;

(2). 对于src*alpha+beta的结果如果大于255,则取255;

(3). 对于src*alpha+beta的结果是负值,且小于-255,则取255;

(4). 对于src*alpha+beta的结果如果在0-255之间,则保持不变;

img=np.random.randint(-256,256,size=[4,5],dtype=np.int16)
rst=cv2.convertScaleAbs(img)
print("img=\n",img)
print("rst=\n",rst)

img=
 [[ 147 -106  249  188 -132]
 [-225   56 -112 -116 -123]
 [  -6  146  143 -134   60]
 [-158 -160  130 -225 -240]]
rst=
 [[147 106 249 188 132]
 [225  56 112 116 123]
 [  6 146 143 134  60]
 [158 160 130 225 240]]
方向

在函数cv2.Sobel() 中参数 dx dy 表示 x,y轴方向的求导阶数,通常的值为0或1.最大值为2.0表示再该方向上不求导,当然这两个参数不能同时为零.,一下的参数也可以是2.

  1. 计算x 方向边缘(梯度) dx=1, dy=0, 只计算水平方向的边缘。
  2. 计算y方向边缘(梯度):dx=0,dy=1 ,
  3. 参数dx与参数dy的值均为 1:dx=1,dy=1 ,这个获得的图不明显,只可以看到一些小白点,每个点的大小都是一个像素
  4. 计算x方向和y方向的边缘叠加
dx= cv2.Sobel( src , ddepth , 1 , 0 )    # 叠加方式,分别获取两个方向的边缘图,然后相加
dy= cv2.Sobel( src , ddepth , 0 , 1 )
dst=cv2.addWeighted( src1 , alpha , src2 , beta , gamma )
实例
o=cv2.imread('13.jpg',0) # 读为单通道灰度图
Sobelx=cv2.Sobel(o,-1,1,0)  # 深度为原图的8位图像
cv2.imshow("original",o)
cv2.imshow("x",Sobelx)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
可以看到只获得黑色框的右边界,因为左边界运算得到了负值,被处理成0就没有显示,y轴方向的一样。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

o = cv2.imread('5.jpg',0)
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) 
Sobelxy11=cv2.Sobel(o,cv2.CV_64F,1,1)
Sobelxy11=cv2.convertScaleAbs(Sobelxy11) 
cv2.imshow("original",o)
cv2.imshow("xy",Sobelxy)
cv2.imshow("xy11",Sobelxy11)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
效果 针不戳,,,当然彩图也是可以的,就是得到的轮廓不是黑白。。。

祝我明天四级过过过 !!!!!!!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值