Operadores de detección de gradientes y bordes de procesamiento de imágenes.

El gradiente es la velocidad a la que cambia una cantidad.En matemáticas se suele utilizar la derivación y la derivación parcial para obtener el gradiente o la pendiente en una determinada dirección.
En una imagen digital, el gradiente se puede considerar como la velocidad de cambio del valor del píxel en las direcciones X e Y respectivamente. Debido al tipo discreto de la imagen digital y la característica de que el píxel es la unidad de procesamiento más pequeña, al calcular el gradiente de la imagen digital, no hay necesidad de calcular la derivada, solo se requieren sumas y restas. (De hecho, es la forma de derivación de aproximación diferencial.) Como se muestra en la siguiente figura:
inserte la descripción de la imagen aquí

1. Operador sobel

El operador de Sobel incluye dos conjuntos de matrices de 3 ∗ 3, que son las plantillas horizontal y vertical, que se convolucionan con la imagen para obtener las aproximaciones de la diferencia de brillo horizontal y vertical, respectivamente. A continuación se muestra G x G_xGRAMOx G y G_y GRAMOtuPredeterminado
G x = [ + 1 0 − 1 + 2 0 − 2 + 1 0 − 1 ] ∗ A G_x= \left[ \begin{array} {cccc} +1&0&-1\\ +2 &0&-2\ \ + 1 &0&-1 \end{matriz}\right]*AGRAMOx= + 1+ 2+ 100012 1 A

GRAMO y = [ + 1 + 2 + 1 0 0 0 − 1 − 2 − 1 ] ∗ A G_y= \left[ \begin{array} {cccc} +1&+2&+1\\ 0&0&0\\ -1&-2& -1 \end{matriz} \right]*AGRAMOtu= + 10 1+ 20 2+ 10 1 A
es como la fórmula anterior,G x G_xGRAMOx G y G_y GRAMOtuRepresente respectivamente los resultados obtenidos al realizar la detección de gradiente horizontal y vertical en la imagen A.
Tome la suma de los cuadrados de los dos para obtener el valor de gradiente de cada punto de la imagen, es decir, calcule xx en este punto al mismo tiempodirección x y yyEl gradiente en la dirección y .
G = G x 2 + G y 2 G=\sqrt{G_x^2+G_y^2}GRAMO=GRAMOX2+GRAMOy2
La dirección del gradiente en ese punto se puede determinar tomando el arctan arctan arctan de la relación de estos dos valoresa rc t una razón:
Θ = arctan ( G y G x ) \Theta=arctan\left(\frac{G_y}{G_x}\right)el=lo siento _ _(GRAMOxGRAMOtu)
el código de implementación es el siguiente:

def SobelX(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            result[i,j] =v
            if(result[i,j]<threshold):
                result[i,j]=0
    return result
def SobelY(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] =h
            if(result[i,j]<threshold):
                result[i,j]=0
    return result

def Sobel(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    G_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result

Los resultados de la prueba son los siguientes:
inserte la descripción de la imagen aquí

Dos, operador Scharr

El operador de Scharr es una forma especial del operador de Sobel. La forma de su núcleo es la siguiente:
[ + 3 0 − 3 + 10 0 − 10 + 3 0 − 3 ] \left[ \begin{array} {cccc} +3&0&-3\\ +10 &0&-10\\ +3&0&- 3 \end{matriz} \right] + 3+ 10+ 3000310 3
[ − 3 − 10 − 3 0 0 0 + 3 + 10 + 3 ] \left[ \begin{array} {cccc} -3&-10&-3\\ 0 &0&0\\ +3&+10&+3 \end{array } \bien] 30+ 3100+ 1030+ 3
Como se mencionó anteriormente, cuanto mayor sea el kernel en el operador de Sobel, mejor será la derivada aproximada y mayor será la precisión. Por lo tanto, cuando el kernel es relativamente pequeño, como 3×3, la precisión del kernel de Sobel es pobre y el uso del operador Scharr en lugar del kernel de Sobel de 3×3 puede mejorar la precisión. Debido a que aumenta el peso en la dirección x o en la dirección y, el ángulo de gradiente (dirección del gradiente) no estará demasiado lejos de la dirección x o y, por lo que el error no será demasiado grande. Por ejemplo, cuando solo se calcula el gradiente en la dirección x, los dos pesos en la dirección x del punto central del kernel son mucho más grandes que los otros pesos, lo que hace que el gradiente obtenido esté más cerca de la dirección x y reduce el error. hasta cierto punto.

def Scharr(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-3, 0, 3], [-10, 0, 10], [-3, 0, 3]])
    G_y = np.array([[-3, -10, -3], [0, 0, 0], [3, 10, 3]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result

Resultados de la prueba:
inserte la descripción de la imagen aquí

3. Operador de Roberts

[ − 1 0 0 1 ] \left[ \begin{matriz} {cccc} -1&0\\ 0&1\\ \end{matriz} \right][1001]
[ 0 − 1 1 0 ] \left[ \begin{matriz} {cccc} 0&-1\\ 1 &0\\ \end{matriz} \right][0110]

El núcleo del operador de Roberts se muestra en la figura anterior, es un algoritmo de diferencia cruzada simple, que es más efectivo cuando se calcula el gradiente de ±45°.
En comparación con los operadores de diferencia horizontal y vertical generales, el operador de Roberts puede preservar efectivamente los puntos de esquina del borde y la velocidad de cálculo es más rápida. La desventaja es que es sensible a los detalles y también es muy sensible al ruido.
Código de implementación:

def Roberts(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0], [0,1]])
    G_y = np.array([[0, -1], [1,0]])
    result = np.zeros(img.shape)
    for i in range(0, width - 1):
        for j in range(0, height - 1):
            v = np.sum(G_x * img[i:i + 2, j:j + 2])
            h = np.sum(G_y * img[i:i + 2, j:j + 2])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result

