【Opencv入门到项目实战】(八):图形直方图|傅里叶变换

news2024/12/23 23:24:16

所有订阅专栏的同学可以私信博主获取源码文件

文章目录

  • 1.图像直方图
    • 1.1 直方图计算
    • 1.2 分通道读取
    • 1.3 mask操作(掩码操作)
  • 2.傅里叶变换
    • 2.1 频率转换结果
    • 2.2 高通和低通滤波器

1.图像直方图

1.1 直方图计算

直方图是一种用于可视化数据分布的图表形式,它显示了数据在各个数值范围内的频率或数量。直方图可以帮助我们了解数据的分布情况、寻找异常值和识别数据模式。在计算机视觉中,直方图也经常用于图像处理和分析。通过统计图像中不同灰度级别的像素数量,可以获得图像的灰度分布,进而进行图像增强、对比度调整、颜色校正等操作。

首先每个图像单独拿出来其实就是一堆像素点,范围在0-255之间,而直方图就是统计这一张图片各个像素点值的个数,如下图所示,横坐标代表不同像素点取值,纵坐标代表出现的次数。

image-20230802212923653

Opencv中,可以使用cv2.calcHist()函数来计算图像的直方图。语法如下:

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

cv2.calcHist()函数的各个参数解释:

  • images: 需要计算直方图的图像,以方括号的形式传递,表示可以处理多个图像。例如[img]
  • channels: 指定计算直方图的通道索引,对于灰度图像,只有一个通道,因此传递0。如果是彩色图像,则传入的参数可以是 0,1,2,它们分别对应着 BGR。
  • mask: 用于指定掩码图像,如果不需要,则设置为None,即统计整幅图像的直方图
  • Size: 表示直方图的大小,即有多少个bins,例如设置为256,表示将图像像素值分成256个区间进行统计。
  • ranges 表示像素值的范围。常为 [0, 256]

接下来我们来看一下具体的案例:

我们照样是读取小狗洋气的照片,来看一下它的直方图分布

import cv2 #opencv读取的格式是BGR

# 定义图像显示函数
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
    
img = cv2.imread('yangqi.jpg',0) #0表示读取灰度图

# 直方图计算
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist.shape
(256, 1)

hist返回每个0-255共256个像素值出现的个数,我们打印出来看一下它的分布情况

plt.hist(img.ravel(),256); 
plt.show()

image-20230802214117541

1.2 分通道读取

接下来我们以彩色图为例,统计每一个通道的直方图。这里要注意的是,opencv的颜色顺序是b、g、r。

接下来我们首先读取彩色图,然后利用一个for循环来遍历每个通道得到对应的直方图并打印。

# 读取彩色图
img = cv2.imread('yangqi.jpg') 

# 直方图
color = ('b','g','r')
for i,col in enumerate(color): 
    histr = cv2.calcHist([img],[i],None,[256],[0,256]) 
    plt.plot(histr,color = col) 
    plt.xlim([0,256]) 

image-20230802214635075

1.3 mask操作(掩码操作)

直方图掩码操作是一种通过应用掩码图像来选择特定区域,并计算该区域的直方图的方法。它在图像处理和计算机视觉领域中非常常用,用于分析图像中感兴趣区域的像素分布情况。

在直方图掩码操作中,我们使用两个图像:原始图像和掩码图像。

  • 原始图像:这是我们要进行操作和分析的图像。
  • 掩码图像:这是一个二值图像,用于指定原始图像中我们感兴趣的区域。掩码图像通常是灰度图像,其中具有我们感兴趣的区域的像素值设为255,而其他区域的像素值为零。

我们先来创建一个掩码图像

# 创建mast
mask = np.zeros(img.shape[:2], np.uint8)
print (mask.shape)
mask[100:200, 50:150] = 255
cv_show(mask,'mask')

image-20230802223538049

接下来我们应用掩码:

使用OpenCV的cv2.bitwise_and()函数将原始图像和掩码图像进行操作。产生一个新的图像,其中只有掩码图像非零像素对应的原始图像像素会被保留下来,其余像素置为零,相当于起到了一个捕捉特定区域的作用

masked_img = cv2.bitwise_and(img, img, mask=mask)#掩码操作
cv_show(masked_img,'masked_img')

