图像处理之梯度及边缘检测算子

这篇具有很好参考价值的文章主要介绍了图像处理之梯度及边缘检测算子。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

梯度是一个量变化的速度,在数学中通常使用求导、求偏导获取梯度或者某一方向上的梯度。
在数字图像中梯度可以看为像素值分别在x,y方向上的变化速度,因为数字图像的离散型,以及像素是最小处理单元的特性,求数字图像的梯度时,不需要求导,只需要进行加减运算即可。(其实就是求导的差分近似形式).如下图所示:
图像处理之梯度及边缘检测算子,图像处理,图像处理,python,机器学习

一、sobel 算子

Sobel算子包含两组 3 ∗ 3的矩阵,分别为横向及纵向模板,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。下面是 G x G_x Gx G y G_y Gy的模板。
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{array} \right]*A Gx= +1+2+1000121 A

G 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{array} \right]*A Gy= +101+202+101 A
如上式, G x G_x Gx G y G_y Gy分别表示对图像A进行横向和纵向梯度检测得到的结果。
取二者平方和即可得到图像上每一点的梯度值,即在该点同时计算 x x x方向与 y y y方向的梯度。
G = G x 2 + G y 2 G=\sqrt{G_x^2+G_y^2} G=Gx2+Gy2
该点的梯度方向可以通过取这两个值的比的反正切 a r c t a n arctan arctan得到:
Θ = a r c t a n ( G y G x ) \Theta=arctan\left(\frac{G_y}{G_x}\right) Θ=arctan(GxGy)
实现代码如下:

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

检测结果如下:
图像处理之梯度及边缘检测算子,图像处理,图像处理,python,机器学习

二、Scharr算子

Scharr算子是Sobel算子的一种特殊形式。其核的形式如下:
[ + 3 0 − 3 + 10 0 − 10 + 3 0 − 3 ] \left[ \begin{array} {cccc} +3&0&-3\\ +10 &0&-10\\ +3&0&-3 \end{array} \right] +3+10+30003103
[ − 3 − 10 − 3 0 0 0 + 3 + 10 + 3 ] \left[ \begin{array} {cccc} -3&-10&-3\\ 0 &0&0\\ +3&+10&+3 \end{array} \right] 30+3100+1030+3
前面提到了,Sobel算子中核越大就能够更好的近似导数,准确度也更高。因此,在核比较小时如3×3时,Sobel核的准确度较差,使用Scharr算子代替3×3的Sobel核能够提高精度。因为加大了在x方向或y方向的权重,使得梯度角(梯度方向)不会距离x或y方向太远,因此误差也不会太大。例如,只求x方向的梯度时,核的中心点的x方向的两个权值远大于其它权值,这使得求得的梯度更靠近x方向,一定程度减小了误差。

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

检测结果:
图像处理之梯度及边缘检测算子,图像处理,图像处理,python,机器学习

三、Roberts算子

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

Roberts算子的核如上图所示,是一种简单的交叉差分算法,在求±45°的梯度时最有效。
相比于一般的水平竖直方向的差分算子,Roberts算子能够有效地保留边缘的角点,并且计算速度较快。缺点是对细节敏感导致对噪声也十分敏感。
实现代码:

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

检测结果如下:
图像处理之梯度及边缘检测算子,图像处理,图像处理,python,机器学习

四、拉普拉斯算子

