计算机视觉实验:图像增强应用实践

news/2024/5/14 22:13:37

本次实验主要从基于统计、函数映射的图像增强方法和基于滤波的图像增强方法两种方法中对一些图像增强的算法进行实现。主要的编程语言为python,调用了python自带的PIL图像库用于读取图像,利用numpy进行图像运算,最后使用opencv第三方库进行对比验证。下面为实验的详细步骤与过程。

基于统计、函数映射的图像增强方法

图像反转

所谓的图像反转是将颜色或灰度进行颠倒,如白色变成黑色,亮变暗暗变亮等等。其原理在于用255减去每个像素的颜色值或灰度值,从而达到反转的效果,R/G/B = 255 - R/G/B。下面使用代码进行实现(完整代码见 图片反转.py)。

  • 调用Image与numpy读取图像信息
  1.  img = np.array(Image.open(path))
  1. 根据shape判断是否是彩色图并用255减去颜色值
  1. if len(img.shape) > 2:
  2.         img = np.array(list(map(lambda x:list(map(lambda y:list(map(lambda z:255-z, y)), x)), img)))
  3. else:
  4.         img = np.array(list(map(lambda x:list(map(lambda y:255-y, x)) , img)))
  • 保存图像
  1. 下面的uint8是为了改变数据类型 否则会报错
  2. image = Image.fromarray(np.uint8(img))
  3. 保存图片
  4. image.save(f'./output/reverse/{path[7:]}')
  5. image.show()

调用opencv进行结果对比

代码如下所示,此代码调用了opencv库进行图像反转操作。完整代码见图片反转opencv.py

与上面的代码基本一致,不同点在于调用Opencv来代替Image与numpy的部分操作。其关键不同代码如下所示。

  1. 创建空图像
  2. dst = np.zeros((height, width, 3), np.uint8)
  3. for i in range(height):
  4.  for j in range(width):
  5.         (b, g, r) = img[i, j]
  6.         b = 255 - b
  7.         g = 255 - g
  8.         r = 255 - r
  9.         dst[i, j] = (b, g, r)
  10. 部分代码参考于https://laoai.blog.csdn.net/article/details/81133070

最后两者结果如下图图1所示

图1 图像反转结果对比图

从结果中可以看出,与原始图像相比颜色发生了很大的反转。而未用Openvc处理与使用了Opencv处理的结果是一样的。

直方图均衡化

直方图均衡化只要是让灰度能均匀分布而不是集中在某个范围内。使得某些地方特别亮某些特别暗。直方图均衡化的操作流程一般如下图图2所示,首先需要计算出目前原始图像的灰度直方图。然后对数量占比进行累加。累加得到的结果均在0-1之间。那么用255乘以结果,以获取最新的映射关系,此时再绘制直方图那么就可看出其分布更均匀。下面利用代码进行实现。

图2 直方图均衡化流程图

此处使用一张灰度图进行处理coins.png

  • 计算直方图

利用字典统计每个灰度值的数量映射

  1. def show_hist(img):
  2.     hist = collections.defaultdict(int)
  3.     for i in img:
  4.         for j in i:
  5.             hist[j] += 1
  6.     绘制直方图
  7.     plt.title('灰度直方图')
  8.     plt.xlabel('Bins')
  9.     plt.xlim([0256])
  10.     plt.ylabel('Pixels')
  11.     plt.bar(hist.keys(), hist.values())
  12.     plt.show()
  13.     return hist

 累加操作

  1. for i in range(256):
  2.     if i:
  3.         reduction_hist[i] = hist[i]+reduction_hist[i-1]
  4.     else:
  5.         reduction_hist[i] = hist[i]
  • 计算新的映射关系
  1. for index, i in enumerate(img):
  2.     for jndex, j in enumerate(i):
  3.         img[index][jndex] = reduction_hist[img[index][jndex]]*255

调用opencv进行结果对比

Opencv只需要调用下面的库函数即可进行直方图均衡化操作。详细代码可见直方图均衡化cv.py

  1. img = cv2.equalizeHist(img)

将原始图像、非opencv处理的直方图均衡化图像与opencv处理的直方图均衡化图像进行对比,如下图图3所示。可以看到后面两者与前面原始图像相比其直方图分布更均匀。而后面两者基本无差别。

图3 直方图均衡化结果对比图

伽马变换

伽马变换的数学公式如下所示,其中s为变换后的值,c为一常数此处取1,$\gamma$是用于控制变换幅度的,而r则是原图像的输入范围在0-1。