image-20230802223731760

计算直方图:使用OpenCV的cv2.calcHist()函数计算掩码后图像的直方图。可以指定通道索引,直方图大小和像素值范围等参数。

hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])

绘制直方图:

使用Matplotlib库绘制直方图,并通过plt.show()显示图像。

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()

image-20230802223850606

通过直方图掩码操作,我们可以获取特定区域的像素分布情况,从而对图像进行更精细的分析和处理。这种方法常用于目标检测、图像分割、背景建模等应用中,使得我们可以专注于感兴趣的区域并获得相关的统计信息。

2.傅里叶变换

傅里叶变换(Fourier Transform)是一种将信号在时域(时间域)频域(频率域)之间进行转换的数学工具,具体的数学理论不做详细探讨。它的基本思想是将一个信号分解成一组不同频率的正弦和余弦函数的叠加。

在图像处理中,傅里叶变换常被用于分析和处理图像的频域信息,通过将图像从空间域转换到频域,我们可以了解图像中各个频率成分的贡献,针对不同频率,我们有以下作用:

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

2.1 频率转换结果

对于二维图像而言,我们常用离散傅里叶变换(Discrete Fourier Transform, DFT)

离散傅里叶变换(DFT)是将图像从空间域转换到频域的一种方法,它通过计算图像中每个像素点的频谱来描述图像的频率特征。DFT输出的结果是一个复数数组,其中每个元素表示该频率分量的振幅和相位。因此,我们需要将这个输出结果转换成图像格式。

在opencv中我们调用cv2.dft()函数实现dft转换,输入图形要先转换成np.float32的格式,此外,cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('lena.jpg',0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT) # 使用dft
dft_shift = np.fft.fftshift(dft)#shift转换,将频率为0的部分转换到中心位置。

# 得到灰度图能表示的形式
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1])) 

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

image-20230802210721073

右图是经过频率转换之后的结果,可以看到中心位置比较亮,呈现一个中心向外发散的情况,越在中心频率越低,越在外边频率越高

2.2 高通和低通滤波器

低通滤波器和高通滤波器是信号处理中常见的两种滤波器类型,用于在频域上选择特定频率范围内的信号分量。

低通滤波器(Low-pass Filter)的作用是保留信号中较低频率的分量,并削弱或消除高频分量,相当于把边界抹除了,使得图像变得模糊。低通滤波器可以用来平滑信号、去除噪声或降低信号频率。 低通滤波器的频率响应通常是一个平坦的直线,直到截止频率,截止频率之后,频率响应开始逐渐下降。

我们下面来看一下如何实现一个经过低通滤波器之后再返回源图像

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('lena.jpg',0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT) #dft结果
dft_shift = np.fft.fftshift(dft) #使用shift将0转换到中心位置

rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置

# 低通滤波
mask = np.zeros((rows, cols, 2), np.uint8) 
mask[crow-30:crow+30, ccol-30:ccol+30] = 1 #只在中心位置为1,其余位置都为0

# IDFT:DFT的逆变换,将dft的结果变换的源图像
fshift = dft_shift*mask #通过掩码操作只保留中心位置
f_ishift = np.fft.ifftshift(fshift)# 做shift的逆变换
img_back = cv2.idft(f_ishift)# 做dft的逆变换
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()                

image-20230802210740045

左图是我们的原始图像,右图是经过低通道后得到的图像结果,可以看到图像变得模糊,并且边界点不是很明显,主要集中在中心人脸位置。

高通滤波器(High-pass Filter): 高通滤波器允许通过频率范围内的高频信号,而抑制低频信号,相当于将边界锐化,会使得图像细节增强。它的作用是保留信号中的高频分量,并减弱或消除低频信号。高通滤波器可以用来强调信号中的快速变化部分,滤除基线漂移或去除低频噪声。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('lena.jpg',0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT) #dft结果
dft_shift = np.fft.fftshift(dft) #使用shift将0转换到中心位置

rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置

# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0 #只在中心位置为0,其余位置都为1

# IDFT:DFT的逆变换,将dft的结果变换的源图像
fshift = dft_shift*mask #通过掩码操作只保留中心位置
f_ishift = np.fft.ifftshift(fshift)# 做shift的逆变换
img_back = cv2.idft(f_ishift)# 做dft的逆变换
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()                

