去噪、梯度与边缘检测

图像噪点消除

噪声在图像处理中指的是图像中出现的干扰因素,通常由采集设备或传输过程引起。噪声使得图像的亮度变得不均匀或引入了随机的干扰点。常见的噪声类型包括:

  • 高斯噪声:符合正态分布的噪声,会使图像变得模糊或出现噪点。其噪声值是从正态分布中随机生成的。

  • 椒盐噪声:图像中出现的随机黑点或白点,类似于“椒盐”撒在图像上,使图像看起来像被打上了斑点。

滤波器(或卷积核)是一种用于处理图像的工具,通过在图像上滑动并计算周围像素的加权平均值来平滑或锐化图像。滤波器分为线性和非线性两类:

  • 线性滤波器:对邻域像素进行线性运算,例如均值滤波和高斯滤波。均值滤波器通过计算邻域像素的平均值来平滑图像,高斯滤波器则通过高斯函数加权邻域像素来实现平滑。

  • 非线性滤波器:根据像素间的逻辑关系处理图像,例如中值滤波和双边滤波。中值滤波器用邻域像素的中值替代中心像素值,适合去除椒盐噪声;双边滤波器结合了空间距离和像素值差异,能在平滑图像的同时保持边缘细节。

滤波与模糊的联系与区别

  • 联系:滤波和模糊都涉及卷积操作,线性滤波方法通过不同的卷积核实现各种效果。

  • 区别:

    • 低通滤波器(如均值滤波、高斯滤波)用于模糊图像,去除噪声和平滑图像,因为它们允许低频信号通过,滤除高频噪声。

    • 高通滤波器用于锐化图像,增强边缘细节,因为它们允许高频信号通过,抑制低频信号。

简言之,椒盐噪声像图像上的黑白斑点,高斯噪声则像由光照等因素造成的随机干扰。滤波技术通过调整图像的频率成分来处理这些噪声,实现图像的清晰或模糊效果。

1.均值滤波
  • 原理:用固定大小的卷积核在图像上滑动,将核覆盖区域内所有像素的平均值作为中心像素的新值。

    如3×3的卷积核:

  • 效果:平滑图像,去除噪声,但可能会模糊细节和边缘。

2.方框滤波
  • 原理:类似均值滤波,使用一个形状为方框的卷积核。计算方框内所有像素的平均值,用于平滑图像。

    如3×3的滤波核如下:

  • 效果:简单有效的平滑技术,但对边缘处理不够好,可能导致边缘模糊。

3.高斯滤波
  • 原理:使用高斯函数生成的卷积核,对图像进行加权平均。中心像素权重最大,离中心越远权重越小。

    高斯公式:

    其中的值也是与自适应二值化里的一样,当时会取固定的系数,当kernel大于7并且没有设置时,会使用固定的公式进行计算$\sigma$的值:

    以3*3的卷积核为例:

  • 效果:平滑图像同时保留细节,相比均值滤波能更好地减少噪声。

4.中值滤波
  • 原理:在每个像素的邻域内,将所有像素值排序,选择中间值作为中心像素的新值。

  • 效果:有效去除椒盐噪声,保持边缘锐利,但计算量较大。

5.双边滤波
  • 原理:结合空间距离和像素值差异进行滤波。既考虑像素位置距离,也考虑像素值的相似性,以平滑噪声同时保留边缘。

    双边滤波采用了两个高斯滤波的结合,一个负责计算空间邻近度的权值(也就是空域信息),也就是上面的高斯滤波器,另一个负责计算像素值相似度的权值(也就是值域信息),也是一个高斯滤波器。其公式如下所示:

  • 效果:在去噪的同时能够较好地保留图像的边缘细节。

    import cv2
    img = cv2.imread('./src/lvbo2.png')
    img1 = cv2.blur(img, (3, 3))  # 均值滤波
    img2 = cv2.boxFilter(img, -1,(3, 3),normalize=True)  # 方框滤波
    img3 = cv2.GaussianBlur(img, (3, 3),1)  # 高斯滤波
    img4 = cv2.medianBlur(img,3) #中值滤波
    img5 = cv2.bilateralFilter(img,10,80,75) #双边滤波
    cv2.imshow("img", img)
    cv2.imshow("img1", img1)
    cv2.imshow("img2", img2)
    cv2.imshow("img3", img3)
    cv2.imshow("img4", img4)
    cv2.imshow("img5", img5)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

