Python实现多种图像去噪方法

Python实现多种图像去噪方法:中值滤波,均值滤波,高通滤波,低通滤波,高斯滤波,同态滤波

图像和视频逐渐成为人们生活中信息获取的重要来源。人们准确地获取信源发出的图像和视频信息需要保证在传输过程中的无失真性,而在传输过程中很容易受到外部噪声干扰,因此需要在接收端采用去噪算法减轻图像的噪声。

本文首先介绍了多种图像去噪的方法:低通滤波,高通滤波,均值滤波,中值滤波,高斯滤波和同态滤波。

然后针对图像传输中常见的椒盐噪声,分别利用上述滤波方法进行了图像去噪,通过实验证明,中值滤波能有效滤除椒盐噪声。

图像去噪

图像和视频信息在传输过程中很容易受到成像设备和外部环境的噪声干扰,导致人们接收到的信息和信源发出的信息差异很大,如果不能很好地消除这些外部噪声,那么人们将会接收到错误的信息。

外部噪声类型多种多样,可以按照噪声的时间特征、频率特征等进行分类。常见的一种噪声是椒盐噪声,也称为脉冲噪声。它的出现通常是由于图像信号突然受到强烈的干扰而产生。它是一种随机出现的白点或黑点,它会导致图像中暗的区域突然出现一个白点,亮的区域突然出现一个黑点。

低通滤波

低通滤波器可以允许图像信号频域中的低频分量通过而组织高频分量通过,因此低通滤波可以过滤高频噪声。理想的低通滤波器:

在这里插入图片描述

高通滤波

与低通滤波相反,高通滤波可以允许图像信号频域中的高频分量通过而抑制低频分量,因此高通滤波可以过滤掉低频噪声。理想的高通滤波器:

在这里插入图片描述

均值滤波

均值滤波是指将图像中的每个像素点的灰度值替换为该像素点附近灰度值的平均值。均值滤波器:

在这里插入图片描述

中值滤波

中值滤波是指将图像中的每个像素点的灰度值替换为该像素点附近灰度值的中值。中值滤波器:

在这里插入图片描述

高斯滤波

高斯滤波是一种线性平滑滤波,图像中每一个像素点的值都由其本身和邻域内的其他像素值经过加权平均后得到,它适用于消除高斯噪声。高斯滤波器:

在这里插入图片描述

同态滤波

同态滤波是指把频率滤波和空域灰度变换结合起来的一种图像处理方法,它可以用于删除由于不均匀照明引起的图像中的大阴影区域。同态滤波器:

在这里插入图片描述

Python代码实现低通、高通滤波等

# @description:
# @author:Jianping Zhou
# @email:jianpingzhou0927@gmail.com
# @Time:2022/11/13 16:37
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
from skimage import io
from salt_pepper_noise import pepper_and_salt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号


def salt_pepper(image, salt, pepper):
    """
    添加椒盐噪声的图像
    :param image: 输入图像
    :param salt: 盐比例
    :param pepper: 椒比例
    :return: 添加了椒盐噪声的图像
    """
    height = image.shape[0]
    width = image.shape[1]
    pertotal = salt + pepper  # 总噪声占比
    noise_image = image.copy()
    noise_num = int(pertotal * height * width)
    for i in range(noise_num):
        rows = np.random.randint(0, height - 1)
        cols = np.random.randint(0, width - 1)
        if (np.random.randint(0, 100) < salt * 100):
            noise_image[rows][cols] = 255
        else:
            noise_image[rows][cols] = 0
    return noise_image


