【OpenCV-直方图与傅里叶变换】图像的基本变换、傅里叶变换、直方图

embedded/2024/12/23 8:41:46/
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows()

1 直方图

在这里插入图片描述

1.1 cv2.calcHist(images,channels,mask,histSize,ranges)

  • images: 原图像图像格式为 uint8 或 float32。当传入函数时应 用中括号 [] 括来例如[img]
  • channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的参数可以是 [0][1][2] 它们分别对应着 BGR。
  • mask: 掩模图像。统整幅图像的直方图就把它为 None。但是如 果你想统图像某一分的直方图的你就制作一个掩模图像并 使用它。
  • histSize:BIN 的数目。也应用中括号括来
  • ranges: 像素值范围常为 [0256]
img = cv2.imread('cat.jpg',0) #0表示灰度图# 计算图像的直方图
# [img]:输入图像,是一个图像列表。这里我们使用的是单通道的灰度图像。
# [0]:表示计算第0个通道的直方图,即灰度图像的唯一通道。
# None:没有使用掩码,即对整个图像进行计算。
# [256]:表示直方图的分组数(bins),将灰度级分为256个区间,对应0到255的像素值。
# [0, 256]:像素值范围为0到256,表示灰度值的范围。
hist = cv2.calcHist([img], [0], None, [256], [0, 256])hist.shape
# 使用 Matplotlib 生成图像的直方图
# img.ravel():将图像的多维数组展平为一维数组,适用于计算直方图的像素值。
# 256:直方图的分组数(bins),将像素值划分为 256 个区间,对应 0 到 255 的灰度值。
plt.hist(img.ravel(), 256)plt.show()

在这里插入图片描述

img = cv2.imread('cat.jpg') 
color = ('b','g','r')
for i,col in enumerate(color): # 计算图像的颜色通道直方图并绘制# [img]:输入图像,是一个包含多个颜色通道的图像(如 BGR 图像)。# [i]:颜色通道的索引,i 表示当前处理的通道(0=蓝色,1=绿色,2=红色)。# None:不使用掩码,对整个图像进行处理。# [256]:将像素值分为 256 个区间(bins),对应灰度值 0 到 255。# [0, 256]:像素值范围为 0 到 256。histr = cv2.calcHist([img], [i], None, [256], [0, 256])# 使用 Matplotlib 绘制颜色通道的直方图# histr:当前通道的直方图数据。# color=col:指定绘制的颜色,'col' 是当前通道的颜色('b' = 蓝色,'g' = 绿色,'r' = 红色)。plt.plot(histr, color=col)# 设置 X 轴的范围,确保显示 0 到 255 的像素值范围。plt.xlim([0, 256])

在这里插入图片描述

1.2 mask操作

# 创建mast
mask = np.zeros(img.shape[:2], np.uint8)
print (mask.shape)
mask[100:300, 100:400] = 255
cv_show(mask,'mask')img = cv2.imread('cat.jpg', 0)
cv_show(img,'img')
# masked_img = cv2.bitwise_and(img, img, mask=mask)#与操作# 使用按位与操作结合掩码进行图像处理
# img:输入图像,这是需要应用掩码的原始图像。
# cv2.bitwise_and():OpenCV 中的按位与操作,对图像的每个像素进行按位与运算。
# mask=mask:指定掩码,掩码是一个与图像大小相同的二值图像,只有掩码中为白色(255)的部分会保留,其他部分会被忽略(黑色部分对应的像素值被屏蔽)。
# 最终结果是图像中的某些部分根据掩码进行保留,其余部分被屏蔽。
masked_img = cv2.bitwise_and(img, img, mask=mask)cv_show(masked_img,'masked_img')
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])# 计算带掩码的图像直方图
# [img]:输入图像,计算直方图的目标图像。
# [0]:计算第 0 个通道的直方图(灰度图或图像的第一个颜色通道)。
# mask:用于限定计算区域的掩码,只对掩码中为白色(255)的区域进行直方图计算。
# [256]:直方图的分组数(bins),将像素值分为 256 个区间(灰度值 0 到 255)。
# [0, 256]:像素值的范围,表示从 0 到 255 的灰度值。
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
# 使用 Matplotlib 创建子图并可视化图像和直方图
# plt.subplot(221):创建 2x2 网格的第一个子图,用于显示原始图像。
plt.subplot(221), plt.imshow(img, 'gray')  # 显示原始图像,使用灰度颜色映射# plt.subplot(222):创建 2x2 网格的第二个子图,用于显示掩码。
plt.subplot(222), plt.imshow(mask, 'gray')  # 显示掩码图像,使用灰度颜色映射# plt.subplot(223):创建 2x2 网格的第三个子图,用于显示应用了掩码后的图像。
plt.subplot(223), plt.imshow(masked_img, 'gray')  # 显示带掩码的图像,使用灰度颜色映射# plt.subplot(224):创建 2x2 网格的第四个子图,用于显示完整图像和掩码区域的直方图。
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)  # 绘制完整图像和掩码区域的直方图# plt.xlim([0, 256]):设置 X 轴范围,确保显示从 0 到 255 的像素值。
plt.xlim([0, 256])# plt.show():显示所有子图。
plt.show()