Los resultados de la prueba son los siguientes:
inserte la descripción de la imagen aquí

4. Operador laplaciano

El laplaciano se puede definir mediante la segunda derivada:
Δ 2 ( x , y ) = ∂ 2 f ( x , y ) ∂ x 2 + ∂ 2 f ( x , y ) ∂ y 2 \Delta^2(x, y) =\frac{\parcial^2f(x,y)}{\parcial x^2}+\frac{\parcial^2f(x,y)}{\parcial y^2}D2 (x,y )=x22 f(x,y )+años22 f(x,y )
Sin embargo, en la discretización de imágenes digitales, la diferencia de segundo orden se expresa como:
∂ 2 f ( x , y ) ∂ x 2 ≈ Δ xf ( i + 1 , j ) − Δ xf ( i , j ) = [ f ( yo + 1 , j ) - F ( yo , j ) ] - [ F ( yo , j ) - F ( yo - 1 , j ) ] = F ( yo + 1 , j ) + F ( yo - 1 , j ) − 2 f ( yo , j ) \begin{align*} \begin{split} \frac{\parcial^2f(x,y)}{\parcial x^2} &\approx \Delta_xf(i+1, j)- \Delta_xf(i,j) \\ &= \left[ f(i+1,j)-f(i,j) \right]- \left[f(i,j)-f(i- 1,j ) \right] \\ &=f(i+1,j)+f(i-1,j)-2f(i,j) \end{dividir} \end{align*}x22 f(x,y )Dxf ( yo+1 ,j )Dxf ( yo ,j )=[ f ( yo+1 ,j )f ( yo ,j ) ][ f ( yo ,j )f ( yo1 ,j ) ]=f ( yo+1 ,j )+f ( yo1 ,j )2 f ( yo ,j )
同理可得:
∂ 2 f ( x , y ) ∂ y 2 ≈ f ( yo , j + 1 ) + f ( yo , j − 1 ) − 2 f ( yo , j ) \frac{\parcial^2f( x,y)}{\parcial y^2} \approx f(i,j+1)+f(i,j-1)-2f(i,j)años22 f(x,y )f ( yo ,j+1 )+f ( yo ,j1 )2 f ( yo ,j )
Entonces el operador laplaciano se puede expresar como:
Δ 2 ( x , y ) = f ( i + 1 , j ) + f ( i − 1 , j ) + f ( i , j + 1 ) + f ( i , j − 1 ) − 4 f ( yo , j ) \Delta^2(x,y)=f(i+1,j)+f(i-1,j)+f(i,j+1) +f (i,j-1)-4f(i,j)D2 (x,y )=f ( yo+1 ,j )+f ( yo1 ,j )+f ( yo ,j+1 )+f ( yo ,j1 )4 f ( yo ,j )
El kernel de convolución es el siguiente:
[ 0 1 0 1 − 4 1 0 1 0 ] \left[ \begin{array} {cccc} 0&1&0\\ 1&-4&1\\ 0&1&0 \end{array} \right] 010141010
El método laplaciano es en realidad un operador de mejora de los bordes de la imagen, que a menudo se usa para mejorar la nitidez de la imagen. Mientras mejora el borde, también mejora el ruido, por lo que debe suavizarse o filtrarse antes de su uso. Como se muestra en la figura a continuación, se puede ver que cuando el valor de la función cambia repentinamente, la segunda derivada puede mejorar el contraste entre el punto de cambio repentino y sus dos lados. En una imagen digital, se realza el borde de la imagen, realizándose así la nitidez de la imagen.
inserte la descripción de la imagen aquí

El código se implementa de la siguiente manera:

def Laplacian(img):
    temLaplacian = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
    height, width = img.shape[::-1]
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            result[i][j] = np.abs(np.sum(temLaplacian * img[i:i + 3, j:j + 3]))
    return result