def low_pass_filtering(image, radius):
    """
    低通滤波函数
    :param image: 输入图像
    :param radius: 半径
    :return: 滤波结果
    """
    # 对图像进行傅里叶变换,fft是一个三维数组,fft[:, :, 0]为实数部分,fft[:, :, 1]为虚数部分
    fft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)
    # 对fft进行中心化,生成的dshift仍然是一个三维数组
    dshift = np.fft.fftshift(fft)

    # 得到中心像素
    rows, cols = image.shape[:2]
    mid_row, mid_col = int(rows / 2), int(cols / 2)

    # 构建掩模,256位,两个通道
    mask = np.zeros((rows, cols, 2), np.float32)
    mask[mid_row - radius:mid_row + radius, mid_col - radius:mid_col + radius] = 1

    # 给傅里叶变换结果乘掩模
    fft_filtering = dshift * mask
    # 傅里叶逆变换
    ishift = np.fft.ifftshift(fft_filtering)
    image_filtering = cv2.idft(ishift)
    image_filtering = cv2.magnitude(image_filtering[:, :, 0], image_filtering[:, :, 1])
    # 对逆变换结果进行归一化(一般对图像处理的最后一步都要进行归一化,特殊情况除外)
    cv2.normalize(image_filtering, image_filtering, 0, 1, cv2.NORM_MINMAX)
    return image_filtering


def high_pass_filtering(image, radius, n):
    """
    高通滤波函数
    :param image: 输入图像
    :param radius: 半径
    :param n: ButterWorth滤波器阶数
    :return: 滤波结果
    """
    # 对图像进行傅里叶变换,fft是一个三维数组,fft[:, :, 0]为实数部分,fft[:, :, 1]为虚数部分
    fft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)
    # 对fft进行中心化,生成的dshift仍然是一个三维数组
    dshift = np.fft.fftshift(fft)

    # 得到中心像素
    rows, cols = image.shape[:2]
    mid_row, mid_col = int(rows / 2), int(cols / 2)

    # 构建ButterWorth高通滤波掩模

    mask = np.zeros((rows, cols, 2), np.float32)
    for i in range(0, rows):
        for j in range(0, cols):
            # 计算(i, j)到中心点的距离
            d = math.sqrt(pow(i - mid_row, 2) + pow(j - mid_col, 2))
            try:
                mask[i, j, 0] = mask[i, j, 1] = 1 / (1 + pow(radius / d, 2 * n))
            except ZeroDivisionError:
                mask[i, j, 0] = mask[i, j, 1] = 0
    # 给傅里叶变换结果乘掩模
    fft_filtering = dshift * mask
    # 傅里叶逆变换
    ishift = np.fft.ifftshift(fft_filtering)
    image_filtering = cv2.idft(ishift)
    image_filtering = cv2.magnitude(image_filtering[:, :, 0], image_filtering[:, :, 1])
    # 对逆变换结果进行归一化(一般对图像处理的最后一步都要进行归一化,特殊情况除外)
    cv2.normalize(image_filtering, image_filtering, 0, 1, cv2.NORM_MINMAX)
    return image_filtering


def bandpass_filter(image, radius, w, n=1):
    """
    带通滤波函数
    :param image: 输入图像
    :param radius: 带中心到频率平面原点的距离
    :param w: 带宽
    :param n: 阶数
    :return: 滤波结果
    """
    # 对图像进行傅里叶变换,fft是一个三维数组,fft[:, :, 0]为实数部分,fft[:, :, 1]为虚数部分
    fft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)
    # 对fft进行中心化,生成的dshift仍然是一个三维数组
    dshift = np.fft.fftshift(fft)

    # 得到中心像素
    rows, cols = image.shape[:2]
    mid_row, mid_col = int(rows / 2), int(cols / 2)

    # 构建掩模,256位,两个通道
    mask = np.zeros((rows, cols, 2), np.float32)
    for i in range(0, rows):
        for j in range(0, cols):
            # 计算(i, j)到中心点的距离
            d = math.sqrt(pow(i - mid_row, 2) + pow(j - mid_col, 2))
            if radius - w / 2 < d < radius + w / 2:
                mask[i, j, 0] = mask[i, j, 1] = 1
            else:
                mask[i, j, 0] = mask[i, j, 1] = 0

    # 给傅里叶变换结果乘掩模
    fft_filtering = dshift * np.float32(mask)
    # 傅里叶逆变换
    ishift = np.fft.ifftshift(fft_filtering)
    image_filtering = cv2.idft(ishift)
    image_filtering = cv2.magnitude(image_filtering[:, :, 0], image_filtering[:, :, 1])
    # 对逆变换结果进行归一化(一般对图像处理的最后一步都要进行归一化,特殊情况除外)
    cv2.normalize(image_filtering, image_filtering, 0, 1, cv2.NORM_MINMAX)
    return image_filtering


