计算机视觉(OpenCV+TensorFlow)

计算机视觉(OpenCV+TensorFlow)


文章目录

  • 计算机视觉(OpenCV+TensorFlow)
  • 前言
    • 7. 图像直方图
        • 绘制直方图
          • 绘制直方图有两种方式:
        • 掩膜
    • 8. 直方图均衡化
      • 直方图均衡化的介绍
      • 直方图均衡化的步骤
      • 自适应直方图均衡化
    • 9. 图像转换
      • 傅里叶变换
      • 在频域中的图像
      • OpenCV中使用傅里叶变换
      • 高通滤波和低通滤波
  • 总结


前言

本系列文章是OpenCV系列文章的第四篇,仍然跟随上篇内容主要聚焦于图像的一些操作,到本篇为止,与图像有关的所有的基本操作我们就都总结完了


7. 图像直方图

图像直方图顾名思义就是,x轴是像素值,y是像素的数量
下图就是一个图像直方图,像素值为250的数量大概是500个
在这里插入图片描述


Opencv给我们提供的函数是cv2.calcHist(),该函数有5个参数:

  • image:输入图像,传入时应该用中括号括起来,也就是我们可以传入多张数据
  • channels:传入图像的通道,如果是灰度图像,那只有一个通道,值为0,如果是彩色图像,那么值为0,1,2中选择一个,对应着BGR各个通道,这个值也要[]传入
  • mask:掩膜图像,如果统计整幅图,那么为none,如果我们只是统计图的一部分的直方图,那就要构造相应的掩膜实现,这个之后我们再具体说
  • histSize:灰度级的个数,需要中括号,比如[256]
  • ranges:像素值的范围,通常[0,256],有的图像如果不是,需要自己调整这个值

hist是256x1的数组,每个值对应于该图像中具有相应像素值的像素数

img = cv2.imread('cat.jpg',0) #0表示灰度图
hist = cv2.calcHist([img],[0],None,[256],[0,256])

绘制直方图

绘制直方图有两种方式:
  1. 使用Matplotlib
    1. Matplotlib带有直方图绘图功能:matplotlib.pyplot.hist()

它直接找到直方图并将其绘制。无需使用 calcHist() 或 np.histogram() 函数来查找直方图

img = cv2.imread('cat.jpg',0) #0表示灰度图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
plt.hist(img.ravel(),256); 
plt.show()
  1. 或者还可以使用Matplotlib的法线图
img = cv2.imread('cat.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]) 
  1. 使用OpenCV,用OpenCV的话,就有点麻烦,还要对hist数组进行变化,所以就用Matplotlib就可以了。
掩膜

如果我们要查找图像某些区域的直方图,只需在要查找直方图的区域上创建白色图像,不查找的创建黑色。然后这个只有白色和黑色的图像就是一个掩膜。
掩膜其实就是用了与操作,因为要显示的区域掩膜上是255,255换算成二进制8个1,任何数跟1做与运算都是它本身,那也就是任何数跟255做与运算都是它本身,那这不就是保留了原来的值了嘛。而又因为不想保留的地方是黑色的,任何数与0做与运算都是0,所以就把不想保留的地方变成了黑色的

# 先创建一个都是0的数组,然后将部分区域变成白色
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)
# 相应位置做与运算
masked_img = cv2.bitwise_and(img, img, mask=mask)#与操作
# 传入mask,统计部分区域的图像直方图
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])

8. 直方图均衡化

https://blog.csdn.net/zaishuiyifangxym/article/details/89813977

直方图均衡化的介绍

** 直方图均衡化是一种简单有效的图像增强技术,通过改变图像的直方图来改变图像中各个像素的灰度,主要用于增强动态范围偏小的图像的对比度。原始图像由于其灰度分布可能集中在较窄的区间,造成图像不够清晰。**

例如,过曝光图像的灰度级集中在高亮度范围内,而曝光不足图像的灰度级集中在低亮度范围内。
** 通过直方图均衡化,可以把原始图像的直方图变换成均匀分布的形式,这样就增加了像素之间灰度值差别的动态范围,从而达到增强图像整体对比度的效果。**

简而言之,直方图均衡化的原理是:对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而增大对比度,使图像清晰。

直方图均衡化的步骤

  1. 计算累计直方图
  2. 将累计直方图进行区间转换
  3. 在累计直方图中,概率相近的原始值会被处理为相同值

具体的例子:
** 如下图所示,已知一幅图像的像素分布为 7**
在这里插入图片描述

7,根据像素值,则可以计算出统计直方图

在这里插入图片描述


根据统计直方图,可以算出归一化直方图和累计直方图,如下图所示:

在这里插入图片描述


将累计直方图进行区间转换,如下图所示:

在这里插入图片描述