图像梯度处理

1.图像梯度

在高等数学中,我们利用一阶导数来求函数的极值。同样地,可以将图像视为一个连续的二维函数。在图像中,边缘部分的像素值与周围像素值存在明显差异,因此,通过局部求极值的方法,我们可以提取出图像的边缘信息。然而,由于图像是离散的二维函数,我们采用差分的方法来近似导数,这种差分被称为图像的梯度。

2.垂直边缘提取

cv2.filter2D 函数用于对图像进行二维卷积操作,允许使用自定义的卷积核来实现各种图像处理效果,如平滑、锐化和边缘检测。以下是参数的简要说明:

  • src: 输入图像,通常为 numpy 数组。

  • ddepth: 输出图像的深度。如果设为 -1,则输出图像与输入图像具有相同的深度。可以设为其他正值或特定值来控制输出图像的深度。

  • kernel: 卷积核,是一个二维数组(通常为奇数大小的矩阵),用于计算每个像素周围邻域的加权和。

3.Sobel算子

Sobel 算子是一种用于图像边缘检测的经典算子,它通过计算图像梯度来识别边缘。Sobel 算子有两个方向的卷积核,分别用于计算图像在水平方向和垂直方向的梯度。

在使用 cv2.Sobel 函数时,你可以设置以下参数:

  • src: 输入图像,通常是灰度图像,因为 Sobel 算子是基于像素亮度计算梯度的。如果图像是彩色的,你需要先将其转换为灰度图像。

  • ddepth: 输出图像的深度,通常设置为 -1,表示输出图像的深度与输入图像相同。

  • dxdy: 分别表示计算图像在 x 方向和 y 方向的梯度。dx=1dy=0 表示计算 x 方向的一阶导数,dx=0dy=1 表示计算 y 方向的一阶导数。

  • ksize: Sobel 算子的大小,通常选择 3、5 或 7,默认值是 3。

这些算子提供了不同的边缘检测效果,选择适当的算子可以根据实际应用需求来确定。

4.Laplacian算子

在 OpenCV 中,使用 cv2.Laplacian(src, ddepth) 进行 Laplacian 运算,其中 src 是输入图像,ddepth 表示输出图像的深度,-1 表示输出图像深度与输入图像相同。

import cv2
import numpy as np
img=cv2.imread('./src/shudu.png',cv2.IMREAD_GRAYSCALE)
kernel=np.array([[-1,0,1],[-2,0,2],[-1,0,1]], dtype=np.float32)
img1=cv2.filter2D(img,-1,kernel) #垂直边缘提取
img2=cv2.filter2D(img, -1, kernel.T) #水平边缘提取
#Sobel算子
img3=cv2.Sobel(img,-1,1,0,ksize=3) #水平方向的梯度,垂直边缘提取
img4=cv2.Sobel(img,-1,0,1,ksize=3) #垂直方向的梯度,水平边缘提取
​
# Laplacian算子
img5=cv2.Laplacian(img,-1)
​
cv2.imshow("img",img)
cv2.imshow("img1",img1)
cv2.imshow("img2",img2)
cv2.imshow("img3",img3)
cv2.imshow("img4",img4)
cv2.imshow("img5",img5)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像边缘检测

Canny 边缘检测算法是一种非常流行的边缘检测算法,是 John F. Canny 于 1986年提出的,被认为是最优的边缘检测算法。

