图像锐化-拉普拉斯算子 Sobel算子

算子解释

   广义的讲,对任何函数进行某一项操作都可以认为是一个算子,甚至包括求幂次,开方都可以认为是一个算子,只是有的算子我们用了一个符号来代替他所要进行的运算罢了,所以大家看到算子就不要纠结,他和f(x)的f没区别,它甚至和加减乘除的基本运算符号都没有区别,只是他可以对单对象操作罢了(有的符号比如大于、小于号要对多对象操作)。又比如取概率P{X<x},概率是集合{X<x}(他是属于实数集的子集)对[0,1]区间的一个映射,我们知道实数域和[0,1]区间是可以一一映射的(这个后面再说),所以取概率符号P,我们认为也是一个算子,和微分,积分算子算子没区别。总而言之,算子就是映射,就是关系,就是变换。

算子_百度百科

 一.Sobel 算子

Sobel 算子是一种用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导。该算子用于计算图像明暗程度近似值,根据图像边缘旁边明暗程度把该区域内超过某个数的特定点记为边缘。Sobel 算子在 Prewitt 算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓 [1-4]。

Sobel 算子的边缘定位更准确,常用于噪声较多、灰度渐变的图像。其算法模板如公式(1)所示,其中 dx 表示水平方向,dy 表示垂直方向 [3]。

图片

其像素计算公式如下:

图片

Sobel 算子像素的最终计算公式如下:

图片

Sobel 算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息。因为 Sobel 算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel 算子是一种较为常用的边缘检测方法。

Python 和 OpenCV 将 Sobel 算子封装在 Sobel () 函数中,其函数原型如下所示:

dst = Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])– src 表示输入图像– dst 表示输出的边缘图,其大小和通道数与输入图像相同– ddepth 表示目标图像所需的深度,针对不同的输入图像,输出目标图像有不同的深度– dx 表示 x 方向上的差分阶数,取值 1 或 0– dy 表示 y 方向上的差分阶数,取值 1 或 0– ksize 表示 Sobel 算子的大小,其值必须是正数和奇数– scale 表示缩放导数的比例常数,默认情况下没有伸缩系数– delta 表示将结果存入目标图像之前,添加到结果中的可选增量值– borderType 表示边框模式,更多详细信息查阅 BorderTypes

 注意,在进行 Sobel 算子处理之后,还需要调用 convertScaleAbs () 函数计算绝对值,并将图像转换为 8 位图进行显示。其算法原型如下:

dst = convertScaleAbs(src[, dst[, alpha[, beta]]])– src 表示原数组– dst 表示输出数组,深度为 8 位– alpha 表示比例因子– beta 表示原数组元素按比例缩放后添加的值

Sobel 算子的实现代码如下所示。

# -*- coding: utf-8 -*-# By:Eastmountimport cv2import numpy as npimport matplotlib.pyplot as plt#读取图像img = cv2.imread('luo.png')lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)#灰度化处理图像grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#Sobel算子x = cv2.Sobel(grayImage, cv2.CV_16S, 1, 0) #对x求一阶导y = cv2.Sobel(grayImage, cv2.CV_16S, 0, 1) #对y求一阶导absX = cv2.convertScaleAbs(x)absY = cv2.convertScaleAbs(y)Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)#用来正常显示中文标签plt.rcParams['font.sans-serif']=['SimHei']#显示图形titles = ['原始图像', 'Sobel算子']images = [lenna_img, Sobel]for i in range(2):plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show()

其运行结果如图所示: 

二.Laplacian 算子

laplacian  /lɑ:'plɑ:siən/     n.[数] 拉普拉斯算子(调和算子)adj.[数] 拉普拉斯算子的(调和算子的)

如果将一系列计算规则或公式规定为某个特定名称(梯度、拉普拉斯算子等等),那它的背后肯定有个符合直觉的描述,而不是硬生生地去记住计算规则

试想一下,当面对一个复杂的数学公式,其中包含拉普拉斯算子,你还要回想一下算子是怎么个计算规则,这对于公式整体的理解是很有阻碍的。

其实它的含义一句话就能说明白:拉普拉斯算子描述函数当前值f(x)与其附近周边点的平均值之间的差值(deviation from the nearby average)。有了这样直觉性理解,就能更透彻明白其在工程中的应用了:

图片

