python数字图像处理基础(七)——直方图均衡化、傅里叶变换

目录

    • 直方图均衡化
      • 均衡化原理
      • 均衡化效果
      • 标准直方图均衡化
      • 自适应直方图均衡化
    • 傅里叶变换
      • 原理
      • 低通滤波
      • 高通滤波

直方图均衡化

均衡化原理

图像均衡化是一种基本的图像处理技术,通过更新图像直方图的像素强度分布来调整图像的全局对比度。这样做可以使低对比度的区域在输出图像中获得更高的对比度。

简单理解:改变图像对比度,让色彩更丰富,灰度值直方图:瘦高 -> 均衡

本质上,直方图均衡化的工作原理是:

  • 1.计算图像像素强度的直方图
  • 2.均匀展开并分布最频繁的像素值(即直方图中计数最大的像素值)
  • 3.给出累积分布函数(CDF)的线性趋势

在这里插入图片描述

注意到以上直方图有许多峰值,这表明有很多像素被归入到这些各自的bin中。使用直方图均衡化,我们的目标是将这些像素分散到没有太多像素的bin中。

均衡化效果

在这里插入图片描述

注意输入图像的对比度是如何显著提高的,但代价是也提高了输入图像中的噪声的对比度。

这就提出了一个问题:是否有可能在不增加噪声的同时提高图像对比度?
答案是“是的”,你只需要应用自适应直方图均衡化

通过自适应直方图均衡化,我们将输入图像划分为M × N网格。然后我们对网格中的每个单元进行均衡处理,从而获得更高质量的输出图像:

在这里插入图片描述

标准直方图均衡化

OpenCV 包括通过以下两个函数实现基本直方图均衡和自适应直方图均衡:

cv2.equalizeHist
cv2.createCLAHE

应用cv2.equalizeHist()函数非常简单,只需将图像转换为灰度,然后调用cv2.equalizeHist即可:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
equalized = cv2.equalizeHist(gray)

自适应直方图均衡化

实现自适应直方图均衡化要求:

1.将输入图像转换为灰度/从中提取单个通道
2.使用cv2.createCLAHE实例化CLAHE算法
3.在CLAHE对象上调用.apply()方法来应用直方图均衡化
这比听起来容易得多,只需要几行代码:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
equalized = clahe.apply(gray)

注意,我们为cv2.createCLAHE提供了两个参数:

  • clipLimit:这是对比度限制的阈值
  • tileGridSize:将输入图像划分为M × N块,然后对每个局部块应用直方图均衡化

傅里叶变换

原理

傅里叶变换常用来分析各种滤波器的特性。可以是用2D离散傅里叶变换分析图像的频域特性。

(个人理解,在图像问题当中,频域是指图像的灰度变化,也就是灰度图像的梯度值,这个和轮廓的原理差不多,灰度值变化剧烈的叫做高频分量,例如边界和噪声。灰度值变化缓慢的称谓低频分量)

实现2D离散傅里叶变换(DFT)的的算法叫做快速傅里叶变换(FFT)。

对图像进行X方向和Y方向的傅里叶变换,会得到图像的频域表示图。

直观理解,一个正弦信号,如果幅度变换很快,可以称之为高频信号,如果变换慢,可以称之为低频信号。在图像中,灰度值变化快的位置,可以称之为高频分量(只变化快而不是次数多),灰度值变化慢的称之为低频分量

图像使用使用二维离散傅里叶变换后得到一个复数矩阵,叫做图像的频谱图。

低通滤波器:只保留低频,会使得图像模糊

高通滤波器:只保留高频,会使得图像细节增强

  • opencv中主要就是从cv2.dftt()cv2.idft(),输入图像需要先转换成np.float32格式:

    img = cv2.imread(‘lena.jpg’, 0)

    img_ float32 = np.float32(img)

    dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)

  • 得到的结果中频率为0的部分会在左上角,通常要转换到中心位置(故转换后的图像从中心向四周频率增高),可以通过shift变换来实现:

    dft_shift = np.fft.fftshift(dft)

  • cv2.dft()返回的结果是复数矩阵,即双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)

    magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:, :, 0],dft_shift[:, :, 1]))

