图像处理之图像梯度(python实现)

图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯度值也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。一般情况下,图像梯度计算的是图像的边缘信息。

1.Sobel算子

1.1Sobel理论基础

在点f(x,y)处,f(x,y)的梯度为
∇ f ( x , y ) = [ G x   G y ] T = [ ∂ f ∂ x   ∂ f ∂ y ] T = ( G x 2 + G y 2 ) \nabla f(x,y)=[G_{x} \ G_{y}]^T=[\frac{\partial f}{\partial x} \ \frac{\partial f}{\partial y}]^T=\sqrt{(G_{x}^2+G_{y}^2)} f(x,y)=[Gx Gy]T=[xf yf]T=(Gx2+Gy2)

G x = f ( x + 1 , y ) − f ( x − 1 , y ) 2 G y = f ( x , y + 1 ) − f ( x , y − 1 ) 2 G_{x}=\frac{f(x+1,y)-f(x-1,y)}{2}\\ G_{y}=\frac{f(x,y+1)-f(x,y-1)}{2} Gx=2f(x+1,y)f(x1,y)Gy=2f(x,y+1)f(x,y1)

1.1.1计算水平方向偏导数的近似值

当Sobel算子与原始图像src进行卷积计算,可以计算水平方向上的像素变化情况,水平方向偏导数 G x G_{x} Gx的计算方式为:
G x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] ∗ s c r G_x= \left [ \begin{matrix} -1&0&1\\ -2&0&2\\ -1&0&1 \end{matrix} \right]*scr Gx= 121000121 scr
上式中,scr为原始图像。假设其中有9个像素点,如图所示。
G x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] ∗ [ P 1 P 2 P 3 P 4 P 5 P 6 P 7 P 8 P 9 ] G_x=\left [ \begin{matrix} -1&0&1\\ -2&0&2\\ -1&0&1 \end{matrix} \right]* \left [ \begin{matrix} P_1&P_2&P_3\\ P_4&P_5&P_6\\ P_7&P_8&P_9 \end{matrix} \right] Gx= 121000121 P1P4P7P2P5P8P3P6P9
则可得像素点 P 5 P_5 P5的水平方向偏导数为:
P 5 x = ( P 3 − P 1 ) + 2 ∗ ( P 6 − P 4 ) + ( P 9 − P 7 ) P_5x=(P_3-P_1)+2*(P_6-P_4)+(P_9-P_7) P5x=(P3P1)+2(P6P4)+(P9P7)
即用像素点 P 5 P_5 P5右侧像素点的值减去左侧像素点的值,其中,中间像素点距离像素点 P 5 P_5 P5较近,其像素值差值的权重为2,其余差值权重均为1.

1.1.2计算垂直方向偏导数的近似值

当Sobel算子与原始图像src进行卷积计算,可以计算垂直方向上的像素变化情况,垂直方向偏导数 G y G_{y} Gy的计算方式为:
G y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] ∗ s c r G_y= \left [ \begin{matrix} -1&-2&-1\\ 0&0&0\\ 1&2&1 \end{matrix} \right]*scr Gy= 101202101 scr
上式中,scr为原始图像。假设其中有9个像素点,如图所示。
G y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] ∗ [ P 1 P 2 P 3 P 4 P 5 P 6 P 7 P 8 P 9 ] G_y=\left [ \begin{matrix} -1&-2&-1\\ 0&0&0\\ 1&2&1 \end{matrix} \right]* \left [ \begin{matrix} P_1&P_2&P_3\\ P_4&P_5&P_6\\ P_7&P_8&P_9 \end{matrix} \right] Gy= 101202101 P1P4P7P2P5P8P3P6P9
则可得像素点 P 5 P_5 P5的垂直方向偏导数为:
P 5 y = ( P 7 − P 1 ) + 2 ∗ ( P 8 − P 2 ) + ( P 9 − P 3 ) P_5y=(P_7-P_1)+2*(P_8-P_2)+(P_9-P_3) P5y=(P7P1)+2(P8P2)+(P9P3)
即用像素点 P 5 P_5 P5下一行像素点的值减去上一行像素点的值,其中,中间像素点距离像素点 P 5 P_5 P5较近,其像素值差值的权重为2,其余差值权重均为1.