上面是正常图像经过拉普拉斯算子卷积滤波(也就是对每个像素进行与周围像素平均值差值处理)得到的轮廓图。为什么这样的图像处理可以得到物体轮廓呢?因为物体轮廓的像素和附近像素(背景或其他物体)平均值的偏差一般都很大,把差值设定一个阈值,进行黑白阶跃处理,就能得到物体的轮廓。

 

拉普拉斯算子是二阶微分线性算子,在图像边缘处理中,二阶微分的边缘定位能力更强,锐化效果更好,因此在进行图像边缘处理时,直接采用二阶微分算子而不使用一阶微分。

离散函数的导数退化成了差分,一维一阶差分公式和二阶差分公式分别为:

分别对Laplace算子x,y两个方向的二阶导数进行差分就得到了离散函数的Laplace算子。在一个二维函数f(x,y)中,x,y两个方向的二阶差分分别为:

所以Laplace算子的差分形式为:


写成filter mask的形式如下:

该mask的特点,mask在上下左右四个90度的方向上结果相同,也就是说在90度方向上无方向性。为了让该mask在45度的方向上也具有该性质,对该filter mask进行扩展定义为:

将Laplace算子写成filter mask后,其操作大同小异于其他的空间滤波操作。将filter mask在原图上逐行移动,然后mask中数值与其重合的像素相乘后求和,赋给与mask中心重合的像素,对图像的第一,和最后的行和列无法做上述操作的像素赋值零,就得到了拉普拉斯操作结果。因为Laplace算子是二阶导数操作,其在强调图像素中灰度不连续的部分的同时也不在强调灰度值连续的部分。这样会产生一个具有很明显的灰度边界,但是没有足够特征的黑色背景。背景特征可以通过原图像与Laplace算子操作后的图像混合恢复,公式如下:

进一步推导如下:


写成filter mask的形式如下:

扩展定义为:


高斯-拉普拉斯算子

由于拉普拉斯算子对图片中的噪声很敏感。因此,为了解决这一问题,我们一般会在进行拉普拉斯操作之前先对图像进行高斯平滑滤波处理,得到高斯-拉普拉斯算子(LoG)。
高斯-拉普拉斯算子是效果更好的边缘检测器,它把高斯平滑器和拉普拉斯锐化结合起来。先平滑掉噪声,再进行边缘检测。
模版例子如下:

拉普拉斯(Laplacian)算子是 n 维欧几里德空间中的一个二阶微分算子,常用于图像增强领域和边缘提取。它通过灰度差分计算邻域内的像素,基本流程是:

  • 判断图像中心像素灰度值与它周围其他像素的灰度值;

  • 如果中心像素的灰度更高,则提升中心像素的灰度;

  • 反之降低中心像素的灰度,从而实现图像锐化操作。

在算法实现过程中,Laplacian 算子通过对邻域中心像素的四方向或八方向求梯度再将梯度相加起来判断中心像素灰度与邻域内其他像素灰度的关系最后通过梯度运算的结果对像素灰度进行调整 [2]。

一个连续的二元函数 f (x,y),其拉普拉斯运算定义为:

图片

Laplacian 算子分为四邻域和八邻域,四邻域是对邻域中心像素的四方向求梯度,八邻域是对八方向求梯度。其中,四邻域模板如公式(5)所示:

图片

其像素的计算公式可以简化为:

图片

通过模板可以发现,当邻域内像素灰度相同时,模板的卷积运算结果为 0;当中心像素灰度高于邻域内其他像素的平均灰度时,模板的卷积运算结果为正数;当中心像素的灰度低于邻域内其他像素的平均灰度时,模板的卷积为负数。对卷积运算的结果用适当的衰弱因子处理并加在原中心像素上,就可以实现图像的锐化处理。

Laplacian 算子的八邻域模板如下:

图片

其像素的计算公式可以简化为:

图片

Python 和 OpenCV 将 Laplacian 算子封装在 Laplacian () 函数中,其函数原型如下所示:

dst = Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])– src 表示输入图像– dst 表示输出的边缘图,其大小和通道数与输入图像相同– ddepth 表示目标图像所需的深度– ksize 表示用于计算二阶导数的滤波器的孔径大小,其值必须是正数和奇数,且默认值为 1,更多详细信息查阅 getDerivKernels– scale 表示计算拉普拉斯算子值的可选比例因子。默认值为 1,更多详细信息查阅 getDerivKernels– delta 表示将结果存入目标图像之前,添加到结果中的可选增量值,默认值为 0– borderType 表示边框模式,更多详细信息查阅 BorderTypes