我们看均衡直方图,1对应3,这个3是说明像素级<=1的共有3个,那像素级为1的就有2个
2-0,3-1,4-1,5-0,6-1,7-1,我们可以看到有两个都是0,那相比于原来不就少了两个像素级嘛
上面的灰度级是8,那灰度级转变成256,计算方法类似,如下图所示:

在这里插入图片描述

!
原始直方图和均衡直方图为

在这里插入图片描述


由上图可以看出,虽然二者相似,但右侧均衡化后的直方图分布更均匀,相邻像素级概率和与高概率近似相等。如果将两张图的灰度级放在同一区间,可以看出差别更大,如下图所示:

在这里插入图片描述

在OpenCV中,我们用 equ = cv2.equalizeHist(img) 这个函数就可以均衡化

# 均衡化之前
img = cv2.imread('clahe.jpg',0) #0表示灰度图 #clahe
plt.hist(img.ravel(),256); 
plt.show()
# 均衡化之后
equ = cv2.equalizeHist(img) 
plt.hist(equ.ravel(),256)
plt.show()

均衡化之前:

在这里插入图片描述

均衡化之后:

在这里插入图片描述

自适应直方图均衡化

下图是均衡化的前后对比,可以看到背景的对比度是增强了,但是雕像的脸却变亮了许多,我们在那里丢失了大多数的信息,这是因为均衡化是默认是对全图进行均衡化,我们也可以分模块进行均衡化,这样就可以处理的更好。
在这里插入图片描述
在这里插入图片描述


在OpenCV 中,我们用 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) 函数来做自适应变化

  • titleGridSize 进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作
  • clipLimit:颜色对比度限制阈值,默认为40;
# 创建一个clear对象
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) 
# 让图像交给clear对象处理
res_clahe = clahe.apply(img)

9. 图像转换

傅里叶变换

傅里叶变换,在很多领域都有很重要的运用,那么在图像处理中也有许多的运用,如果有朋友不是很了解的话,可以看下面这篇文章

https://zhuanlan.zhihu.com/p/19763358
傅里叶变换在图像中的运用:

  1. 图像增强与图像去噪
  2. 图像分割与边缘检测
  3. 图像特征提取
  4. 图像压缩

大家看傅里叶变换在图像中的运用我们或多或少在前都提到过,比如这个图像增强,图像去噪,图像分割和边缘检测,但是那些都是在时域上的操作,如果把图像放到频域中,那这些操作会更轻松。
简单来说:傅里叶变换的目的并不是为了观察图像的频率分布(至少不是最终目的),更多情况下是为了对频率进行过滤,通过修改频率以达到图像增强、图像去噪、边缘检测、特征提取、压缩加密等目的。

在频域中的图像

下面是图像在频域中的一些概念:

  1. 图像的频率是表征图像中灰度变化剧烈程度的指标,是灰度在平面空间上的梯度
  2. 图像高频分量:图像突变部分;在某些情况下指图像边缘信息,某些情况下指噪声,更多是两者的混合;
  3. 低频分量:图像变化平缓的部分,也就是图像轮廓信息
  4. 高通滤波器:让图像使低频分量抑制,高频分量通过
  5. 低通滤波器:与高通相反,让图像使高频分量抑制,低频分量通过
  6. 带通滤波器:使图像在某一部分的频率信息通过,其他过低或过高都抑制
  7. 还有个带阻滤波器,是带通的反。

OpenCV中使用傅里叶变换

如果有朋友想要快速上手在OpenCV中使用傅里叶变换,只需要记住

  1. 傅立叶变换的物理意义是将图像的灰度分布函数变换为图像的频率分布函数、
  2. 傅立叶变换提供另外一个角度来观察图像,可以将图像从灰度分布转化到频率分布上来观察图像的特征。
  3. 对一张图像做傅里叶变换,就是将它分解为 sin 和 cos 两部分,也就是将图像从空间域转换到频域。
    在这里插入图片描述

import numpy as np
import cv2
from matplotlib import pyplot as plt
# 导入一张灰度图
img = cv2.imread('lena.jpg',0)
# 将图像转换为float32的格式
img_float32 = np.float32(img)
# OpenCV的傅里叶变换函数,输出的是图像经过傅里叶变换后的结果
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
# 此时,图像频谱中的零频率分量位于频谱图像(频域图像)的左上角,
# 通常使用 numpy.fft.fftshift() 来将零频率成分移动到频域图像的中心位置
dft_shift = np.fft.fftshift(dft)
# 我们得到的是一个复数数组,为了显示图像,需要将他们的值调到 [0,255] 的灰度空间中
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()

右边的图是左边图的频谱图

在这里插入图片描述


那频谱图是什么呢?具体的解释大家可以看这篇文章:https://blog.csdn.net/u014488388/article/details/52612456?t=1496943343720&utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-52612456-blog-94553357.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.1&utm_relevant_index=3

