sobel计算以及代码

sobel 算子

索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是以离散性差分算子,用来计算凸显两素函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是法矢量。
Sobel 的卷积因子为:
在这里插入图片描述
该算子包含两组3 * 3 的矩阵,分别为横向和纵向,将之与图像做平面卷积,即可分别得出横向及纵向的亮度差
分近似值,若以A代表为原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:
Gx=[−10+1−20+2−10+1]×A and Gy=[+1+2+1000−1−2−1]×A  G_x=\left[ \begin{matrix} -1& 0& +1\\ -2& 0& +2\\ -1& 0& +1\\ \end{matrix} \right] \times A\ and\ G_y=\left[ \begin{matrix} +1& +2& +1\\ 0& 0& 0\\ -1& -2& -1\\ \end{matrix} \right] \times A\ Gx=121000+1+2+1×A and Gy=+101+202+101×A 

图像的每一像素的横向以及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
G=Gx2+Gy2  G=\sqrt{G_x^2+G_y^2}\ G=Gx2+Gy2 
通常,为了提高计算的效率,也使用以下公式计算:
∣G∣=∣Gx∣+∣Gy∣ \left| G \right|=\left| G_x \right|+\left| G_y \right| G=Gx+Gy

具体代码实现

import cv2 as cv
import math
import numpy as np


def rgb2gray(img):
    h=img.shape[0]
    w=img.shape[1]
    img1=np.zeros((h,w),np.uint8)
    for i in range(h):
        for j in range(w):
            img1[i, j] = np.max(img[i, j])
    return img1

def otsu(img):
    h=img.shape[0]
    w=img.shape[1]
    m=h*w
    otsuimg=np.zeros((h,w),np.uint8)
    threshold_max=threshold=0
    histogram=np.zeros(256,np.int32)
    probability=np.zeros(256,np.float32)
    for i in range (h):
        for j in range (w):
            s=img[i,j]
            histogram[s]+=1
    for k in range (256):
        probability[k]=histogram[k]/m
    for i in range (255):
        w0 = w1 = 0
        fgs = bgs = 0
        for j in range (256):
            if j<=i:
                w0+=probability[j]
                fgs+=j*probability[j]
            else:
                w1+=probability[j]
                bgs+=j*probability[j]
        u0=fgs/w0
        u1=bgs/w1
        g=w0*w1*(u0-u1)**2   # 类间方差
        if g>=threshold_max:
            threshold_max=g
            threshold=i
    print(threshold)
    for i in range (h):
        for j in range (w):
            if img[i,j]>threshold:
                otsuimg[i,j]=255
            else:
                otsuimg[i,j]=0
    return otsuimg

def sobel(img):
    h=img.shape[0]
    w=img.shape[1]
    sobelimg=np.zeros((h,w),np.uint8)
    sobelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
    sobely = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
    sobelx=np.array(sobelx)
    sobely=np.array(sobely)
    for i in range(1,h-1):
        for j in range(1,w-1):
            edgex=0
            edgey=0
            for k in range(-1,2):
                for l in range(-1,2):
                    edgex+=img[k+i,l+j]*sobelx[1+k,1+l]
                    edgey+=img[k+i,l+j]*sobely[1+k,1+l]
            gx=abs(edgex)
            gy=abs(edgey)
            gramag=gx+gy
            sobelimg[i,j]=gramag
    return sobelimg

image= cv.imread(r"pin1.jpg")
grayimage=rgb2gray(image)

otsuimage=otsu(grayimage)
cv.imshow("grayimage",otsuimage)
sobelimage=sobel(otsuimage)
cv.imshow("image",image)
cv.imshow("sobelimage",sobelimage)
cv.waitKey(0)
cv.destroyAllWindows()

结果

原图 && 二值化灰度图 && sobel图
在这里插入图片描述

opencv函数实现

import cv2
import numpy as np

img = cv2.imread(r"3.jpg")

x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)

absX = cv2.convertScaleAbs(x)  # 转回unit8
absY = cv2.convertScaleAbs(y)

dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

cv2.imshow("absX", absX)
cv2.imshow("absY", absY)

cv2.imshow("Result", dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
结果

X 方向 && Y方向 && X+Y方向
在这里插入图片描述

### Sobel算子的图像处理计算方法 Sobel算子是一种基于卷积的离散差分算子,主要用于图像的边缘检测。其核心思想是通过计算图像中像素点在水平方向和垂直方向上的梯度值,从而突出图像中的边缘信息。Sobel算子由两个3×3的卷积核组成,分别用于检测水平方向(Gx)和垂直方向(Gy)的边缘。 Sobel算子卷积核如下: - 水平方向(Gx): ``` [-1, 0, 1] [-2, 0, 2] [-1, 0, 1] ``` - 垂直方向(Gy): ``` [-1, -2, -1] [ 0, 0, 0] [ 1, 2, 1] ``` 在图像处理过程中,Sobel算子通过将上述卷积核与图像中的每个像素点进行卷积运算,得到该像素点在水平方向和垂直方向上的梯度值。具体来说,卷积运算的结果分别表示为Gx和Gy,其中Gx反映了水平方向上的梯度变化,Gy反映了垂直方向上的梯度变化。 根据Gx和Gy的值,可以进一步计算图像中每个像素点的梯度大小(G)和梯度方向(θ)。梯度大小的计算公式为: $$ G = \sqrt{G_x^2 + G_y^2} $$ 梯度方向的计算公式为: $$ \theta = \arctan\left(\frac{G_y}{G_x}\right) $$ 在实际应用中,为了简化计算,通常使用以下近似公式来计算梯度大小: $$ G = |G_x| + |G_y| $$ 通过设定一个阈值,可以将梯度大小转换为二值化的边缘图像。梯度值大于阈值的像素点被认为是边缘点,而梯度值小于阈值的像素点则不被视为边缘点。 以下是一个使用Python实现Sobel算子的示例代码: ```python import cv2 import numpy as np # 读取图像并转换为灰度图 image = cv2.imread('input_image.jpg', 0) # 定义Sobel算子卷积sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) sobel_y = np.array([[-1, -2, -1], [ 0, 0, 0], [ 1, 2, 1]]) # 对图像进行卷积运算,得到水平方向和垂直方向的梯度值 gradient_x = cv2.filter2D(image, -1, sobel_x) gradient_y = cv2.filter2D(image, -1, sobel_y) # 计算梯度大小 gradient_magnitude = np.sqrt(gradient_x**2 + gradient_y**2) # 归一化处理,将梯度值映射到0-255范围内 gradient_magnitude = cv2.normalize(gradient_magnitude, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) # 显示结果 cv2.imshow('Gradient Magnitude', gradient_magnitude) cv2.waitKey(0) cv2.destroyAllWindows() ``` 需要注意的是,Sobel算子在提取图像边缘时,并未严格区分图像的主题与背景,也未基于图像的灰度值进行处理,因此在某些情况下,其边缘检测效果可能不如其他更先进的算子[^2]。 ### 相关问题 1. Sobel算子与Scharr算子边缘检测中的区别是什么? 2. 如何通过调整阈值优化Sobel算子边缘检测效果? 3. Sobel算子在图像锐化中的具体应用方法是什么? 4. 什么是各向同性Sobel算子,它与标准Sobel算子有何不同? 5. Sobel算子计算资源有限的场景下是否更具有优势?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值