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

news2024/9/20 20:45:48
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.coloradmin.cn/o/2119258.html

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

相关文章

浪潮信息:构建高效、安全数据存储底座的领航者

浪潮信息在最新IDC发布的《中国企业级外部存储市场跟踪报告,2024Q1》中表现抢眼,以11.4%的市场销售额占比稳居中国存储市场第二,同比增长率高达13.6%,领跑头部厂商。这标志着浪潮信息在推动中国存储市场持续增长中扮演了关键角色&…

智能语音技术在人机交互中的应用与发展

摘要:本文主要探讨智能自动语音识别技术与语音合成技术在构建智能口语系统方面的作用。这两项技术实现了人机语音通信,建立起能听能说的智能口语系统。同时,引入开源 AI 智能名片小程序,分析其在智能语音技术应用场景下的意义与发…

电商平台的仅退款,如何“卷”出一个千亿IPO?

“快递柜第一股”,丰巢登陆港交所 当英国走进工业革命时代,狄更斯曾经这样形容那个充满着激情、创造和无限可能的世界,“这是最好的时代,也是最坏的时代。” 如今,随着运费险、仅退款、直播带货的出现,中…

【最新华为OD机试E卷-支持在线评测】字母组合(200分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

【Power Compiler手册】9.时钟门控(6)

使用安全寄存器插入时钟门控 你可以使用同一个时钟门控来门控三模冗余(TMR)寄存器,对所有安全寄存器进行操作,而不需要触碰或修改投票逻辑。 Design Compiler NXT 工具会自动检测是否使用了安全寄存器,并相应地插入时钟门控。该工具始终确保同一安全组内的安全寄存器共享…

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创 作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能教育公司 ,宣布将长期致力于AI原生教育。 近日&#xff…

Transformer(Attention is all you need)网络结构

Transformer(Attention is all you need) Transformer结构 Transformer是一个从Encode到Decode的一个框架。Transformer的编码器和解码器是基于自注意力的模块叠加而成的,源(输入)序列和目标(输出)序列的嵌入&#x…

牛客周赛 Round 59 F范德蒙卷积

思路:对于计数问题,考虑两个数对于答案的贡献,考虑 a i a_i ai​ 和 a j a_j aj​ 作为子序列中的两个对称位置,其在多少个字符串中出现过,显然,若 a i a_i ai​ 距离子序列字符串s的首位距离为 x, 那么 …

儿童孤独症康复学校:打破孤岛,关爱与成长

在世界的某个角落,有一群孩子,他们如同夜空中最亮的星,却往往因孤独症的屏障,而难以与周围的世界建立连接。这些孩子,如同被无形的岛屿环绕,渴望着被理解、被接纳。而正是在这样的背景下,星贝育…

CSS媒体查询

媒体查询介绍 例如,同一个网页,在电脑上显示和在手机上显示有可能不一样的,因为电脑的屏幕更大,显示的东西可能更多。 为了适应不同设备的屏幕大小,就要写多种样式,例如在电脑上,ipad上&#x…

攻防世界 ics-05

ics-05 隐藏的变量传参,php弱类型比较 只有设备维护中心可以点击进去 查看源码,发现有个隐藏的超链接变量传参 看到变量传参,有可能存在文件包含漏洞读取源码,这个站是php的站,所以可以使用php伪协议读取源码 index.p…

编译安装redis运行注册服务脚本sh install_server.sh时报错。

在编译安装redis的时候,运行注册服务脚本sh install_server.sh时,报错。 Welcome to the redis service installer This script will help you easily set up a running redis server This systems seems to use systemd. Please take a look at the pro…

Django-Python网站框架(MVT三层架构实现)

1 新建项目 2.选择Django 3.选择解释器 4.等待安装 5. 安装完成后,点击终端 6.输入 python manage.py startapp djangoWeb 7.等待生成djangoWeb<

辉煌ERP的销售收入为何有一部分归入其他收入里面

管家婆辉煌ERP15.0&#xff0c;客户查询经营情况利润表时发现&#xff0c;在其他业务收入里面有销售单收入&#xff0c;为什么这些销售单没有归入销售收入里面&#xff1f; 经查&#xff0c;发现这些销售单销售的都是原材料或者劳务服务商品&#xff0c;而商品属性为原材料和服…

Spring Boot3项目的常见通用整体架构

Spring Boot 3 项目的整体架构。 1. IDEA创建项目 <properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…

500W逆变器(一)

EG8015_24V_500W 这款逆变器是基于 EG8015 SPWM 专用芯片而设计的方案。其额定的输出功率为 500 瓦, 最大输出功率为 600 瓦&#xff0c;输出电压为 220V10%&#xff0c;输出频率为 50Hz0.1Hz&#xff0c;额定输出电流为 2.3 安培。 穿越机降落的时候不要垂直降落&#xff0c;要…

✨机器学习笔记(三)—— 多元线性回归、特征缩放、Scikit-Learn(未完待续)

Course1-Week2: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Supervised%20Machine%20Learning%20Regression%20and%20Classification/week2机器学习笔记&#xff08;三&#xff09; 1️⃣多元线性回归及矢量化2️⃣特征缩放&#xff08;Featur…

Java进阶13讲__第12讲_2/2

线程安全问题 线程同步方案 线程池 线程通信 理论补充 1. 线程安全问题 1.1 举例说明 1.2 代码实现 package com.itheima.a_线程安全;/* 线程安全:多个线程同时修改同一个资源取钱案例小明和小红是一对夫妻&#xff0c;他们有一个共同的账户&#xff0c;余额是10万元如…

西门子PLC与HMI之间的时间同步工控小周

HMI 时间同步功能工控人加入PLC工业自动化精英社群 HMI 设备具有时间同步功能&#xff0c;利用 HMI 设备的该功能&#xff0c;可实现 PLC 和 HMI 之间的时间同步&#xff0c;进而实现多个 PLC 之间的时间同步。 HMI 设备时间同步的属性&#xff1a; 1.HMI 设备既可作为主站对…

WinCC 中对 VBS 进行单步执行调试

以前应该写过文章给各位展示如何在WinCC 中通过自身控件对脚本&#xff08;C、VBS&#xff09;进行脚本诊断和排错。但是也有用户反馈说在编写了一些相对复杂的脚本后&#xff0c;WinCC自身控件无法做到单步调试&#xff0c;也会影响脚本的诊断调试效率。如果能够对WinCC 中的脚…