注意,Laplacian 算子其实主要是利用 Sobel 算子的运算,通过加上 Sobel 算子运算出的图像 x 方向和 y 方向上的导数,得到输入图像的图像锐化结果。

同时,在进行 Laplacian 算子处理之后,还需要调用 convertScaleAbs () 函数计算绝对值,并将图像转换为 8 位图进行显示。其算法原型如下:

dst = convertScaleAbs(src[, dst[, alpha[, beta]]])– src 表示原数组– dst 表示输出数组,深度为 8 位– alpha 表示比例因子– beta 表示原数组元素按比例缩放后添加的值

当 ksize=1 时,Laplacian () 函数采用 3×3 的孔径(四邻域模板)进行变换处理。下面的代码是采用 ksize=3 的 Laplacian 算子进行图像锐化处理,其代码如下:

# -*- coding: utf-8 -*-# By:Eastmountimport cv2import numpy as npimport matplotlib.pyplot as plt#读取图像img = cv2.imread('luo.png')lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)#灰度化处理图像grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#拉普拉斯算法dst = cv2.Laplacian(grayImage, cv2.CV_16S, ksize = 3)Laplacian = cv2.convertScaleAbs(dst)#用来正常显示中文标签plt.rcParams['font.sans-serif']=['SimHei']#显示图形titles = ['原始图像', 'Laplacian算子']images = [lenna_img, Laplacian]for i in range(2):plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show()

其运行结果如图 2 所示:

图片

边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此需要采用滤波器来过滤噪声,并调用图像增强或阈值化算法进行处理,最后再进行边缘检测。下面是采用高斯滤波去噪和阈值化处理之后,再进行边缘检测的过程,并对比了四种常见的边缘提取算法。

# -*- coding: utf-8 -*-# By:Eastmountimport cv2import numpy as npimport matplotlib.pyplot as plt#读取图像img = cv2.imread('luo.png')lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#灰度化处理图像grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#高斯滤波gaussianBlur = cv2.GaussianBlur(grayImage, (3,3), 0)#阈值处理ret, binary = cv2.threshold(gaussianBlur, 127, 255, cv2.THRESH_BINARY)#Roberts算子kernelx = np.array([[-1,0],[0,1]], dtype=int)kernely = np.array([[0,-1],[1,0]], dtype=int)x = cv2.filter2D(binary, cv2.CV_16S, kernelx)y = cv2.filter2D(binary, cv2.CV_16S, kernely)absX = cv2.convertScaleAbs(x)absY = cv2.convertScaleAbs(y)Roberts = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)#Prewitt算子kernelx = np.array([[1,1,1],[0,0,0],[-1,-1,-1]], dtype=int)kernely = np.array([[-1,0,1],[-1,0,1],[-1,0,1]], dtype=int)x = cv2.filter2D(binary, cv2.CV_16S, kernelx)y = cv2.filter2D(binary, cv2.CV_16S, kernely)absX = cv2.convertScaleAbs(x)absY = cv2.convertScaleAbs(y)Prewitt = cv2.addWeighted(absX,0.5,absY,0.5,0)#Sobel算子x = cv2.Sobel(binary, cv2.CV_16S, 1, 0)y = cv2.Sobel(binary, cv2.CV_16S, 0, 1)absX = cv2.convertScaleAbs(x)absY = cv2.convertScaleAbs(y)Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)#拉普拉斯算法dst = cv2.Laplacian(binary, cv2.CV_16S, ksize = 3)Laplacian = cv2.convertScaleAbs(dst)#效果图titles = ['Source Image', 'Binary Image', 'Roberts Image','Prewitt Image','Sobel Image', 'Laplacian Image']images = [lenna_img, binary, Roberts, Prewitt, Sobel, Laplacian]for i in np.arange(6):plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show()

输出结果如图 3 所示。其中,Laplacian 算子对噪声比较敏感,由于其算法可能会出现双像素边界,常用来判断边缘像素位于图像的明区或暗区,很少用于边缘检测;Robert 算子对陡峭的低噪声图像效果较好,尤其是边缘正负 45 度较多的图像,但定位准确率较差;Prewitt 算子对灰度渐变的图像边缘提取效果较好,而没有考虑相邻点的距离远近对当前像素点的影响;Sobel 算子考虑了综合因素,对噪声较多的图像处理效果更好。

