Image gradient for image processing (python implementation)

The image gradient calculates the speed at which the image changes. For the edge part of the image, the gray value changes greatly, and the gradient value is also large; on the contrary, for the smooth part of the image, the gray value changes small, and the corresponding gradient value is also small. In general, the image gradient calculation is the edge information of the image.

1. Sobel operator

1.1 Sobel Theoretical Basis

在点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 Calculating the approximate value of the partial derivative in the horizontal direction

When the Sobel operator performs convolution calculation with the original image src, the pixel change in the horizontal direction can be calculated, and the horizontal partial derivative G x G_{x}GxThe calculation method is:
G x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] ∗ scr G_x= \left [ \begin{matrix} -1&0&1\\ -2&0&2\\ -1&0&1 \end{matrix} \ right]*scrGx= 121000121 scr
In the above formula, scr is the original image. Suppose there are 9 pixels in it, as shown in the figure.
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
Then the pixel point P 5 P_5 can be obtainedP5The horizontal partial derivative of is:
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)
is the pixel pointP 5 P_5P5The value of the pixel on the right minus the value of the pixel on the left, where the middle pixel is 5 P_5 away from the pixelP5Closer, the weight of its pixel value difference is 2, and the weight of other differences is 1.

1.1.2 Calculation of approximate values ​​of partial derivatives in the vertical direction

When the Sobel operator performs convolution calculation with the original image src, the pixel change in the vertical direction can be calculated, and the vertical partial derivative G y G_{y}GyThe calculation method is:
G y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] ∗ scr G_y= \left [ \begin{matrix} -1&-2&-1\\ 0&0&0\\ 1&2&1 \end{matrix } \right]*scrGy= 101202101 scr
In the above formula, scr is the original image. Suppose there are 9 pixels in it, as shown in the figure.
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
Then the pixel point P 5 P_5 can be obtainedP5The vertical partial derivative of is:
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)
is the pixel pointP 5 P_5P5The value of the next row of pixels minus the value of the previous row of pixels, where the middle pixel is 5 P_5 away from the pixelP5Closer, the weight of its pixel value difference is 2, and the weight of other differences is 1.

1.1.3 Superposition of partial derivatives in the horizontal direction and partial derivatives in the vertical direction

∇ 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 Custom function implementation

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.3 Opencv functions

In Opencv, use the function cv2.Sobel() to implement the Sobel operator operation:
dst=cv2.Sobel(src,ddepth,dx,dy)

  • dst represents the target image
  • src represents the original image
  • ddepth represents the output image depth (usually set to "cv2.CV_64F")
  • dx represents the derivative order in the x direction
  • dy represents the derivative order in the y direction

Sample code:

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

In order to obtain the partial derivative whose result is a positive number, it is necessary to take the absolute value of the partial derivative obtained by the Sobel function. In Opencv, use the function cv2.convertScaleAbs() to take the absolute value of the parameter, that is
dst=cv2.convertScaleAbs(src)

  • dst represents the processing result
  • src represents the original image

Sample code:

absy=cv.convertScaleAbs(sobley)

If you want to obtain the edge superposition in the x direction and the y direction, you need to add the edge maps in the horizontal direction and the vertical direction. In Opencv, use the function cv2.addweighted() for superposition, namely:

dst=cv2.addweighted(src1,alpha,src2,gamma)
  • dst represents the processing result
  • src1 represents original image 1
  • alpha represents the overlay weight of src1
  • src2 stands for original image 2
  • Gamma represents the overlay weight of src2

Sample code:

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

1.4 Overall code

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 Results Comparison Chart

Custom functions and library functions

2. Laplacian operator

The Laplacian operator (Laplacian) is a second-order derivative operator, which has rotation invariance and can meet the requirements of image edge sharpening (edge ​​detection) in different directions. Typically, the sum of the coefficients of its operators needs to be zero. For example, a Laplacian operator of size 3x3 is shown below.
[ 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
The Laplacian operator is similar to the second-order Sobel derivative and needs to calculate the gradient values ​​​​in two directions. For example:
L ap = [ 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
Then the pixel point P 5 P_5 can be obtainedP5The approximate derivative value of is:
P 5 lap = ( P 2 + P 4 + P 6 + P 8 ) − 4 ⋅ P 5 P_5lap=(P_2+P_4+P_6+P_8)-4·P_5P5lap=(P2+P4+P6+P8)4P5

2.1. Opencv functions

Use the function cv2.Laplacian() in Opencv to realize the calculation of the Laplacian operator. The syntax format of this function is:

dst=cv2.Laplacian(src,ddepth,ksize)
  • dst represents the target image
  • src represents the original image
  • ddepth represents the output image depth (usually set to "cv2.CV_64F")
  • ksize represents the kernel size, which must be a positive odd number.

2.2 Function implementation

	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 Calculation results

laplacian

Guess you like

Origin blog.csdn.net/m0_53192838/article/details/127415508