在查阅资料后发现,opencv并未自带伽马变换的相关函数,所以此处不进行与opencv的结果对比。根据学习发现,伽马变换需要进行以下步骤。

  • 图像数据归一化
  • 图像各像素点进行乘幂运算

最后代码如下:

  1. def gama_transfer(img,power1):
  2.     if len(img.shape) > 3:
  3.          img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
  4.     img = 255*np.power(img/255,power1)
  5.     img = np.around(img)
  6.     img[img>255] = 255
  7.     out_img = img.astype(np.uint8)
  8.     return out_img
  9. 参考于https://zhuanlan.zhihu.com/p/340513008?utm_id=0

结果输出如下图图4所示,

图4 伽马变换结果对比图

从图片对比中可以看出, 时暗部变量,对于此图可以看得更清晰, 时暗部变暗,图片则更难看清。

基于滤波的图像增强方法

均值滤波

均值滤波的原理在于将图像中的每个像素点的值都变成其周围n阶矩阵的平均值。所以在编程实现中,首先需要创建一个大小一样的0矩阵用以记录平均值。然后遍历一次图像,将计算得到的平均值填充进0矩阵中即可得到均值滤波的结果。其核心代码如下(完整可见`均值滤波.py`):

  1. for index in range(height):
  2.         for jndex in range(width):
  3.             判断是否为边界
  4.             if index <= int((kernel-1)/2) - 1 or index >= height - 1 - int((kernel-1)/2) \
  5.                     or jndex <= int((kernel-1)/2) - 1 or jndex >= height - int((kernel-1)/2) - 1:
  6.                 result[index, jndex] = img[index, jndex]
  7.             else:  均值值滤波
  8.                 result[index, jndex] = np.average(
  9.                     img[index - int((kernel-1)/2):index + int((kernel-1)/2) + 1,
  10.                     jndex - int((kernel-1)/2):jndex + int((kernel-1)/2) + 1])
  11. 部分参考于https://blog.csdn.net/qq_43633939/article/details/120854570

此处对于边界不做任何处理。上面的代码是针对灰度图的,若需要对彩色图片进行滤波处理,则可在后面加上三个通道即可如下面代码所示。

  1. for kndex in range(3):
  2.     result[index, jndex, kndex] = np.average(
  3.         img[index - int((kernel - 1) / 2):index + int((kernel - 1) / 2) + 1,
  4.             jndex - int((kernel - 1) / 2):jndex + int((kernel - 1) / 2) + 1, kndex])

调用opencv进行结果对比

均值滤波对于opencv存在一个函数调用,只需要指定滤波核即可进行操作。此处滤波核均选择3*3。

  1. import cv2
  2. path = './pics/save.bmp'
  3. # img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
  4. img = cv2.imread(path)
  5. ksize = [3,3]
  6. dst=cv2.blur(img,ksize)
  7. cv2.imshow('img', dst)
  8. cv2.imwrite(f'./cv-output/mean-filtering/{path[7:]}', img)
  9. cv2.waitKey(0)

最后将输出结果进行对比,如下图图5所示。

图5 均值滤波结果对比图

可以看出原图和滤波后的图像差别还是很大的,原图的噪点颗粒很清晰,而滤波后则变得模糊。同时opencv的结果和自编代码的结果差别不大。

高斯滤波

高斯滤波的流程图如下图图6所示,

图6 高斯滤波流程图

对于高斯滤波首先需要根据下面的高斯公式计算出各点的高斯值,

其中x,y均是离中心点的距离,所以说对于整个图像高斯值是固定的。在得到这些值后,将他们的各自除以他们的和以进行归一化。最后中心值等于归一化的结果除以周围点颜色值后求和。根据以上思路可进行编程如下:

  • 计算高斯值
  1. kernel = 3
  2. sigma = 1.3
  3. K = np.zeros([kernel, kernel])
  4. 计算高斯值
  5. for x in range(-12):
  6.     for y in range(-1,2):
  7.         K[x+1, y+1] = np.exp( -(x ** 2 + y ** 2) / (2 * (sigma ** 2)))

  • 归一化
  1. 归一化
  2. K = K/np.sum(K)
  • 加权求和
  1. result[index, jndex] = np.sum(K*img[index - int((kernel-1)/2):index + int((kernel-1)/2) + 1,
  2.                     jndex - int((kernel-1)/2):jndex + int((kernel-1)/2) + 1])

完整代码可见于`高斯滤波.py`