1.1.3水平方向偏导数和垂直方向偏导数叠加

∇ f ( x , y ) = ( G x 2 + G y 2 ) \nabla f(x,y)=\sqrt{(G_{x}^2+G_{y}^2)} f(x,y)=(Gx2+Gy2)

1.2自定义函数实现

import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
import time
plt.rcParams['font.sans-serif']=['SimHei'] 

def Sobel(img,filter1,filter2):
    b=time.time()
    h,w=img.shape[:2]
    new_img=np.zeros((h+2,w+2),np.uint8)
    new_img[1:h+1,1:w+1]=img#填充
    out=[]
    for i in range(1,h+1):
        for j in range(1,w+1):
            dx=np.sum(np.multiply(new_img[i-1:i+2,j-1:j+2],filter1))
            dy=np.sum(np.multiply(new_img[i-1:i+2,j-1:j+2],filter2))
            out.append(
                np.clip(int(np.sqrt(dx**2+dy**2)),0,255)
            )
    out=np.array(out).reshape(h,w)
    e=time.time()
    print(e-b)
    return out

if __name__=="__main__":
    path="D:\\code\\python\\opencv\\lena.jpg"
    img=cv.imread(path,0)
    filter1=np.array([
        [-1,0,1],
        [-2,0,2],
        [-1,0,1]
    ])
    filter2=np.array([
        [-1,-2,-1],
        [0,0,0],
        [1,2,1]
    ])
    # img=np.array([
    #     [0,0,1,255,254,254,254],
    #     [1,1,1,254,253,254,254],
    #     [0,0,0,255,255,253,253],
    #     [1,1,0,254,254,254,254]
    # ],dtype=np.uint8)
    plt.figure(figsize=(6,8))
    plt.subplot(121)
    plt.imshow(Sobel(img,filter1,filter2),cmap='gray')
    plt.title('自定义函数')
    
   
    

1.3Opencv函数

在Opencv内,使用函数cv2.Sobel()实现Sobel算子运算:
dst=cv2.Sobel(src,ddepth,dx,dy)

  • dst代表目标图像
  • src代表原始图像
  • ddepth代表输出图像深度(通常设置为"cv2.CV_64F")
  • dx代表x方向上的求导阶数
  • dy代表y方向上的求导阶数

示例代码:

sobley=cv.Sobel(img,cv.CV_64F,0,1)
soblex=cv.Sobel(img,cv.CV_64F,1,0) 

为得到结果为正数的偏导数,需要对Sobel函数求出的偏导数取绝对值,在Opencv中,使用函数cv2.convertScaleAbs()对参数取绝对值,即
dst=cv2.convertScaleAbs(src)

  • dst代表处理结果
  • src代表原始图像

示例代码:

absy=cv.convertScaleAbs(sobley)

如果想要获取x方向和y方向的边缘叠加,需要将水平方向和垂直方向的边缘图进行相加,在Opencv中,使用函数cv2.addweighted()进行叠加,即:

扫描二维码关注公众号,回复: 15546413 查看本文章
dst=cv2.addweighted(src1,alpha,src2,gamma)
  • dst代表处理结果
  • src1代表原始图像1
  • alpha代表src1的叠加权重
  • src2代表原始图像2
  • gamma代表src2的叠加权重

示例代码:

dst=cv.addWeighted(absx,0.5,absy,0.5,0)

1.4总体代码

import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
import time
plt.rcParams['font.sans-serif']=['SimHei'] 

