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

文章目录

  • 一、sobel 算子
  • 二、Scharr算子
  • 三、Roberts算子
  • 四、拉普拉斯算子

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

一、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] =vif(result[i,j]<threshold):result[i,j]=0return 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] =hif(result[i,j]<threshold):result[i,j]=0return resultdef 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]=0return result

检测结果如下:
在这里插入图片描述

二、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]=0return result

检测结果:
在这里插入图片描述

三、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]=0return result

检测结果如下:
在这里插入图片描述

四、拉普拉斯算子

拉普拉斯算子可由二阶导数定义:
Δ 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
拉普拉斯算子法其实是一种图像边缘增强算子,常用于图像锐化,在增强边缘的同时也增强了噪声,因此使用前需要进行平滑或滤波处理。如下图,可以看出,在函数值发生突变的情况时,二阶导数能够增强突变点与其两侧的对比度。在数字图像中就是图像边缘处得到了增强,因此实现了图像的锐化。
在这里插入图片描述

代码实现如下:

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

检测结果如下:
在这里插入图片描述
整体代码如下:

import numpy as np
import cv2
import imgShow as iSdef 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] =vif(result[i,j]<threshold):result[i,j]=0return resultdef 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] =hif(result[i,j]<threshold):result[i,j]=0return resultdef 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]=0return 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]=0return 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]=0return 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]=0return 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 resultimg=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()

画图代码:

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 = 0for 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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/27206.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软浏览器连不上网络

针对微软浏览器连不上网络&#xff0c;但其他浏览器仍能连上网络 控制面板 -> 网络和Internet -> Internet 选项 -> 连接 -> 局域网设置 -> 取消代理服务器

SQL数据库(设置模式、数据库操作、表操作、列操作、SQL索引/约束、SQL数据类型、SQL函数、常见问题)

目录 SQL数据库 设置模式 SET NAMES utf-8 set sql_safe_updates1 数据库操作 CREATE DATABASE databaseName&#xff08;创建数据库&#xff09; USE databaseName&#xff08;选择数据库&#xff09; DROP DATABASE databaseName&#xff08;删除数据库&#xff09; …

[pyqt5]鼠标指针光标样式

pyqt5默认有下面几种光标样式 设置光标&#xff1a; self.setCursor(Qt.CrossCursor) 恢复默认光标 self.unsetCursor() 自定义光标 from PyQt5.Qt import * import sysapp QApplication(sys.argv)# 创建一个控件 window QWidget() window.resize(500,500) window.move(…

指针知多少

作者简介&#xff1a;დ旧言~&#xff0c;目前大一&#xff0c;现在学习Java&#xff0c;c&#xff0c;Python等 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 望小伙伴们点赞&#x1f44d;收藏✨加关注哟&#x1f495;&#x1f495; ⛵前言 不知道大家还记…

【深度学习】多任务学习

多任务学习是一个很火的话题&#xff0c;在自动驾驶领域以及其他对存储资源要求较高的端侧任务&#xff0c;都会考虑这种方式。之前面试的时候也有被问题多任务学习。前几天看到一个写得很好的例子&#xff0c;在此记录一下&#xff0c;也好久没有写博客了。 1.参考 论文是20…

p2p大豆计数模型

前面学习了一下论文&#xff1a;Improved Field-Based Soybean Seed Counting and Localization with Feature Level Considered 论文链接&#xff1a;https://spj.science.org/doi/10.34133/plantphenomics.0026 解读链接&#xff1a;论文阅读--考虑特征水平的改进的基于田间…

如何在 3ds Max 中使用 Mental Ray 制作逼真的草地和带有光晕的天空

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 首先&#xff0c;您将创建一个平面对象&#xff0c;然后添加一个噪点修改器。在此之上应用毛发和毛皮修饰符。 这将用于模拟逼真的草地。 我们用日光系统创造太阳和天空。为太阳添加镜头和戒指效果以及酷炫…

ES6类-继承-Symbol-模版字符串

目录 类 继承 ES5 如何继承 ES6继承 Symbol 用途 可以产生唯一的值&#xff0c;独一无二的值 解决命名冲突 getOwnPropertySymbols() 作为全局注册表 缓存 Symbol.for() 消除魔术字符串 模版字符串 类 在javascript语言中&#xff0c;生成实例对象使用构造函数&#xf…

使用Linux Deploy搭建服务器(三)Linux Deploy安装宝塔面板

宝塔面板是一个免费的服务器管理平台&#xff0c;可以在你的服务器上安装它&#xff0c;然后你就能很方便的管理你的服务器&#xff0c;以及搭建各种服务平台&#xff0c;在此基础上我们可以使用内网穿透&#xff0c;搭建出自己的Linux服务器。可以这样一个相对便宜的方式&…

【数学建模】利用C语言来实现 太阳赤纬 太阳高度角 太阳方位角 计算和求解分析 树木树冠阴影面积与种植间距的编程计算分析研究

太阳赤纬的计算 #include <stdio.h> #include <math.h>double calculateDelta(int year, int month, int day, int hour, int minute, int second) {int n, n0;double t, theta, delta;// 计算n和n0n month * 30 day;n0 79.6764 0.2422 * (year - 1985) - ((y…

前端Vue仿微信我的菜单栏组件按钮组件

随着技术的发展&#xff0c;开发的复杂度也越来越高&#xff0c;传统开发方式将一个系统做成了整块应用&#xff0c;经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改&#xff0c;造成牵一发而动全身。 通过组件化开发&#xff0c;可以有效实现…

Oracle Profile概念与示例

Profile和SQL Profile是不同的&#xff0c;前者是用CREATE PROFILE创建&#xff0c;后者和SQL Tuning有关。 profile的定义为&#xff1a; which is a set of limits on database resources. If you assign the profile to a user, then that user cannot exceed these limits…