def bandstop_filter(image, radius, w, n=1):
    """
    带通滤波函数
    :param image: 输入图像
    :param radius: 带中心到频率平面原点的距离
    :param w: 带宽
    :param n: 阶数
    :return: 滤波结果
    """
    # 对图像进行傅里叶变换,fft是一个三维数组,fft[:, :, 0]为实数部分,fft[:, :, 1]为虚数部分
    fft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)
    # 对fft进行中心化,生成的dshift仍然是一个三维数组
    dshift = np.fft.fftshift(fft)

    # 得到中心像素
    rows, cols = image.shape[:2]
    mid_row, mid_col = int(rows / 2), int(cols / 2)

    # 构建掩模,256位,两个通道
    mask = np.zeros((rows, cols, 2), np.float32)
    for i in range(0, rows):
        for j in range(0, cols):
            # 计算(i, j)到中心点的距离
            d = math.sqrt(pow(i - mid_row, 2) + pow(j - mid_col, 2))
            if radius - w / 2 < d < radius + w / 2:
                mask[i, j, 0] = mask[i, j, 1] = 0
            else:
                mask[i, j, 0] = mask[i, j, 1] = 1

    # 给傅里叶变换结果乘掩模
    fft_filtering = dshift * np.float32(mask)
    # 傅里叶逆变换
    ishift = np.fft.ifftshift(fft_filtering)
    image_filtering = cv2.idft(ishift)
    image_filtering = cv2.magnitude(image_filtering[:, :, 0], image_filtering[:, :, 1])
    # 对逆变换结果进行归一化(一般对图像处理的最后一步都要进行归一化,特殊情况除外)
    cv2.normalize(image_filtering, image_filtering, 0, 1, cv2.NORM_MINMAX)
    return image_filtering


if __name__ == "__main__":
    image = cv2.imread("./results/lena_salt_pepper.png", 0)
    # image = salt_pepper(image, 0.04, 0.04)
    image_low_pass_filtering5 = low_pass_filtering(image, 50)
    image_high_pass_filtering5 = high_pass_filtering(image, 50, 1)
    cv2.imshow('lena_salt_pepper', image)
    cv2.waitKey(0)

    cv2.imshow('lena_low_pass_filtering', image_low_pass_filtering5)
    # plt.imshow(image_low_pass_filtering5, 'gray')
    # plt.savefig("./results/lena_low_pass_filtering.jpg", dpi=200, bbox_inches='tight', pad_inches=0)
    # image_low_pass_filtering5 = image_low_pass_filtering5.astype(np.uint8)
    io.imsave('./results/lena_low_pass_filtering.png', image_low_pass_filtering5)

    cv2.imshow('lena_high_pass_filtering', image_high_pass_filtering5)
    # plt.imshow(image_high_pass_filtering5, 'gray')
    # plt.savefig("./results/lena_high_pass_filtering.jpg", dpi=200, bbox_inches='tight', pad_inches=0)
    # image_high_pass_filtering5 = image_high_pass_filtering5.astype(np.uint8)
    io.imsave('./results/lena_high_pass_filtering.png', image_high_pass_filtering5)
    # cv2.waitKey(0)
    '''
    # image = pepper_and_salt(image, 0.04)
    image_low_pass_filtering5 = low_pass_filtering(image, 50)
    image_low_pass_filtering1 = low_pass_filtering(image, 10)
    image_high_pass_filtering5 = high_pass_filtering(image, 50, 1)
    image_high_pass_filtering1 = high_pass_filtering(image, 10, 1)
    image_bandpass_filtering5 = bandpass_filter(image, 30, 56, 1)
    image_bandstop_filtering5 = bandstop_filter(image, 30, 56, 1)
    plt.subplot(241), plt.imshow(image, 'gray'), plt.title("原图"), plt.xticks([]), plt.yticks([])
    # plt.subplot(334), plt.imshow(image_noise, 'gray'), plt.title("添加了椒盐噪声的图像"), plt.xticks([]), plt.yticks([])
    plt.subplot(242), plt.imshow(image_low_pass_filtering5, 'gray'), plt.title("半径为50像素的低通滤波"), plt.xticks(
        []), plt.yticks([])
    plt.subplot(246), plt.imshow(image_low_pass_filtering1, 'gray'), plt.title("半径为10像素的低通滤波"), plt.xticks(
        []), plt.yticks([])
    plt.subplot(243), plt.imshow(image_high_pass_filtering5, 'gray'), plt.title("半径为50像素的高通滤波"), plt.xticks(
        []), plt.yticks([])
    plt.subplot(247), plt.imshow(image_high_pass_filtering1, 'gray'), plt.title("半径为10像素的高通滤波"), plt.xticks(
        []), plt.yticks([])
    plt.subplot(244), plt.imshow(image_bandpass_filtering5, 'gray'), plt.title("带通滤波"), plt.xticks([]), plt.yticks([])
    plt.subplot(248), plt.imshow(image_bandstop_filtering5, 'gray'), plt.title("带阻滤波"), plt.xticks([]), plt.yticks([])
    plt.show()
   	'''