那简单的解释就是:
可以将频谱的中心看做坐标原点,横轴为x轴,纵轴是y轴,建立坐标系。
频谱平面上的坐标(X,Y)的黑白,表示图像是否含有z = sin(Xw + Yw)这个正弦平面波成分,白即是有含有。
但是最后的图是我们经过对数运算后的图,原本的图看起来不是很清晰,所以我们用对数运算将对比度放大了看的就比较清晰了

未经对数运算的频谱

在这里插入图片描述

高通滤波和低通滤波

刚才我们得到了这张图片的频谱图,那下面我们就要对这个频谱图进行操作

https://blog.csdn.net/weixin_51995147/article/details/124767050?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-124767050-blog-71699582.pc_relevant_landingrelevant&spm=1001.2101.3001.4242.1&utm_relevant_index=3

import numpy as np
import cv2
from matplotlib import pyplot as plt
# 导进一张图片
img = cv2.imread('lena.jpg',0)
# 转换为 float32的格式
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)     # 中心位置# 低通滤波:图像中心的是低频,我们想要保留低频,过滤高频,就用一个掩膜,中心的是1,其他是0
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1# IDFT:傅里叶的逆变换
# 用频谱图乘掩膜,那最后就中心的保留了,其他都是0
fshift = dft_shift*mask
# 将低频的再移到原来的位置
f_ishift = np.fft.ifftshift(fshift)
# 进行傅里叶的逆变换
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()   

总结

那到本期,OpenCV有关的图像基本操作我们已经全部就介绍完了,但是只是草草地介绍这个一下的话,那对于学习本身是毫无意义的,所以接下来的一遍,我们将引入一个银行卡号图像检测的实战内容,帮助大家理解上述讲过的所有图像操作

我是Mayphry,从一点点到亿点点,我们下次再见

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

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

相关文章

SAP_ABAP_编程基础_数据集_创建并填充摘录数据集 / 处理摘录数据集

SAP ABAP 顾问&#xff08;开发工程师&#xff09;能力模型_Terry谈企业数字化的博客-CSDN博客文章浏览阅读494次。目标&#xff1a;基于对SAP abap 顾问能力模型的梳理&#xff0c;给一年左右经验的abaper 快速成长为三年经验提供超级燃料&#xff01;https://blog.csdn.net/j…

webshell之自建漏洞免杀

今天主要讲解&#xff0c;如何利用通用漏洞来进行命令执行&#xff0c;从而达到免杀效果 常规反序列化免杀 这种方式就相当于直接触发提供一个反序列化漏洞入口&#xff0c;但是能否被利用&#xff0c;还是在于服务端本身是否存在反序列化漏洞&#xff0c;下面给了一个例子&a…

基于机器学习的笔记本电脑导购系统

目 录 中英文摘要 第一章 概述 1 1.1 课题开发背景及意义 1 1.2 课题研究现状 2 1.3 课题主要研究内容 3 第二章 需求分析 4 2.1 功能需求分析 4 2.2 可行性分析 10 2.3 流程分析 11 2.4 数据流图 13 2.5 性能需求分析 15 第三章 开发技术及工具 16 3.1 系统开发模式技术 16 3…

《凤凰项目》读书笔记

文章目录 一、书名和作者二、书籍概览2.1 主要论点和结构2.2 目标读者和应用场景 三、核心观点与主题3.1 DevOps的核心原则与文化变革3.2 持续交付与自动化3.3 变更管理与风险控制3.4 关键绩效指标与持续改进 四、亮点与启发4.1 最有影响的观点4.2 对个人专业发展的启示 五、批…

【Linux--进程控制】

目录 一、进程等待1.1进程等待方法1.2获取子进程status 二、进程替换2.1单进程版本--最简单得程序替换2.2 进程替换得原理2.3 多进程版本--验证各种程序替换接口2.4 总结 一、进程等待 1.1进程等待方法 问题1&#xff1a;进程等待是什么&#xff1f; 通过系统调用wait/waitpi…

Java 定时任务

Java 定时任务 为什么需要定时任务&#xff1f; 我们来看一下几个非常常见的业务场景&#xff1a; 某系统凌晨 1 点要进行数据备份。某电商平台&#xff0c;用户下单半个小时未支付的情况下需要自动取消订单。某媒体聚合平台&#xff0c;每 10 分钟动态抓取某某网站的数据为…

五、关闭三台虚拟机的防火墙和Selinux

目录 1、关闭每台虚拟机的防火墙 2、关闭每台虚拟机的Selinux 2.1 什么是SELinux

使用SpringBoot和ZXing实现二维码生成与解析

一、ZXing简介 ZXing是一个开源的&#xff0c;用Java实现的多种格式的1D/2D条码图像处理库。它包含了用于解析多种格式的1D/2D条形码的工具类&#xff0c;目标是能够对QR编码&#xff0c;Data Matrix, UPC的1D条形码进行解码。在二维码编制上&#xff0c;ZXing巧妙地利用构成计…