图片

三、总结

本文主要介绍图像锐化和边缘检测知识,详细讲解了 Sobel 算子和 Laplacian 算子,并通过小珞珞图像进行边缘轮廓提取。图像锐化和边缘提取技术可以消除图像中的噪声,提取图像信息中用来表征图像的一些变量,为图像识别提供基础。

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

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

相关文章

Sentinel 规则持久化,基于Redis持久化【附带源码】

B站视频讲解 学习链接&#x1f517; 文章目录 一、理论二、实践2-1、dashboard 请求Redis2-1-1、依赖、配置文件引入2-1-2、常量定义2-1-3、改写唯一id2-1-4、新Provider和Publisher2-1-5、改写V2 2-2、应用服务改造2-2-1、依赖、配置文件引入2-2-2、注册监听器 三、源码获取3…

Talk|加州大学圣地亚哥分校程旭欣:视觉反馈下足式机器人的全身操作与运动

本期为TechBeat人工智能社区第576期线上Talk。 北京时间3月6日(周三)20:00&#xff0c;加州大学圣地亚哥分校博士生—程旭欣的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “视觉反馈下足式机器人的全身操作与运动”&#xff0c;向大家系统地介绍…

智能驾驶规划控制理论学习07-规划算法整体框架

一、解耦合策略 1、路径-速度解耦策略概述 路径-速度解耦指的是将车辆的运动分成路径规划和速度规划两部分&#xff0c;对两个部分分别进行研究。 路径规划&#xff1a; 假设环境是“静态的”&#xff0c;将障碍物投射到参考路径上&#xff0c;并规划一条避开它们的路径&…

【C语言】linux内核napi_gro_receive和netif_napi_add

napi_gro_receive 一、注释 // napi_gro_receive是网络设备接口的一个函数&#xff0c;它被NAPI&#xff08;New API&#xff09;网络轮询机制使用&#xff0c;用于接收和处理接收到的数据包。 // 这个函数通过通用接收分组&#xff08;GRO&#xff0c;Generic Receive Offlo…

Ubuntu安装conda以后,给jupyter安装C++内核

前言 大家都知道&#xff0c;jupyter notebook 可以支持python环境&#xff0c;可以在不断点调试的情况下&#xff0c;打印出当前结果&#xff0c;如果代码错了也不影响前面的内容。于是我就想有没有C环境的&#xff0c;结果还真有。 参考文章&#xff1a; 【分享】Ubuntu安装…

【金三银四的季节看下Java ORM的走向和性能对比】总结

写在最后 经过将近一周时间的框架收集、学习、实验、编码、测试市面上常见的ORM框架&#xff0c;过程中拜读了很多作者的博文、样例&#xff0c;学习很多收获很多。 重新梳理下整理的框架&#xff1a;mybatis-plus、lazy、sqltoy、mybatis-flex、easy-query、mybatis-mp、jpa、…

什么是工业交换机?

如今&#xff0c;工业交换机在能源、环保、交通、智慧城市监控等各个行业都发挥着至关重要的作用&#xff0c;其需求也日益增长。本文将全面介绍工业交换机&#xff0c;帮助你进一步加深了解。 什么是工业交换机&#xff1f; 工业交换机&#xff0c;又称工业以太网交换机&…

《探索自动驾驶技术的前景与挑战》

自动驾驶技术,作为现代科技的一大突破,正逐渐改变着我们的交通方式、生活方式以及整个社会结构。本文将围绕自动驾驶技术的现状、优势、局限性以及未来发展趋势展开探讨。 自动驾驶技术的现状概述 自动驾驶技术作为当今科技领域的一项前沿技术,已经取得了巨大的进展并在不同…

安卓开发之资源概述、优劣分析与优化方案

摘要 随着智能手机的普及&#xff0c;Android操作系统已成为全球最广泛使用的移动平台之一。在Android应用开发中&#xff0c;资源管理是构建高效、响应迅速且用户友好的应用程序的关键要素。 本文主要探讨了安卓应用程序开发过程中的资源管理机制&#xff0c;包括其基本结构、…

一键清除JavaScript代码中的注释:使用正则表达式实现