在这里插入图片描述

1.3 直方图均衡化

在这里插入图片描述
在这里插入图片描述

img = cv2.imread('clahe.jpg',0) #0表示灰度图 #clahe# img 是一个图像数组。ravel() 将图像数组展平为一维数组。
# 256 是直方图的 bin 数量,通常用来表示图像的灰度级别范围(0-255)。
plt.hist(img.ravel(), 256)plt.show()

在这里插入图片描述

# img 是一个灰度图像数组。cv2.equalizeHist() 对图像进行直方图均衡化。
# 直方图均衡化用于提高图像对比度,使得图像的像素值分布更加均匀。
equ = cv2.equalizeHist(img)# 展平均衡化后的图像数组为一维数组,以便绘制直方图。
# 256 是直方图的 bin 数量,表示图像灰度级别的范围(0-255)。
plt.hist(equ.ravel(), 256)plt.show()

在这里插入图片描述

res = np.hstack((img,equ))
cv_show(res,'res')

1.4 自适应直方图均衡化

# 创建 CLAHE 对象,用于进行对比度限制自适应直方图均衡化。
# clipLimit:指定对比度限制阈值,通常用于防止噪声放大的过度增强。
# tileGridSize:指定局部均衡化的区域大小,通常为 (8, 8) 或其他合适的大小。
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) 
# 对图像进行 CLAHE 处理,生成对比度增强后的图像。
res_clahe = clahe.apply(img)# 将原始图像 (img)、均衡化图像 (equ) 和 CLAHE 处理后的图像 (res_clahe) 横向拼接在一起。
# np.hstack() 函数用于将多个数组沿水平方向(列方向)拼接。
res = np.hstack((img, equ, res_clahe))# res 现在包含了三幅图像并排显示,便于比较原始图像、直方图均衡化结果和 CLAHE 处理结果。
cv_show(res,'res')

2 傅里叶变换

我们生活在时间的世界中,早上7:00起来吃早饭,8:00去挤地铁,9:00开始上班。。。以时间为参照就是时域分析。

但是在频域中一切都是静止的!

傅里叶变换

傅里叶变换的作用

  • 高频:变化剧烈的灰度分量,例如边界

  • 低频:变化缓慢的灰度分量,例如一片大海

滤波

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

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

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

  • 得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现。

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