调用opencv进行结果对比

对于opencv高斯滤波只需要一个函数即可进行。完整代码见高斯滤波cv.py。

  1. result = cv2.GaussianBlur(img, (33), 1.3)

最后输出结果如下图图7所示,

图7 高斯滤波结果对比图

可以看到和原图相比高斯滤波后的结果变得模糊,同时有些噪点也变得不明显。高斯滤波的结果和opencv的结果基本一致。

实验结论或体会

本次实验完成了图像反转、直方图均衡化、伽马变换、均值滤波、高斯滤波五种图像增强方法的代码实现。并将输出的图片与opencv的结果进行对比发现基本一致,说明本次实验编程实现的方法基本与实际相符合。同时图像增强后的图像与原图进行对比,可以看出不同增强方法的作用,比如说高斯滤波可以减弱图像的噪点,伽马变换可以让原图的暗部或亮部细节更突出以获得隐藏的信息,直方图均衡化可以让图像亮度或颜色分布更均匀使得图像原本不能看出的细节可清晰显示等等。

在此次实验中,对图像进行增强需要用到python的PIL库和numpy库,这些的使用让我们更加地了解图像处理的方式。同时通过对这些库的练习也让我更加熟练地直接操作图像的像素点。理论课中讲解的关于图像增强方法的知识,在代码编辑实现过程中均得以体现,通过实验对理论知识理解也更加深入。总而言之,此次的实验让我对图像增强方法以及图像的处理方法有了更加深入的了解。


http://www.mrgr.cn/p/74048087

相关文章

2023-07-31力扣每日一题

链接&#xff1a; 143. 重排链表 题意&#xff1a; 将链表L0 → L1 → … → Ln - 1 → Ln变成L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 解&#xff1a; 线性表法还是好写的 这边搞一下翻转法&#xff0c;快慢指针求翻转点&#xff08;翻转后面一半然后双指针合并…

shell脚本:数据库的分库分表

#!/bin/bash ######################### #File name:db_fen.sh #Version:v1.0 #Email:admintest.com #Created time:2023-07-29 09:18:52 #Description: ########################## MySQL连接信息 db_user"root" db_password"RedHat123" db_cmd"-u${…

第五章 Opencv图像处理框架实战 5-3 图像阈值与平滑处理

图像阈值 ret, dst cv2.threshold(src, thresh, maxval, type) src&#xff1a; 输入图&#xff0c;只能输入单通道图像&#xff0c;通常来说为灰度图 dst&#xff1a; 输出图 thresh&#xff1a; 阈值 maxval&#xff1a; 当像素值超过了阈值&#xff08;或者小于阈值&am…

产品开发八大模块交流︱奇瑞新能源汽车产品开发院院长荣升格

奇瑞新能源汽车股份有限公司研发中心/产品开发院院长荣升格先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;产品开发八大模块交流。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; VUCA时代…

Linux之 环境变量

什么是环境变量 windows中也有个 Linux 环境变量 env linux和windows环境变量&#xff0c;功能类似的&#xff0c; windows系统的环境变量&#xff0c;在cmd中可以之间调用程序运行。这些程序的执行程序的路径&#xff0c;一般编辑在path变量中 环境变量都分全局的&#xff…

想做上位机,学C#还是QT?

学习C#还是Qt&#xff0c;取决于你的具体需求和偏好。 如果你计划开发跨平台的桌面应用程序&#xff0c;并且希望使用一种更轻量级、直观的界面框架&#xff0c;那么Qt可能是一个不错的选择。Qt是一个功能丰富且成熟的跨平台框架&#xff0c;支持多种开发语言&#xff08;包括…

[个人笔记] Windows配置NTP时间同步

Windows - 运维篇 第六章 Windows配置NTP时间同步 Windows - 运维篇系列文章回顾Windows配置NTP时间同步域控环境的NTP配置工作组环境的NTP配置Windows的CMD部分命令集 参考来源 系列文章回顾 第一章 迁移WinSrv系统到虚拟机 第二章 本地安全策略xcopy实现实时备份文件夹内容 …

[golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务

本次内容需要 gin框架基础知识, golang微服务基础知识才能更好理解 一.Captcha验证码功能引入 在前面,讲解了微服务的架构等,这里,来讲解前面商城项目的 Captcha验证码 微服务 ,captcha验证码功能在前台,后端 都要用到 ,可以把它 抽离出来 ,做成微服务功能 编辑 这个验证码功能…

SBFI AM(Na+Indicator),129423-53-6,可用来预测纯化线粒体Na+梯

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ SBFI AM(NaIndicator)钠离子荧光探针 PART1----​Product structure&#xff1a; PART2----​Product specifications&#xff1a; 1.CAS No&#xff1a;129423-53-6 2.Molecular formula&#xff1a;C56H58N2O23 3.Molec…

Docker 容器生命周期:创建、启动、暂停与停止----从创建到停止多角度分析

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【后端面经】微服务构架 (1-6) | 隔离:如何确保心悦会员体验无忧?唱响隔离的鸣奏曲!

文章目录 一、前置知识1、什么是隔离?2、为什么要隔离?3、怎么进行隔离?A) 机房隔离B) 实例隔离C) 分组隔离D) 连接池隔离 与 线程池隔离E) 信号量隔离F) 第三方依赖隔离二、面试环节1、面试准备2、基本思路3、亮点方案A) 慢任务隔离B) 制作库与线上库分离三、章节总结 …

100个网络安全测试面试题

1、Burpsuite常用的功能是什么&#xff1f; 2、reverse_tcp和bind_tcp的区别&#xff1f; 3、拿到一个待检测的站或给你一个网站&#xff0c;你觉得应该先做什么&#xff1f; 4、你在渗透测试过程中是如何敏感信息收集的&#xff1f; 5、你平时去哪些网站进行学习、挖漏洞提交到…

NAT协议(网络地址转换协议)详解

NAT协议&#xff08;网络地址转换协议&#xff09;详解 为什么需要NATNAT的实现方式静态NAT动态NATNAPT NAT技术的优缺点优点缺点 NAT协议是将IP数据报头中的IP地址转换为另外一个IP地址的过程&#xff0c;主要用于实现私有网络访问公有网络的功能。这种通过使用少量的IP地址代…

C—数据的储存(下)

文章目录 前言&#x1f31f;一、练习一下&#x1f30f;1.例一&#x1f30f;2.例二&#x1f30f;3.例三&#x1f30f;4.例四 &#x1f31f;二、浮点型在内存中的储存&#x1f30f;1.浮点数&#x1f30f;2.浮点数存储&#x1f4ab;&#xff08;1&#xff09;.二进制浮点数&#x…

查找-多路查找详解篇

多路查找树 多路查找树&#xff08;Multway Search Tree&#xff09;是一种高级的树形数据结构&#xff0c;它 允许每个节点有多个子节点&#xff08;通常大于等于2&#xff09;。多路查找树的每个节点 可以存储多个关键字和对应的值。分类 2-3树&#xff08;2-3 Tree&#x…

微服务——服务异步通讯RabbitMQ

前置文章 消息队列——RabbitMQ基本概念容器化部署和简单工作模式程序_北岭山脚鼠鼠的博客-CSDN博客 消息队列——rabbitmq的不同工作模式_北岭山脚鼠鼠的博客-CSDN博客 消息队列——spring和springboot整合rabbitmq_北岭山脚鼠鼠的博客-CSDN博客 目录 Work queues 工作队列…

动态内存管理面试题

动态内存管理面试题 文章目录 动态内存管理面试题一、第一题此代码存在的问题运行结果分析原因修改 二、第二题此代码存在的问题运行结果分析原因修改 一、第一题 代码如下&#xff08;示例&#xff09;&#xff1a; #include<stdio.h> #include<string.h> #incl…

echarts遇到的问题

文章目录 折线图-区域面积图 areaStyley轴只有整数y轴不从0开始y轴数值不确定&#xff0c;有大有小&#xff0c;需要动态处理折线-显示label标线legend的格式化和默认选中状态x轴的lable超长处理x轴的相关设置 echarts各个场景遇到的问题 折线图-区域面积图 areaStyle areaStyl…

关于提示词 Prompt

Prompt原则 原则1 提供清晰明确的指示 注意在提示词中添加正确的分割符号 prompt """ 请给出下面文本的摘要&#xff1a; <你的文本> """可以指定输出格式&#xff0c;如&#xff1a;Json、HTML提示词中可以提供少量实例&#xff0c;…

ubuntu目录分析

在Ubuntu根目录下&#xff0c;以下是一些常见文件夹的含义&#xff1a; /bin&#xff1a;存放可执行文件&#xff0c;包含一些基本的命令和工具。 /boot&#xff1a;存放启动时所需的文件&#xff0c;如内核和引导加载程序。 /dev&#xff1a;包含设备文件&#xff0c;用于与硬…