系列十四、SpringBoot的jar包可以直接运行原理分析

一、普通jar包运行 vs SpringBoot jar包运行 1.1、普通jar包运行 general-test-1.0-SNAPSHOT.jar是位于D盘的一个普通的jar包&#xff0c;是idea中一个普通的maven项目通过package打包生成&#xff0c;为了方便测试我把它拷贝到D盘了。 java -jar general-test-1.0-SNAPSHOT.j…

springboot虚拟请求——测试

springboot虚拟请求 表现层测试 web环境模拟测试 虚拟请求状态匹配——执行状态的匹配 Testvoid testStatus(Autowired MockMvc mvc) throws Exception { // //http://localhost:8080/books// 创建一个虚拟请求&#xff0c;当前访问的是booksMockHttpServletRequestBui…

不会代码(零基础)学语音开发(学习工具)

学习&#xff0c;要选择适合自己的&#xff0c;好的学习工具至关重要。就像读书&#xff0c;要读好书一样。 自己不会选&#xff0c;可以参考前辈&#xff0c;找chatgpt等来帮忙。充分利用好周边的资源。 秉承着GPT和前辈们的经验之谈&#xff0c;开始选择语音开发产品&#…

localStorage 和sessionStorage

localStorage 和 sessionStorage 是浏览器提供的两种客户端存储数据的方式&#xff1a; 生命周期&#xff1a; localStorage&#xff1a; 存储在 localStorage 中的数据在浏览器关闭后仍然保留&#xff0c;直到被显式删除或浏览器清除缓存。sessionStorage&#xff1a; 存储在 …

操作系统-输入输出管理

I/O设备的基本概念和分类 I/O就是输入/输出 I/O设备就是可以将数据输入到计算机&#xff0c;或者可以接收计算机输出数据的外部设备&#xff0c;属于计算机中的硬件部件。 I/O设备按使用特性分类 人机交互类外部设备存储设备网络通信设备 I/O设备按传输速率分类 低速设备中…

uniapp-距离distance数字太长,截取保留前3为数字

1.需求 将接口返回的距离的字段&#xff0c;保留三位数显示。 2.实现效果 3.代码&#xff1a; 1.这是接口返回的数据&#xff1a; 2.调取接口&#xff0c;赋值前先处理每条数据的distance <view class"left">距你{{item.distance}}km</view>listFun() …

聚焦数据库Serverless创新,就在2023亚马逊云科技re:Invent

11月28日&#xff0c;亚马逊云科技在其最新的re:Invent 2023大会上宣布了三项重要的serverless创新&#xff0c;这些创新将极大地简化客户在任何规模上分析和管理数据的能力。以下是这些发布的主要要点总结和分析。 Amazon Aurora Limitless Database的新功能&#xff1a; 功能…

播放器开发(七):音视频同步实现

目录 学习课题&#xff1a;逐步构建开发播放器【QT5 FFmpeg6 SDL2】 原理 简单分析&#xff1a; 下图简单描述了在一个播放过程中&#xff0c;假设我们先播放音频&#xff0c;对比一个公共时间轴&#xff0c;视频就会始终比音频慢0.003s。 我们在日常中用一些播放器播放视频…

docker-compose脚本编写及常用命令

安装 linux DOCKER_CONFIG/usr/local/lib/docker/cli-plugins sudo mkdir -p $DOCKER_CONFIG/cli-plugins sudo curl -SL https://521github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose sudo c…

附录A 指令集基本原理

1. 引言 本书主要关注指令集体系结构4个主题&#xff1a; 1. 提出对指令集进行分类的方法&#xff0c;并对各种方法的优缺点进行定性评估&#xff1b; 2. 提出并分析一些在很大程度上独立于特定指令集的指令集评估数据。 3. 讨论语言与编译器议题以及…

shell编程系列(9)-使用cut选择列

文章目录 前言使用cut选择列选择特定的列 结语 前言 前面的文章介绍了sed命令&#xff0c;sed可以帮我们处理文本列&#xff0c;这边文章介绍cut命令&#xff0c;cut命令可以帮我们选择想要的列&#xff0c;在文本处理时候结合sed命令&#xff0c;就可以精准定位了。 cut命令是…

利用 NRF24L01 无线收发模块实现传感器数据的无线传输

NRF24L01 是一款常用的无线收发模块&#xff0c;适用于远程控制和数据传输应用。本文将介绍如何利用 NRF24L01 模块实现传感器数据的无线传输&#xff0c;包括硬件的连接和配置&#xff0c;以及相应的代码示例。 一、引言 NRF24L01 是一款基于 2.4GHz 射频通信的低功耗无线收发…