import numpy as np
import cv2
from matplotlib import pyplot as plt# 读取图像,第二个参数 0 表示以灰度模式加载图像
img = cv2.imread('lena.jpg', 0)# 将图像转换为 32 位浮点数格式,以便执行傅里叶变换
img_float32 = np.float32(img)# 对图像进行离散傅里叶变换 (DFT),flags=cv2.DFT_COMPLEX_OUTPUT 确保输出是复数,包含实部和虚部
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)# 使用 np.fft.fftshift 将零频率分量移到频谱图中心
dft_shift = np.fft.fftshift(dft)# 计算幅度谱,使用 cv2.magnitude 计算二维向量的模
# dft_shift[:,:,0] 是实部,dft_shift[:,:,1] 是虚部
# 取对数缩放值,以便能更好地显示幅度谱(否则值可能太小)
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:,:,0], dft_shift[:,:,1]))# 使用 Matplotlib 显示图像
# 第一个子图,显示原始输入图像,使用灰度颜色映射
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image')  # 设置标题为 "Input Image"
plt.xticks([]), plt.yticks([])  # 隐藏 x 和 y 轴刻度# 第二个子图,显示傅里叶变换后的幅度谱,使用灰度颜色映射
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum')  # 设置标题为 "Magnitude Spectrum"
plt.xticks([]), plt.yticks([])  # 隐藏 x 和 y 轴刻度# 显示图像
plt.show()

在这里插入图片描述

import numpy as np
import cv2
from matplotlib import pyplot as plt# 读取图像,第二个参数 0 表示以灰度模式加载图像
img = cv2.imread('lena.jpg', 0)# 将图像转换为 32 位浮点数格式,以便执行傅里叶变换
img_float32 = np.float32(img)# 对图像进行离散傅里叶变换 (DFT),flags=cv2.DFT_COMPLEX_OUTPUT 确保输出是复数,包含实部和虚部
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)# 使用 np.fft.fftshift 将零频率分量移到频谱图中心
dft_shift = np.fft.fftshift(dft)# 获取图像的行和列
rows, cols = img.shape
# 确定图像的中心位置
crow, ccol = int(rows/2), int(cols/2)# 创建一个掩码,尺寸与图像相同,2 表示包含实部和虚部的二维数组
# 掩码初始化为全 0
mask = np.zeros((rows, cols, 2), np.uint8)# 在中心区域设置为 1,形成低通滤波器(30x30 的矩形区域)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1# 将掩码应用到频谱上,实现低通滤波
fshift = dft_shift * mask# 进行逆 FFT 移位,将频率分量还原到原始位置
f_ishift = np.fft.ifftshift(fshift)# 对频谱应用逆离散傅里叶变换 (IDFT),返回到空间域
img_back = cv2.idft(f_ishift)# 计算返回图像的幅值,得到最终的结果
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])# 使用 Matplotlib 显示图像
# 第一个子图,显示原始输入图像,使用灰度颜色映射
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image')  # 设置标题为 "Input Image"
plt.xticks([]), plt.yticks([])  # 隐藏 x 和 y 轴刻度# 第二个子图,显示低通滤波后的图像
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Result')  # 设置标题为 "Result"
plt.xticks([]), plt.yticks([])  # 隐藏 x 和 y 轴刻度# 显示图像
plt.show()

在这里插入图片描述

import numpy as np
import cv2
from matplotlib import pyplot as plt# 读取图像,0 表示灰度模式
img = cv2.imread('lena.jpg', 0)# 将图像转换为 32 位浮点数格式,以便执行傅里叶变换
img_float32 = np.float32(img)# 对图像执行离散傅里叶变换,flags=cv2.DFT_COMPLEX_OUTPUT 输出复数图像
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)# 使用 np.fft.fftshift 将零频率分量移到频谱图的中心位置
dft_shift = np.fft.fftshift(dft)# 获取图像的行数和列数
rows, cols = img.shape
# 确定图像的中心位置,用于创建高通滤波器
crow, ccol = int(rows / 2), int(cols / 2)# 创建高通滤波掩码,初始化为全 1(保留所有频率)
mask = np.ones((rows, cols, 2), np.uint8)# 将中心区域设置为 0,形成一个高通滤波器
# 该区域对应于低频信息,设置为 0 将低频滤除
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0# 将掩码应用到傅里叶变换后的频谱上,实现高通滤波
fshift = dft_shift * mask# 进行逆傅里叶变换之前,使用 np.fft.ifftshift 将频率分量移回原始位置
f_ishift = np.fft.ifftshift(fshift)# 对频谱应用逆离散傅里叶变换,将频域数据转换回空间域
img_back = cv2.idft(f_ishift)# 计算返回图像的幅值,得到最终的结果
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])# 使用 Matplotlib 显示图像
# 第一个子图显示原始图像
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image')  # 标题为 "Input Image"
plt.xticks([]), plt.yticks([])  # 隐藏 x 和 y 轴刻度# 第二个子图显示高通滤波后的图像
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Result')  # 标题为 "Result"
plt.xticks([]), plt.yticks([])  # 隐藏 x 和 y 轴刻度# 显示图像
plt.show()