这个正则表达式可以有效地匹配 JavaScript 代码中的各种注释&#xff0c;并且跳过了以 http: 或 https: 开头的链接。 /\/\*[\s\S]*?\*\/|\/\/[^\n]*|<!--[\s\S]*?-->|(?<!http:|https:)\/\/[^\n]*/gvscode 实战&#xff0c;ctrlF 调出查找替换工具&#xff0c;点…

如何把网页调用变为代码调用

1.背景 最近有一个需求&#xff0c;猜测一段十六进制流的校验方式&#xff0c;挨个尝试非常耗时&#xff0c;需要写代码&#xff0c;调用网页上的功能。 2.解决方案 可以使用Python的 requests 库来发起HTTP请求&#xff0c;并通过POST请求将数据发送给服务器进行计算CRC校验和…

【备战蓝桥杯系列】Java组国二选手笔记一:蓝桥杯中的常用语法特性

蓝桥杯Java国二选手笔记一&#xff1a;蓝桥杯中的常用语法特性 前言 参加了好几次蓝桥杯了&#xff0c;C组参加了&#xff0c;Java也参加过&#xff0c;也会用python刷算法。下面给出常用的Java语法特性在蓝桥杯中的使用&#xff0c;以及常见的需要注意的Java语法规范。有准备…

【MySQL】-知识点整理

1、存储引擎 -- 查询数据库支持的存储引擎 show engines; -- 查询当前数据库使用的存储引擎 show variables like %storage_engines%; 主要的存储引擎说明&#xff1a; 1&#xff09;MyISAM&#xff1a;无外键、表锁、所有索引都是非聚簇索引、无事务、记录表总条数、删除表…

基于el-tree实现懒加载穿梭条

一、关键代码 <template><div><!-- 左侧待选列表 --><div class"left-box"><p>待选列表</p><el-input placeholder"输入关键词过滤" v-model"leftFilterText" clearable/><el-treeref"tree…

便捷在线导入:完整Axure元件库集合,让你的设计更高效!

Axure元件库包含基本的工具组件&#xff0c;可以使原型绘制节省大量的重复工作&#xff0c;保持整个设计页面的一致性和标准化&#xff0c;同时显得专业。Axure元件库就像我们日常生活中的门把手、自行车踏板和桌子上的螺丝钉&#xff0c;需要组装才能使用。作为一名成熟的产品…

【Web - 框架 - Vue】随笔 - Vue的简单使用(02) - 快速上手

【Web - 框架 - Vue】随笔 - Vue的简单使用(02) - 快速上手 Vue模板代码 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Vue模板</title> </head> <body> <div id"…

redis 性能优化二

前言 性能优化的第二篇文章&#xff0c;将重点讲一下Redis 的响应延迟&#xff0c;响应延迟如何对redis 进行优化。这个延迟不是说一个命令或者几个命令变慢了&#xff0c;延迟了几秒&#xff0c;就说Redis 变慢了。在不同的软硬件环境下&#xff0c;Redis 本身的绝对性能并不…

基于STM32开路清障车控制系统设计

目 录 摘 要 I Abstract II 引 言 1 1总体方案论证与设计 3 1.1设计方案 3 1.2主控模块的选型和论证 3 2系统硬件电路设计 5 2.1主控模块设计 5 2.1.1 STM32单片机概述 5 2.1.2 STM32单片机最小系统电路 5 2.2 MCU主要实现功能 6 2.3火焰传感器 7 2.4超声波模块 8 2.5驱动模块…

Docker-自定义镜像

目录 1 前言 2 构建java应用的步骤及镜像结构图 2.1 构建步骤 2.2 镜像结构图 3 Dockerfile常用指令 4 Dockerfile的内容举例 4.1 一般形式 4.2 一般形式的优化 5 构建镜像 5.1 指令 5.2 实操 5.2.1 加载jdk镜像(基础镜像) 5.2.2 构建我们的镜像 5.2.3 使用我们的…

SpringCloud微服务-RabbitMQ快速入门

文章目录 RabbitMQ快速入门1、什么是MQ&#xff1f;2、RabbitMQ概述3、RabbitMQ的结构和概念4、常见消息模型5、HelloWorld RabbitMQ快速入门 1、什么是MQ&#xff1f; MQ &#xff08;MessageQueue&#xff09;&#xff0c;中文是消息队列&#xff0c;字面来看就是存放消息的…