img = cv2.imread('33.jpg',0)  # 读图
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)  # 傅里叶变换
dft_shift = np.fft.fftshift(dft)  # 平移到中心,结果为双通道(实部,虚部)
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))  # 转化为频谱图

理解:通过傅里叶变换,将图像转化为频谱图,而低通滤波和高通滤波则是傅里叶变换的逆变换,即通过对频谱图进行一些操作(保留低频/保留高频),从而达到改变原始图像的效果。

低通滤波

作用:将图像变得平滑,同时也就看起来比较模糊。

做法:利用掩码,把中心部分频率低的保留下来

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./image/img1.jpg', 0)img_float32 = np.float32(img)dft = cv2.dft(img_float32, flags= cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)rows, cols = img.shape  # 横纵坐标
crow, ccol = int(rows/2), int(cols/2)  # 找到中心位置# 低通滤波制作蒙板
mask = np.zeros((rows, cols, 2), np.uint8)  # 初始化全部像素点数值置为0
mask[crow-30:crow+30, ccol-30:ccol+30] = 1  # 相当于只有中心位置60*60像素点是1,其余全为0# IDFT傅里叶逆变换 即把dft后得到的按频率分布的奇奇怪怪的图(称为频谱图)变为原来imread进来的图
fshift = dft_shift*mask  # 将掩膜和得到的结果结合,即只有中心60*60保留
f_ishift = np.fft.fftshift(fshift)  # 做逆变换,当然要把原来fft左上角移到中间的再移回左上角ifft
img_back = cv2.idft(f_ishift)  # 逆变换,频谱图还原为原图,但还不能看,因为结果是双通道(实部,虚部)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])  # 套公式处理,让图像可看plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])plt.show()

高通滤波

作用:增强边缘,非边缘部分被过滤

做法:使用一个60×60的矩形窗口进行蒙板操作,去除低频分量,使用函数np.fft.ifftshift将图像中心平移回左上角,然后使用函数 np.ifft2()进行FFT逆变换,将得到的复数结果取绝对值。(DFT的逆变换)

与低通滤波唯一的区别就在蒙版的制作

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./image/img1.jpg', 0)img_float32 = np.float32(img)dft = cv2.dft(img_float32, flags= cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)rows, cols = img.shape  # 横纵坐标
crow, ccol = int(rows/2), int(cols/2)  # 找到中心位置# 高通滤波制作蒙板
mask = np.ones((rows, cols, 2), np.uint8)  # 初始化全部像素点数值置为1
mask[crow-30:crow+30, ccol-30:ccol+30] = 0  # 相当于只有中心位置60*60像素点是0,其余全为1# IDFT傅里叶逆变换 即把dft后得到的按频率分布的奇奇怪怪的图变为原来imread进来的图
fshift = dft_shift*mask  # 将掩膜和得到的结果结合,即只有中心60*60保留
f_ishift = np.fft.fftshift(fshift)  # 做逆变换,当然要把原来fft左上角移到中间的再移回左上角ifft
img_back = cv2.idft(f_ishift)  # 逆变换,模糊频率图还原为原图,但还不能看,因为结果是双通道(实部,虚部)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])  # 套公式处理,让图像可看plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])plt.show()

思想:将图像通过傅里叶变换映射到频域中进行操作,往往简单高效,最后再逆变换转化回来就好


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

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

相关文章

高密数据中心卓越运维,更灵活助力企业 AI 就绪

AIGC的高速发展将企业对基础架构的需求推上了新的层次,根据中国通服数字基建产业研究院发布的《中国数据中心产业发展白皮书(2023)》报告,互联网行业客户对单机柜功率密度的要求较高,一般在6-8kW,金融行业处…

一个小程序跳转到另一个小程序中如何实现