更多详细代码发布在https://github.com/JeremyChou28/digital_image_processing/tree/main/project2

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

性能优化 vue2/vue3 通过CDN 减少项目启动时间

其实更多可以通过压缩图片等文件大小 也会让项目运行快一些 以及尽量使用异步或者懒加载 使用CDN可以避免在项目中使用npm导入Vue的依赖项&#xff0c;从而减少项目启动时的加载时间 使用方法如下 <!-- Vue 2 --> <script src"https://cdn.jsdelivr.net/npm/vue…

[Linux] Tomcat

一、Tomcat相关知识 1.1 Tomcat的简介 Tomcat 是 Java 语言开发的&#xff0c;Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器&#xff0c;是 Apache 软件基金会的 Jakarta 项目中的一个核心项目&#xff0c;由 Apache、Sun 和其他一些公司及个人共同开发而成。 …

防职业掉坑必看,电商设计主要做什么?

今年双十一刚结束&#xff0c;各电商平台不公布总销售额的新闻就上了热搜。外行人乍一看可能觉得消费意愿下降&#xff0c;消费水平降级&#xff0c;电商行业不景气&#xff0c;但实际上电商领域在国内突飞猛进了10几年后&#xff0c;仍然还有很大的上升空间。很多人说&#xf…

shiro入门demo(二)授权

在前面认证的基础上&#xff0c;认证通过后一般还有个授权的操作。授权根据业务需求有两种维度&#xff0c;基于角色的授权和基于资源的授权。 一、授权-基于角色授权&#xff1a; shiro中授权实现方式&#xff1a;有三种 1、编程式 Subject subject SecurityUtils.getSubje…

电路中的repeater是什么?

最近在看interlaken协议&#xff0c;有一个单词&#xff0c;repeater&#xff0c;不知道是什么含义&#xff0c;查了一下发现它的功能是提高数据的完整性&#xff0c;要么是修复时钟&#xff0c;要么是提高信号裕量等。总之是让信号变好的一个东西。 具体可以参见TI的说明。 【…

企业资产负债表API:获取企业资产负债表数据的重要工具

前言 在当今的数字化时代&#xff0c;信息的获取和整合对于企业的决策和规划至关重要。企业资产负债表API是一种强大的工具&#xff0c;可以帮助企业快速、准确地获取资产负债表数据&#xff0c;从而更好地分析财务状况、做出投资决策以及评估经营绩效。本文将介绍企业资产负债…

【Linux | C++ 】生产者消费者模型(Linux系统下C++ 代码模拟实现)

阅读导航 引言一、生产者消费者问题&#x1f341;将生产者消费者模型比喻为超市的顾客和供货商 二、C queue模拟阻塞队列的生产消费模型&#xff08;伪代码&#xff09;三、RAII风格的加锁方式1. 简介2. 示例 四、基于Linux操作系统使用C代码&#xff0c;采用RAII风格的加锁方式…

flutter的ListView和SingleChildScrollView有什么区别?他们的使用场景有什么不一样?