操作步骤按照如下进行:

  1. 读取图像

  2. 二值化图像。

  3. 高斯滤波。

  4. 计算图像的梯度和方向。

  5. 非极大值抑制。

  6. 双阈值筛选。

1.高斯滤波

边缘检测是一种锐化操作,对噪声较为敏感。因此,在进行边缘检测之前,通常需要对图像进行平滑处理,以减少噪声的影响。这里我们使用一个 5x5 的高斯核来实现高斯滤波,消除图像中的噪声。

高斯滤波器的公式可以用来计算每个像素周围的加权平均值,权重由高斯函数决定,越接近中心的像素权重越大,越远离中心的像素权重越小。这有助于保留图像的边缘信息,同时模糊掉较小的噪声。

2. 计算图像的梯度与方向
1. 使用Sobel算子计算梯度
  • 水平方向Sobel算子:

  • 垂直方向Sobel算子:

应用这两个算子分别得到水平方向的梯度 Gx和垂直方向的梯度 Gy。

2. 计算梯度大小和方向
  • 梯度大小:

  • 或者简化版本:

    G=∣Gx+Gy∣

  • 梯度方向:

    这个角度值其实是当前边缘的梯度的方向

    注意处理当 Gx=0的情况,以避免除以零的错误。

3. 非极大值抑制 (Non-Maximum Suppression)
  • 如果梯度方向不是标准的角度(如0°、45°、90°、135°),需要进行插值来确定是否保留该像素作为边缘的一部分。通常使用线性插值来计算邻近像素的梯度值,并检查中心像素是否为局部最大值。

4. 双阈值筛选 (Double Thresholding)
  • 选择阈值:

    • 选取一个高阈值 Thigh和一个低阈值Tlow,其中 Tlowl<Thigh。常见的比例是 Tlow=0.05×Thigh 到 Tlow=0.2×Thigh。

  • 边缘分类:

    • 强边缘: 如果梯度 G>Thigh,则该像素标记为强边缘。

    • 弱边缘: 如果 Tlow<G<G<Thigh,则该像素标记为弱边缘。

    • 非边缘: 如果 G≤Tlow,则该像素不被视为边缘。

实现步骤
  1. 计算梯度:

    • 应用Sobel算子计算每个像素点的 Gx和 Gy。

    • 计算梯度大小 G和方向 θ

  2. 非极大值抑制:

    • 根据梯度方向 θ,使用适当的插值方法计算邻近像素的梯度值。

    • 检查中心像素的梯度是否大于其两个邻近像素的梯度值。如果不是,则抑制该像素。

  3. 双阈值筛选:

    • 使用 Tlow和 Thigh 标记强边缘和弱边缘。

    • 弱边缘只有在其至少有一个相邻像素被标记为强边缘的情况下才保留下来。

  4. 边缘连接:

    • 从每个强边缘像素开始,递归地检查其相邻像素中是否有其他强边缘或符合条件的弱边缘。

    • 将符合条件的弱边缘连接到强边缘上。

      import cv2
      img=cv2.imread("./src/e.png")
      img1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
      ret,img2=cv2.img1old(img1,127,255,cv2.img1_BINARY)
      img3=cv2.Canny(img2,30,100)
      cv2.imshow("img",img)
      cv2.imshow("img3",img3)
      cv2.waitKey(0)

绘制图像轮廓

  1. 加载图像:使用 OpenCV 加载图像。

  2. 转换为灰度图像:将图像转换为灰度,以简化处理。

  3. 应用边缘检测:使用边缘检测算法,如 Canny 边缘检测。

  4. 绘制轮廓:利用 OpenCV 的 findContoursdrawContours 函数来找到并绘制轮廓。