在这里插入图片描述

3 图像的基本变换

图像的大小与缩放
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])

  • src: 要缩放的图片
  • dsize: 缩放之后的图片大小, 元组和列表表示均可.
  • dst: 可选参数, 缩放之后的输出图片
  • fx, fy: x轴和y轴的缩放比, 即宽度和高度的缩放比.
  • interpolation: 插值算法, 主要有以下几种:
    • INTER_NEAREST, 邻近插值, 速度快, 效果差.
    • INTER_LINEAR, 双线性插值, 使用原图中的4个点进行插值. 默认.
    • INTER_CUBIC, 三次插值, 原图中的16个点.
    • INTER_AREA, 区域插值, 效果最好, 计算时间最长.

http://www.ppmy.cn/embedded/109672.html

相关文章

【Flutter】解决第一次运行项目很慢(gradle需要下载依赖)

配置gradle默认下载路径 默认下C盘谁顶得住 配置环境变量 名称: GRADLE_USER_HOME 值: D:\Develop\gradle 自己创建一个 下边是重点 配置gradle远端下载地址 后边版本号自己换 https://mirrors.cloud.tencent.com/gradle/ https://mirrors.cloud.tencent.com/gradle/gradl…

STM32看门狗

1 WDG简介 1 独立看门狗:时钟要求LSI(内部低速时钟) 要求时钟精度低:可能会出现,程序跑飞,但是喂狗代码也意外执行了 2 窗口看门狗:要求时钟精度高 3 看门狗直接产生复位(看门狗重装值是自减到零之前重装…

负载均衡式在线OJ

个人主页:Lei宝啊 愿所有美好如期而遇 目录 一、所用技术与开发环境 所用技术 开发环境 二、准备及库的安装 1. 升级gcc (gcc -v查看gcc版本, 超过7就不用看本条升级gcc) 2. 安装 jsoncpp 3. 安装 cpp-httplib 4. 安装boost库 5. 安装ctemplate 三、项目宏观结构…

P2P应用

当谈论P2P(点对点)应用程序时,我们实际上是在讨论一种网络架构和通信模式,它允许设备(或节点)直接连接并共享资源,而无需传统的客户端-服务器模型。P2P应用程序在许多领域都有广泛的应用&#x…

教师节重磅福利!《动手学强化学习》作者亲自带你学强化学习

作为大模型的核心技术之一,强化学习越来越受到人们的重视。强化学习(Reinforcement Learning, RL)是机器学习的一个领域,主要研究智能主体(agent)在环境中应该怎样采取行动以最大化所获得的累积奖励。目前强…

mysql——关于表的增删改查(CRUD)

目录 比较运算符和逻辑运算符图 一、增加(Create) 1、全列插入 2、指定列插入 二、查询(Retrieve) 1、全列查询 2、指定列查询 3、别名(as) 4、表达式查询 5、去重(distinct) 6、…

时尚购物体验:Spring Boot技术在网页时装购物中的应用

第2章相关技术 2.1 B/S架构 B/S结构的特点也非常多,例如在很多浏览器中都可以做出信号请求。并且可以适当的减轻用户的工作量,通过对客户端安装或者是配置少量的运行软件就能够逐步减少用户的工作量,这些功能的操作主要是由服务器来进行控制的…

IP查询技术:构建网络安全的坚实防线

在数字化时代,企业网络面临着复杂多变的威胁与挑战。因此,构建一个稳固的网络安全体系至关重要。而IP查询技术,作为网络安全防御体系中的一把利剑,正日益成为企业防范网络风险的重要工具。 什么是IP查询技术? IP查询…