拉普拉斯算子可由二阶导数定义:
Δ 2 ( x , y ) = ∂ 2 f ( x , y ) ∂ x 2 + ∂ 2 f ( x , y ) ∂ y 2 \Delta^2(x,y)=\frac{\partial^2f(x,y)}{\partial x^2}+\frac{\partial^2f(x,y)}{\partial y^2} Δ2(x,y)=x22f(x,y)+y22f(x,y)
而在数字图像中离散化,用二阶差分表示为:
∂ 2 f ( x , y ) ∂ x 2 ≈ Δ x f ( i + 1 , j ) − Δ x f ( i , j ) = [ f ( i + 1 , j ) − f ( i , j ) ] − [ f ( i , j ) − f ( i − 1 , j ) ] = f ( i + 1 , j ) + f ( i − 1 , j ) − 2 f ( i , j ) \begin{align*} \begin{split} \frac{\partial^2f(x,y)}{\partial 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{split} \end{align*} x22f(x,y)Δxf(i+1,j)Δxf(i,j)=[f(i+1,j)f(i,j)][f(i,j)f(i1,j)]=f(i+1,j)+f(i1,j)2f(i,j)
同理可得:
∂ 2 f ( x , y ) ∂ y 2 ≈ f ( i , j + 1 ) + f ( i , j − 1 ) − 2 f ( i , j ) \frac{\partial^2f(x,y)}{\partial y^2} \approx f(i,j+1)+f(i,j-1)-2f(i,j) y22f(x,y)f(i,j+1)+f(i,j1)2f(i,j)
所以拉普拉斯算子可以表示为:
Δ 2 ( x , y ) = f ( i + 1 , j ) + f ( i − 1 , j ) + f ( i , j + 1 ) + f ( i , j − 1 ) − 4 f ( i , j ) \Delta^2(x,y)=f(i+1,j)+f(i-1,j)+f(i,j+1)+f(i,j-1)-4f(i,j) Δ2(x,y)=f(i+1,j)+f(i1,j)+f(i,j+1)+f(i,j1)4f(i,j)
其卷积核如下:
[ 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
拉普拉斯算子法其实是一种图像边缘增强算子,常用于图像锐化,在增强边缘的同时也增强了噪声,因此使用前需要进行平滑或滤波处理。如下图,可以看出,在函数值发生突变的情况时,二阶导数能够增强突变点与其两侧的对比度。在数字图像中就是图像边缘处得到了增强,因此实现了图像的锐化。
图像处理之梯度及边缘检测算子,图像处理,图像处理,python,机器学习

代码实现如下:

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

检测结果如下:
图像处理之梯度及边缘检测算子,图像处理,图像处理,python,机器学习
整体代码如下:

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()

画图代码:文章来源地址https://www.toymoban.com/news/detail-576911.html

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()



到了这里,关于图像处理之梯度及边缘检测算子的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python-OpenCV中的图像处理-边缘检测

    Canny 边缘检测是一种非常流行的边缘检测算法,是 John F.Canny 在 1986 年提出的。它是一个有很多步构成的算法:噪声去除、计算图像梯度、非极大值抑制、滞后阀值等。 Canny(image: Mat, threshold1, threshold2, edges=…, apertureSize=…, L2gradient=…) 在 OpenCV 中只需要一个函数: cv2.Canny(),

    2024年02月13日
    浏览(56)
  • opencv基础41-图像梯度-sobel算子详解cv2.Sobel()(边缘检测基础)

    图像梯度是用于描述图像变化率的概念。在图像处理中,梯度指的是图像中每个像素的灰度值变化速率或方向。它常用于边缘检测和图像特征提取。 一维图像的梯度表示为函数 f(x) 的导数,而在二维图像中,梯度是一个向量,包含两个分量:水平方向和垂直方向的灰度变化率

    2024年02月14日
    浏览(47)
  • (数字图像处理MATLAB+Python)第七章图像锐化-第三节:高斯滤波与边缘检测

    高斯函数 :是一种常见的连续函数,通常用符号 G ( x ) G(x) G ( x ) 表示。它可以用下面的公式定义 G ( x ) = 1 σ 2 π e − x 2 2 σ 2 G(x)=frac{1}{sigma sqrt{ 2pi }}e^{-frac{x^{2}}{2sigma^{2}}} G ( x ) = σ 2 π ​ 1 ​ e − 2 σ 2 x 2 ​ 其中, x x x 是自变量, σ sigma σ 是一个正实数,表示高斯函

    2024年02月06日
    浏览(56)
  • 【数字图像处理】边缘检测

    边缘检测是一种图像处理技术,旨在标识和定位数字图像中的边缘和轮廓。 边缘是图像中灰度值变化明显的位置 ,通常是物体的边缘或表面的变化。通过边缘检测算法,可以将图像中的物体和背景分离出来,从而实现目标检测、图像分割、计算机视觉和机器人视觉等应用。

    2024年02月02日
    浏览(47)
  • 图像处理:边缘检测原理

    很抱歉,前面推导三种边缘检测算子我不是很满意就发出去了,现在以我的知识储备看他们还是有着很大的问题,我潜下心的找资料,看视频,就是为了将我的基础打牢,所以,我在这一篇当中好好的抠细节,毕竟从实际的应用上来说,这是我的学习笔记,再怎么也不能糊弄

    2024年02月06日
    浏览(49)
  • 数字图像处理:图像分割——边缘检测与区域分割

    1.图像分割:根据图像的某些局部特征(灰度级、纹理、彩色或统计特征等)的相似性和互斥性,将图像分割成若干子区域,在每个子区域内部具有相似(相同或相近)特性,而相邻子区域的特性互斥。所以图像分割是利用图像局部特征的相似性和互斥性。 2.图像分割方法分

    2024年02月05日
    浏览(43)
  • 图像处理——边缘检测(MATLAB实现)

    实验表明,人眼对图像中边缘的识别不是通过设置阈值来分割的,目标的边缘一般表现为灰度(对彩色图像还包括色度)的特变。对于人类的视觉感知,图像边缘对理解图像内容起到关键作用。在灰度渐变的图像中无法区分其灰度变化的边界,但如果边界灰度有突变,则可以区

    2024年02月03日
    浏览(41)
  • 【C++】【图像处理】均值滤波 and 高斯滤波 and 中值滤波 and Sobel算子边缘提取(低通滤波)算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)

     中值滤波: 中值滤波中的MidValueFind函数的实现就是冒泡排序,最后去中间值返回:  Soble算子边缘提取:     总结: 1、均值、高斯滤波和Sobel算子边缘提取的核心,创建卷积核并确定各个点上的权重,然后将边缘灰度级归零(是否边缘归零按业务需求决定),提取非边缘像

    2024年02月05日
    浏览(58)
  • 【图像处理】基于matlab蚁群聚类图像边缘检测

    目录 基于matlab蚁群聚类图像边缘检测 蚁群聚类是一种模拟自然界中蚂蚁群体行为的算法,常用于解决优化问题。该算法可以用于图像处理中的边缘检测。下面给出一个基于MATLAB的蚁群聚类图像边缘检测的示例代码。 我们首先读入待处理图像,并将其转换为灰度图像。然后,

    2023年04月22日
    浏览(51)
  • 图像处理技术:数字图像分割 ------ 图像分割、边界分割(边缘检测)、区域分割

    是指根据灰度、彩色、空间纹理、几何形状等特征把图像划分 成若干个互不相交的区域,使得这些特征在同一区域内表现出一致 性或相似性,而在不同区域间表现出明显的不同 分割出来的区域应该同时满足:  (1)分割出来的图像区域的均匀性和连通性。 • 均匀性是指该

    2024年02月04日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包