image-20230802210751038

可以看到图像只保留了一些边界信息,主要是Lena的身体轮廓。

思考:最后我们来思考一下为什么要使用傅里叶变换呢,为什么我们要把图像转换到一个频率当中做处理呢?其实最主要的原因就是这样做更简单高效。经过傅里叶变换,这个频率当中分为低频和高频,层次分明,此时做各种变换都特别容易。如果在原始图像中进行变换,会非常复杂,不利于我们工程去实现迭代。因此,我们通常都会把图像先映射到频率当中,在频率当中做处理。

🔎本章的介绍到此介绍,如果文章对你有帮助,请多多点赞、收藏、评论、订阅支持!!《Opencv入门到项目实战》

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

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

相关文章

朋友圈截图生成,制作朋友圈网页

使用教程可以自己看工具的使用手册。 Windows电脑版: https://imageio.jscs.top/zip/wxchat-moment-windows Mac电脑版: https://imageio.jscs.top/zip/wxchat-moment-mac 这款神器的主要功能是朋友圈评论截图生成器,而且还具有以下功能中…

cesium学习记录05-支持的主要数据格式与服务

1. 矢量数据: 1.1. GeoJSON 定义: 一个基于JSON的地理数据格式,Cesium支持GeoJSON的直接加载。 例子: 加载一个简易故宫建筑的GeoJSON数据。 代码: /*** 添加故宫geojson数据*/AddGuGong() {var viewer this.v…

【Linux从入门到精通】文件操作(C语言vs系统调用)

文章目录 一、C语言的文件IO相关函数操作 1、1 fopen与fclose 1、2 fwrite 1、3 fprintf与fscanf 1、4 fgets与fputs 二、系统调用相关接口 2、1 open与close 2、2 write和read 三、简易模拟实现cat指令 四、总结 🙋‍♂️ 作者:Ggggggtm 🙋‍…

AP2915DC-DC降压恒流驱动IC LED电源驱动芯片 汽车摩托电动车灯

AP2915 是一款可以一路灯串切换两路灯串的降压 恒流驱动器,高效率、外围简单、内置功率管,适用于 5-80V 输入的高精度降压 LED 恒流驱动芯片。内置功 率管输出功率可达 12W,电流 1.2A。 AP2915 一路灯亮切换两路灯亮,其中一路灯亮可 以全亮&a…

C++,文本文件,读取文件

代码演示&#xff1a; #include<iostream> using namespace std; #include<string> #include<fstream>void test() {//1、包含头文件//2、创建流对象ifstream ifs;//3、打开文件并判断文件是否成功ifs.open("test.txt", ios::in);if (!ifs.is_ope…

问道管理:A股缩量整理 新股上演久违暴涨模式

周三&#xff0c;大盘低开后震动&#xff0c;三大指数小幅跌落&#xff0c;创业板指相对偏强。 早盘开盘后&#xff0c;沪指、深证成指弱势震动&#xff0c;创业板指探底上升翻红&#xff0c;盘面热门乏善可陈。午后三大指数震动走弱&#xff0c;创业板指再度翻绿。医药板块活…

Vue 实现重定向、404和路由钩子(六)

一、重定向 1.1 修改 Main.vue <template><div><el-container><el-aside width"200px"><el-menu :default-openeds"[1]"><el-submenu index"1"><template slot"title"><i class"…

伪原创神码ai怎么样【php源码】

这篇文章主要介绍了python汉化补丁包下载&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 火车头采集ai伪原创插件截图&#xff1a; ** Spyder汉化&#xff08;python汉化&…

在vue项目使用数据可视化 echarts ,柱状图、折线图、饼状图使用示例详解及属性详解

官网地址&#xff1a;Apache ECharts ​一、下载插件并在页面中引入 npm install echarts --save 页面导入&#xff1a; import * as echarts from echarts 全局导入&#xff1a; main.js 中&#xff0c;导入并注册到全局 import echarts from echarts Vue.prototype.$echart…

【云存储】【腾讯云】【阿里云】【b2】【google drive】【one drive】【s3】【azure】对比

【1】google drive 【2】b2 price 【3】腾讯云对象存储 文档中心 > 对象存储 > 开发者指南 > 对象 > 存储类型 > 存储类型概述 文档中心 > 对象存储 > 购买指南 > 计费项 > 数据取回费用

【计算机组成原理】24王道考研笔记——第四章 指令系统

第四章 指令系统 一、指令系统 指令是指示计算机执行某种操作的命令&#xff0c;是计算机运行的最小功能单位。一台计算机的所有指令的集合构成该 机的指令系统&#xff0c;也称为指令集。 指令格式&#xff1a; 1.1分类 按地址码数目分类&#xff1a; 按指令长度分类&…

AttentionFreeTransformer 源码解析(一):AFTFull、AFTSimple、AFTLocal

我觉得源码写的很好懂&#xff0c;我就不加注释了&#xff0c;直接上计算流程图。 AFTFull class AFTFull(nn.Module):def __init__(self, max_seqlen, dim, hidden_dim64):super().__init__()max_seqlen: the maximum number of timesteps (sequence length) to be fed indim…

echarts柱状图X轴增加table列表显示数据,多y轴

效果图 完整配置 data(){return{chart1:null,chartType1:1,data:{years:{date:[2015,2016,2017,2018,2019,2020,2021,2022,2023],business:[10,23,26,33,43,58,50,45,66],profit:[3,4,6,7,8,5,7,8,12],proportion:[12,8,15,20,12,16,13,15,9]},months:{date:[1月, 2月,3月, 4月…

在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配

1.Cadence 17.2 配置CIS数据库报&#xff1a;ERROR(ORCIS-6245): Database Operation Failed 安装cadance17.2以上版本时&#xff0c;ERROR(ORCIS-6245): Database Operation Failed_收湾湾的博客-CSDN博客 原因是ODBC数据库没有配置&#xff0c;或者没有驱动&#xff0c; 驱…

侯捷 C++ part2 兼谈对象模型笔记——3 模板

3 模板 3.1 类模板/函数模板 补充&#xff1a;只有模板的尖括号中<>&#xff0c;关键字 typename 和 class 是一样的 3.2 成员模板 它即是模板的一部分&#xff0c;自己又是模板&#xff0c;则称为成员模板 其经常用于构造函数 ctor1 这是默认构造函数的实现&#…

阿里云服务器免费申请使用限制条件及云主机配置

阿里云服务器免费试用申请链接入口&#xff0c;阿里云个人用户和企业用户均可申请免费试用&#xff0c;最高可以免费使用3个小时&#xff0c;阿里云服务器网分享阿里云服务器免费试用申请入口链接及云服务器配置&#xff1a; 目录 阿里云服务器免费试用 企业用户免费服务器试…

解决Qt的列表加载大量数据卡顿的问题

问题概述 本人在使用QListView插入大量数据时&#xff0c;界面卡顿十分严重。数据量大概只有上千左右&#xff0c;但是每个Item的内容比较多。当数据不停地插入一段时间后&#xff0c;卡顿到鼠标的移动都有点困难。 解决思路 QListView是典型的MVC思想的产物。界面呈现出来的数…

CorelDRAW(CDR) 2023中文版64位下载新功能教程

CorelDRAW2023&#xff08;简称CDR2023&#xff09;是一款非常专业的图形设计工具&#xff0c;该产品推出了全新的2023版本&#xff0c;在功能和体验上更进一步&#xff0c;最新的填充和透明设备功能可以完全控制任何类型的纹理&#xff0c;适用于网络摄影、印刷项目、艺术、排…

G. Counting Graphs Codeforces Round 891 (Div. 3) 1857G

Problem - G - Codeforces 题目大意&#xff1a;给出一棵n个点的边权树&#xff0c;问有多少个边权最大不超过s的图的最小生成树是这棵树 2<n<2e5;1<w[i]<1e9 思路&#xff1a;对于最小生成树上的每一条边&#xff0c;如果我们在包含这条边的链上的两点之间加了…

SpringBoot 该如何预防 XSS 攻击

XSS 漏洞到底是什么&#xff0c;说实话我讲不太清楚。但是可以通过遇到的现象了解一下。在前端Form表单的输入框中&#xff0c;用户没有正常输入&#xff0c;而是输入了一段代码&#xff1a;</input><img src1 onerroralert1> 这个正常保存没有问题。问题出在了列表…