import cv2
img=cv2.imread("./src/e.png")
img1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,img2=cv2.img1old(img1,127,255,cv2.img1_BINARY_INV+cv2.img1_OTSU)
# 查找轮廓
# cv2.RETR_EXTERNAL  cv2.RETR_CCOMP  cv2.RETR_LIST cv2.RETR_TREE
c,h=cv2.findContours(img2,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(img,c,-1,(0,0,255),2)
cv2.imshow("img",img)
cv2.imshow("img2",img2)
cv2.waitKey(0)

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

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

相关文章

Java基础之switch分支语句

switch分支语句 ​ switch语句也称为分支语句&#xff0c;其和if语句有点类似&#xff0c;都是用来判断值是否相等&#xff0c;但switch默认只支持byte、short、int、char这四种类型的比较&#xff0c;JDK8中也允许String类型的变量做对比。 语法&#xff1a; switch (表达式…

8.15 哈希表中等 139 Word Break review 467 Unique Substrings in Wraparound String

139 Word Break【逐一对比vs.多种 分割 组合】 片面思考的思路&#xff1a; class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {//字符串和对应的字典&#xff0c;如果s种可以用空格分隔出一个或多个字典里的词就返回true//核心&#x…

windows 安装TVM

TVM支持在Windows环境下使用&#xff0c;但需要一些额外的配置。以下是如何在Windows Python环境中安装TVM的详细步骤。 1. 安装TVM的预备条件 在Windows上安装TVM之前&#xff0c;需要确保系统已经安装了以下工具和依赖项&#xff1a; Visual Studio: 安装包含C开发工具的V…

利用ZXing.Net Bindings for EmguCV识别条形码及绘制条形码边框17(C#)

上一篇博文&#xff1a;绘制条形码的效果不是很好&#xff1a;利用Emgucv绘制条形码边框16(C#)-CSDN博客 测试环境&#xff1a; win11 64位操作系统 visual studio 2022 ZXing.Net.Bindings.EmguCV 0.16.4 测试步骤如下&#xff1a; 1 新建.net framework 4.8的控制台项目…

Linux日常运维-主机名hosts

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 本小章内容就是Linux进阶部分的日常运维部分&#xff0c;掌握这些日常运维技巧或者方法在我们的日常运维过程中会带来很多方…

【Vue3】嵌套路由

【Vue3】嵌套路由 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本文内…

【Linux】缓冲区和文件系统

目录 一、缓冲区 1.1 概念 1.2 用户缓冲区和内核缓冲区 二、磁盘的结构 三、文件系统 3.1 初识“块”和inode 3.2 磁盘分区和文件系统 一、缓冲区 1.1 概念 要理解什么是缓冲区&#xff0c;先看这段代码 #include <stdio.h> #include <string.h> #includ…

Linux系统驱动(十八)SPI总线(未整理)

文章目录 一、SPI总线协议简介二、SPI子系统驱动&#xff08;二&#xff09;SPI子系统API&#xff08;三&#xff09;SPI设备树节点 三、代码示例 一、SPI总线协议简介 高速、同步、全双工、非差分、总线式 传输速度在几十M 差分总线和非差分总线 非差分总线&#xff1a;受压…

江协科技STM32学习笔记(第13章 WDG看门狗)

第13章 WDG看门狗 13.1 WDG看门狗 13.1.1 WDG简介 看门狗就是程序运行的一个保障措施&#xff0c;我们得在程序中定期地喂狗&#xff0c;如果程序卡死了&#xff0c;没有在规定的时间里喂狗&#xff0c;那么看门狗硬件电路就会自动帮我们复位一下&#xff0c;防止程序长时间…

最新爆火文生图模型FLUX

在AI图片生成领域&#xff0c;Flux模型的推出引起了广泛关注。随着AI技术的不断进步&#xff0c;新的模型层出不穷&#xff0c;而Flux正是其中的一颗新星。 Flux&#xff1a;一款迅速走红的AI图片生成模型 8月初&#xff0c;初创公司Black Forest Labs推出了文本生成图像模型…

米联客-FPGA程序设计Verilog语法入门篇连载-10 Verilog语法_一般设计规范

软件版本&#xff1a;无 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用所有系列FPGA 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑&#xff01; 1概述 本小节讲解Verilog语法的一般…

合并两个有序数组(LeetCode)

题目 给你两个按 非递减顺序 排列的整数数组 和 &#xff0c;另有两个整数 和 &#xff0c;分别表示 和 中的元素数目。请你 合并 到 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并后数组不应由函数返回&#xff0c;而是…

Docker最佳实践进阶(一):Dockerfile介绍使用

大家好&#xff0c;上一个系列我们使用docker安装了一系列的基础服务&#xff0c;但在实际开发过程中这样一个个的安装以及繁杂命令不仅仅浪费时间&#xff0c;更是容易遗忘&#xff0c;下面我们进行Docker的进阶教程&#xff0c;帮助我们更快速的部署和演示项目。 一、什么是…

【初阶数据结构】通讯录项目(可用作课程设计)

文章目录 概述1. 通讯录的效果2. SeqList.h3. Contact.h4. SeqList.c5. Contact.c6. test.c 概述 通讯录项目是基于顺序表这个数据结构来实现的。如果说数组是苍蝇小馆&#xff0c;顺序表是米其林的话&#xff0c;那么通讯录就是国宴。 换句话说&#xff0c;通讯录就是顺序表…

个人可识别信息(PII) AI 去除 API 数据接口

个人可识别信息(PII) AI 去除 API 数据接口 ai / 隐私保护 基于 AI 模型自动去除个人识别信息&#xff08;PII&#xff09; 个人信息保护 / AI 模型 。 1. 产品功能 基于自有专业模型进行 PII 自动去除高效处理敏感信息全接口支持 HTTPS&#xff08;TLS v1.0 / v1.1 / v1.2 /…

【剑指 offer】镜像二叉树

目 录 描述&#xff1a; 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像 思路&#xff1a; 仔细观察可以发现&#xff0c;所谓的二叉树镜像本质是自顶向下(or自底向上)进行左右子树交换的过程 public class Solution {public void Mirror(TreeNode root) {if(root nu…

音视频开发继续学习

RGA模块 RGA模块定义 RGA模块是RV1126用于2D图像的裁剪、缩放、旋转、镜像、图片叠加等格式转换的模块。比方说&#xff1a;要把一个原分辨率1920 * 1080的视频压缩成1280 * 720的视频&#xff0c;此时就要用到RGA模块了。 RGA模块结构体定义 RGA区域属性结构体 imgType&am…

LeetCode-3148. 矩阵中的最大得分

本人算法萌新,为秋招找工作开始磨炼算法,算法题均用python实现,如果我有哪些地方做的有问题的,还请大家不吝赐教. 1.题干 给你一个由 正整数 组成、大小为 m x n 的矩阵 grid。你可以从矩阵中的任一单元格移动到另一个位于正下方或正右侧的任意单元格&#xff08;不必相邻&…

提高办公效率,四款语音转文字工具推荐!

无论是在会议记录、采访速记还是日常笔记中&#xff0c;语音转文字技术都展现出了其独特的价值。接下来是就为大家推荐几款市面上广受好评的语音转文字工具&#xff01; 365在线转文字 链接&#xff1a;https://www.pdf365.cn/ 365在线转文字是一款非常实用的在线语音转文字…

【Unity/网络】Unity和内网穿透的网络测试 —— 以聊天室为例

这两天在做那个CodeMonky的胡闹厨房的案例&#xff0c;一直困扰我的是关于Lobby和Relay的相关网络服务&#xff0c;需要挂加速器并且延迟不低&#xff0c;所以我一直在寻找一些其他替代方案&#xff0c;想起来之前做一个UEC的网络枪战时做过一个内网穿透的方法&#xff0c;所以…