Los resultados de la prueba son los siguientes:
inserte la descripción de la imagen aquí
El código general es el siguiente:

import numpy as np
import cv2
import imgShow as iS

def SobelX(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            result[i,j] =v
            if(result[i,j]<threshold):
                result[i,j]=0
    return result

def SobelY(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] =h
            if(result[i,j]<threshold):
                result[i,j]=0
    return result

def Sobel(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    G_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result
def Sobel(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    G_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result
def Scharr(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-3, 0, 3], [-10, 0, 10], [-3, 0, 3]])
    G_y = np.array([[-3, -10, -3], [0, 0, 0], [3, 10, 3]])
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            v = np.sum(G_x * img[i:i + 3, j:j + 3])
            h = np.sum(G_y * img[i:i + 3, j:j + 3])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result
def Roberts(img,threshold):
    height = img.shape[0]
    width = img.shape[1]
    G_x = np.array([[-1, 0], [0,1]])
    G_y = np.array([[0, -1], [1,0]])
    result = np.zeros(img.shape)
    for i in range(0, width - 1):
        for j in range(0, height - 1):
            v = np.sum(G_x * img[i:i + 2, j:j + 2])
            h = np.sum(G_y * img[i:i + 2, j:j + 2])
            result[i,j] = np.sqrt((v ** 2) + (h ** 2))
            if(result[i,j]<threshold):
                result[i,j]=0
    return result
def Laplacian(img):
    temLaplacian = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
    height, width = img.shape[::-1]
    result = np.zeros(img.shape)
    for i in range(0, width - 2):
        for j in range(0, height - 2):
            result[i][j] = np.abs(np.sum(temLaplacian * img[i:i + 3, j:j + 3]))
    return result

img=cv2.imread("./originImg/HorizontalAndVertical.jpg")
img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sobelImg=Sobel(img,56)
iS.showImagegray(sobelImg, img, 25, 15, 'sobelDetection', 'origin', './ProcessedImg/sobelDetection.jpg')
imageList=[]
origin_img=[img,'origin_img']
imageList.append(origin_img)
sobelx=SobelX(img,0)
sobel2=[sobelx,'Sobel_X']
imageList.append(sobel2)
sobely=SobelY(img,0)
sobel1=[sobely,'Sobel_Y']
imageList.append(sobel1)
sobelImg=Sobel(img,56)
sobel3=[sobelImg,'Sobel']
imageList.append(sobel3)
iS.showMultipleimages(imageList,25,25,'./ProcessedImg/sobelEdge.jpg')
img1=cv2.imread('./originImg/Goldhill.tif')
img1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
LapImg=Laplacian(img1)
iS.showImagegray(LapImg, img1, 25, 15, 'LapImg', 'origin', './ProcessedImg/lapImg.jpg')
scharrImg=Scharr(img,56)
iS.showImagegray(scharrImg, img, 25, 15, 'scharrDetection', 'origin', './ProcessedImg/scharrDetection.jpg')
robertsImg=Roberts(img,56)
iS.showImagegray(robertsImg, img, 25, 15, 'robertsDetection', 'origin', './ProcessedImg/robertsDetection.jpg')
# cv2.imshow('sobely',sobely)
# cv2.waitKey(0)
# cv2.destroyAllWindows()

Codigo de dibujo:

import matplotlib.pyplot as plt
import numpy as np
import math
#图像实际大小为 W*100 * H*100 像素  ,
def showImagegray(newImg,oldImg,W,H,newImgtitle,oldImgtitle,saveImgpath):

    plt.figure(figsize=(W,H))
    plt.subplot(121)
    plt.title(oldImgtitle,fontsize=30)
    plt.axis('off')
    plt.imshow(oldImg, cmap='gray')

    plt.subplot(122)
    plt.title(newImgtitle,fontsize=30)
    plt.axis('off')
    plt.imshow(newImg, cmap='gray')
    # plt.tight_layout()  # 调整整体空白
    plt.savefig(saveImgpath)
    plt.show()

def showMultipleimages(imageList,W,H,saveImgpath):

    imageLength=len(imageList)

    plt.rcParams['figure.figsize'] = (W,H)
    col=row=math.ceil(np.sqrt(imageLength))
    fig, a = plt.subplots(col, row)
    m = 0
    for i in range(col):
        for j in range(row):
            a[i][j].set_title(imageList[m][1])
            a[i][j].imshow(imageList[m][0], cmap=plt.cm.gray)
            m += 1
        #去掉边框和刻度
        for ax in a.flat:
            ax.set_axis_off()

    fig.tight_layout()  # 调整整体空白
    plt.subplots_adjust(wspace=0.2, hspace=0.2)  # 调整子图间距
    plt.savefig(saveImgpath)
    plt.show()



Supongo que te gusta

Origin blog.csdn.net/weixin_42491648/article/details/131756263
Recomendado
Clasificación