def Sobel(img,filter1,filter2):
    b=time.time()
    h,w=img.shape[:2]
    new_img=np.zeros((h+2,w+2),np.uint8)
    new_img[1:h+1,1:w+1]=img#填充
    out=[]
    for i in range(1,h+1):
        for j in range(1,w+1):
            dx=np.sum(np.multiply(new_img[i-1:i+2,j-1:j+2],filter1))
            dy=np.sum(np.multiply(new_img[i-1:i+2,j-1:j+2],filter2))
            out.append(
                np.clip(int(np.sqrt(dx**2+dy**2)),0,255)
            )
    out=np.array(out).reshape(h,w)
    e=time.time()
    print(e-b)
    return out

if __name__=="__main__":
    path="D:\\code\\python\\opencv\\lena.jpg"
    img=cv.imread(path,0)
    filter1=np.array([
        [-1,0,1],
        [-2,0,2],
        [-1,0,1]
    ])
    filter2=np.array([
        [-1,-2,-1],
        [0,0,0],
        [1,2,1]
    ])
    # img=np.array([
    #     [0,0,1,255,254,254,254],
    #     [1,1,1,254,253,254,254],
    #     [0,0,0,255,255,253,253],
    #     [1,1,0,254,254,254,254]
    # ],dtype=np.uint8)
    plt.figure(figsize=(6,8))
    plt.subplot(121)
    plt.imshow(Sobel(img,filter1,filter2),cmap='gray')
    plt.title('自定义函数')
    
    sobelx =cv.Sobel(img,cv.CV_64F,1,0)
    absx=cv.convertScaleAbs(sobelx)
    
    sobley=cv.Sobel(img,cv.CV_64F,0,1)
    absy=cv.convertScaleAbs(sobley)
    dst=cv.addWeighted(absx,0.5,absy,0.5,0)
    plt.subplot(122)
    plt.imshow(dst,cmap='gray')
    plt.title('opencv函数')
    plt.show()
    

1.5结果对比图

自定义函数与库函数

2.Laplacian算子

Laplacian算子(拉普拉斯)是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测)的要求。通常情况下,其算子的系数之和需要为零。例如,一个3x3大小的Laplacian算子如下所示。
[ 0 1 0 1 − 4 1 0 1 0 ] \left[ \begin{matrix} 0 &1&0\\ 1&-4&1\\ 0&1&0 \end{matrix} \right] 010141010
Laplacian算子类似二阶Sobel导数,需要计算两个方向的梯度值。例如:
L a p = [ 0 1 0 1 − 4 1 0 1 0 ] ∗ [ P 1 P 2 P 3 P 4 P 5 P 6 P 7 P 8 P 9 ] Lap=\left [ \begin{matrix} 0&1&0\\ 1&-4&1\\ 0&1&0 \end{matrix} \right]* \left [ \begin{matrix} P_1&P_2&P_3\\ P_4&P_5&P_6\\ P_7&P_8&P_9 \end{matrix} \right] Lap= 010141010 P1P4P7P2P5P8P3P6P9
则可得像素点 P 5 P_5 P5的近似导数值为:
P 5 l a p = ( P 2 + P 4 + P 6 + P 8 ) − 4 ⋅ P 5 P_5lap=(P_2+P_4+P_6+P_8)-4·P_5 P5lap=(P2+P4+P6+P8)4P5

2.1.Opencv函数

在Opencv内使用函数cv2.Laplacian()实现Laplacian算子的计算,该函数的语法格式为:

dst=cv2.Laplacian(src,ddepth,ksize)
  • dst代表目标图像
  • src代表原始图像
  • ddepth代表输出图像深度(通常设置为"cv2.CV_64F")
  • ksize代表核尺寸大小,该值必须为正的奇数。

2.2函数实现

	path='D:\\code\\python\\opencv\\lena.jpg'
    img=cv.imread(path,0)
    plt.imshow(cv.Laplacian(img,cv.CV_64F),cmap='gray')
    plt.title('Opencv')
    plt.show()

2.3计算结果

laplacian

猜你喜欢

转载自blog.csdn.net/m0_53192838/article/details/127415508