文章目录 简介ListViewSingleChildScrollView使用场景的不同 简介 ListView和SingleChildScrollView都是在Flutter中用于处理滚动内容的组件&#xff0c;但它们有一些关键的区别。 ListView 多个子元素&#xff1a; ListView是一个滚动的可滚动组件&#xff0c;通常用于包含多…

写字基本功 - 正确握笔姿势

写字基本功 - 正确握笔姿势 1. 写字基本功 郑文彬 (布衣) 先生 2. 正确握笔步骤 握笔姿势教学 http://www.bebosspen.com/index.php/correct 3. 正确握笔姿势 - 重点解说图 握笔姿势教学 http://www.bebosspen.com/index.php/correct 3.1. 食指 食指低于拇指 两段弯曲勿三…

【价值几十万的仿抖音直播电商系统源码共享】

当下&#xff0c;传统的图文电商模式已经走向没落&#xff0c;以抖音为首的直播电商模式备受用户追捧&#xff0c;它具有实时直播和强互动的特点&#xff0c;是传统电商所不具备的优势。而且&#xff0c;当前正是直播电商的红利期&#xff0c;很多主播和品牌商都通过直播电商业…

[Halcon模块] Halcon13.0查询算子模块归属

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

【C语言 | 指针】数组参数 和 指针参数

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

IDEA利用插件完成properties与yml的互相转换(mac与wins通用)

步骤一、插件安装 点击屏幕左上方的IDEA&#xff0c;然后点击Preferences(相当于wins里的settings) 进入后点击Plugins&#xff0c;在插件商城中搜索并安装 Convert YAML and Properties File 这个插件 二、使用 右键选择你需要转换的配置文件&#xff0c;选择Convert YAML …

解决高风险代码:Mass Assignment: Insecure Binder Configuration

Abstract 用于将 HTTP 请求参数绑定到模型类的框架绑定器未显式配置为允许或禁止特定属性 Explanation 为便于开发和提高生产率&#xff0c;现代框架允许自动实例化一个对象&#xff0c;并使用名称与要绑定的类的属性相匹配的 HTTP 请求参数填充该对象。对象的自动实例化和填充…

安装Anaconda和pytorch

首先看下自己电脑是否有英伟达的显卡&#xff0c;如果有的话可以安装GPU版本&#xff0c;没有的话可以安装CPU版本。 CPU版本 1.安装Anaconda 首先去官网下载Anaconda。 点击download&#xff0c;下载的就是最新版本的。 下载完成后&#xff0c;直接运行下步就行 注意到路径…

Chrome更新

Chrome无法通过360软件管家升级&#xff0c;最方便的升级方法应该是通过Chrome本身进行升级&#xff0c;但可能需要自备梯子。 点击Chrome右上角三个点 点击帮助 点击关于Google Chrome 在弹出的页面中查看是否是最新版本&#xff0c;如果不是最新版本会有一个升级的按钮&a…

开题PPT答辩复盘

目录 总体思路加粗和红体字使用研究现状之后主要研究内容讨论 总体思路 分为五个部分&#xff0c;规定在10分钟以内讲完。这次开题答辩&#xff0c;主要是要讲清楚研究背景和意义&#xff0c;国内外研究现状。因此前两部分需要花大概6分钟重点解释&#xff0c;主要研究内容用2…

【Linux】进程周边003之进程优先级

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.基本概念 2.PRI与NI 3.利…

使用护眼台灯能不能有效预防近视?分享高品质的护眼台灯

在近几年&#xff0c;儿童青少年近视率非常高。很多家长认为孩子近视的原因是没有养成正确的用眼习惯&#xff0c;例如经常趴桌子写作业、眯眼看书等&#xff0c;但实际上这些坏习惯是因为没有合适的光线而导致的。所以安排一盏合适的台灯给孩子学习是非常重要的。 目前而言最好…

图片压缩软件4K Image Compressor Pro mac特点介绍

4K Image Compressor Pro mac是一款专业的图片压缩软件&#xff0c;它可以在不损失图像质量的前提下&#xff0c;优化图片文件的大小&#xff0c;从而节省存储空间&#xff0c;方便在社交媒体上共享图片&#xff0c;并优化网站加载速度。 4K Image Compressor Pro mac软件特点 …