【图像处理】sobel边缘检测的实现

Sobel算子是图像边缘检测中最重要的算子之一,该算子包含两组3×3的矩阵,分别为横向及纵向,将之与图像作2D卷积,即可分别得出横向及纵向的亮度差分近似值。Gx,Gy的值如下所示:

【图像处理】sobel边缘检测的实现
将图像I分别和G x , G y G_x,G_y G x ​,G y ​作2D卷积,得到G x ′ , G y ′ G_x’,G_y’G x ′​,G y ′​
图像的每一个像素的横向及纵向梯度近似值可用以下两个公式结合,来计算梯度的大小。
G = ∣ G x ′ ∣ + ∣ G y ′ ∣ G=|G_x’|+|G_y’|G =∣G x ′​∣+∣G y ′​∣
G = G x ′ 2 + G y ′ 2 G=\sqrt{G_x’^2+G_y’^2}G =G x ′2 ​+G y ′2 ​​
计算得到G之后,我们只需要设定一个阈值G m a x G_{max}G m a x ​(比如说:100,一般来讲0-255左右为宜),若梯度G大于阈值G m a x G_{max}G m a x ​,则可认为该点是一个边界点。
代码如下:
import torch
from PIL import Image
import numpy as np

def color2gray(img):
    return 0.3*img[:,:,0]+0.59*img[:,:,1]+0.11*img[:,:,2]

def sobel(img,mode,Gmax):
    h,w=img.shape
    sobel_img=np.zeros((h,w))
    Gx=np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
    Gy=np.array([[1,2,1],[0,0,0],[-1,-2,-1]])
    for i in range(h):
        for j in range(w):
            tmp1=0
            tmp2=0
            for kx in range(3):
                for ky in range(3):
                    if i+kx-1>=0 and i+kx-1<h and j+ky-1>=0 and j+ky-1<w:
                        tmp1+=img[i+kx-1][j+ky-1]*Gx[kx][ky]
                        tmp2+=img[i+kx-1][j+ky-1]*Gy[kx][ky]
            if mode==0:
                if np.abs(tmp1)+np.abs(tmp2)>Gmax:
                    sobel_img[i][j]=255
                else:
                    sobel_img[i][j]=0
            else:
                if np.sqrt(tmp1**2+tmp2**2)>Gmax:
                    sobel_img[i][j]=255
                else:
                    sobel_img[i][j]=0
    return sobel_img

img_PIL = Image.open("test.jpg")

img_PIL.show()

img_PIL = np.array(img_PIL)
gray_img=color2gray(img_PIL)

image=Image.fromarray(np.uint8(gray_img))
image.show()

sobel_img=sobel(gray_img,1,127)
image=Image.fromarray(np.uint8(sobel_img))
image.show()

结果展示:

【图像处理】sobel边缘检测的实现
【图像处理】sobel边缘检测的实现
【图像处理】sobel边缘检测的实现
当对精度的要求较高时可以使用S c h a r r 滤 波 器 Scharr滤波器S c h a r r 滤波器,Scharr滤波器水平方向与竖直方向的核为:
【图像处理】sobel边缘检测的实现
边缘检测的效果如下:
【图像处理】sobel边缘检测的实现
不知为何,效果反而变差了.

改进

去掉了G m a x G_{max}G m a x ​这个阈值的判断,将范围压缩至[0,255]后直接显示灰度图像,效果明显好了很多:

【图像处理】sobel边缘检测的实现
改进后的代码如下所示:
import torch
from PIL import Image
import numpy as np

def color2gray(img):
    return 0.3*img[:,:,0]+0.59*img[:,:,1]+0.11*img[:,:,2]

def sobel(img,mode,Gmax):
    h,w=img.shape
    sobel_img=np.zeros((h,w))
    Gx=np.array([[-3,0,3],[-10,0,10],[-3,0,3]])
    Gy=np.array([[-3,-10,-3],[0,0,0],[3,10,3]])
    for i in range(h):
        for j in range(w):
            tmp1=0
            tmp2=0
            for kx in range(3):
                for ky in range(3):
                    if i+kx-1>=0 and i+kx-1<h and j+ky-1>=0 and j+ky-1<w:
                        tmp1+=img[i+kx-1][j+ky-1]*Gx[kx][ky]
                        tmp2+=img[i+kx-1][j+ky-1]*Gy[kx][ky]
            if mode==0:
                sobel_img[i][j]=np.abs(tmp1)+np.abs(tmp2)
            else:
                sobel_img[i][j]=np.sqrt(tmp1**2+tmp2**2)
    max=np.max(sobel_img)
    min=np.min(sobel_img)
    sobel_img=np.round((sobel_img-min)/(max-min)*255)

    return sobel_img

img_PIL = Image.open("test.jpg")

img_PIL.show()

img_PIL = np.array(img_PIL)
gray_img=color2gray(img_PIL)

image=Image.fromarray(np.uint8(gray_img))
image.show()

sobel_img=sobel(gray_img,1,60)
image=Image.fromarray(np.uint8(sobel_img))
image.show()

Original: https://blog.csdn.net/qq_40268672/article/details/122878596
Author: FPGA硅农
Title: 【图像处理】sobel边缘检测的实现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/633635/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球