小程序 保证两个小程序是一样的主体才可以跳转。怎么知道是不是同样的主体呢&#xff1f; 小程序的后台管理-设置-基本设置-基本信息。查看主体信息。 跳转 <button clicktoOtherMini()>跳转到另一个小程序</button> function toOtherMini(){wx.navigateToMini…

【USTC】verilog 习题练习 21-25

21 基于端口名称的实例化 题目描述 创建一 verilog 电路&#xff0c;实现对模块 mod_a 基于端口名称的实例化&#xff0c;如下图所示&#xff1a; 其中mod_a模块的代码为&#xff1a; module mod_a (output out1,output out2,input in1,input in2,input in3,in…

pytest -- 基本使用详解

1. pytest基本介绍 pytest 是一个功能强大且易于使用的 Python 测试框架&#xff0c;用于编写单元测试、集成测试和功能测试。 它提供了丰富的功能和灵活的用法&#xff0c;使得编写和运行测试变得简单而高效。 --------------->>>>> pytest框架优点&#xff1a…

FlinkAPI开发之状态管理

案例用到的测试数据请参考文章&#xff1a; Flink自定义Source模拟数据流 原文链接&#xff1a;https://blog.csdn.net/m0_52606060/article/details/135436048 Flink中的状态 概述 有状态的算子 状态的分类 托管状态&#xff08;Managed State&#xff09;和原始状态&…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过NEOAPI SDK使用相机日志跟踪功能1.引用合适的类文件2.通过NEOAPI SDK使用相机日志跟踪功能3.通…

在自定义数据集上训练 YOLOv8 进行目标检测

这是目标检测中令人惊叹的 AI 模型之一。在这种情况下&#xff0c;您无需克隆存储库、设置要求并配置模型&#xff0c;就像在 YOLOv5 及其之前的版本中所做的那样。 在 YOLOv8 中&#xff0c;不需要执行这些手动任务。您只需安装 Ultralytics 即可&#xff0c;我将向您展示如何…

【数据结构 | 直接选择排序】

直接选择排序 基本思路直接插入排序SelectSort 基本思路 直接插入排序&#xff08;StraightInsertionSort&#xff09;的基本操作是将一个记录插入到已经排好序的有序表中&#xff0c;从而得到一个新的、记录数增1的有序表。 我们可以同时从数组的头部和尾部同时进行排序工作…

Linux系统三剑客之awk命令详解(三)

Linux系统三剑客之grep和正则表达式的介绍(一)-CSDN博客 Linux系统三剑客之sed命令详解(二)-CSDN博客 接上文 目录 1.作用 2.语法 3.变量 4.选项 5.模式 ​编辑 6.动作 7.实例 1.作用 awk是一个强大的文本分析工具&#xff0c;其主要工作原理就是将文件内容逐行读取…

maven 配置http私服Since Maven 3.8.1 http repositories are blocked. 报错处理

刷maven报错 com.saas:pdf:pom:0.0.1 failed to transfer from http://0.0.0.0/ during a previous attempt. This failure was cached in the local repository and resolution is not reattempted until the update interval of maven-default-http-blocker has elapsed or …

XSS漏洞:xss.haozi.me靶场通关

xss系列往期文章&#xff1a; 初识XSS漏洞-CSDN博客 利用XSS漏洞打cookie-CSDN博客 XSS漏洞&#xff1a;xss-labs靶场通关-CSDN博客 XSS漏洞&#xff1a;prompt.mi靶场通关-CSDN博客 目录 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C…

GPT实战系列-简单聊聊LangChain搭建本地知识库准备

GPT实战系列-简单聊聊LangChain搭建本地知识库准备 LangChain 是一个开发由语言模型驱动的应用程序的框架&#xff0c;除了和应用程序通过 API 调用&#xff0c; 还会&#xff1a; 数据感知 : 将语言模型连接到其他数据源 具有代理性质 : 允许语言模型与其环境交互 LLM大模型…