python 阴暗图像 亮度增强 对比度增强 去雾

news/2024/9/23 18:25:32/

背景说明

最近在处理图像,发现一些样本由于逆光原因过于阴暗,影响图像识别。解决时,可以在训练样本中加入类似的图像,或者手动把相关图像进行颜色变化。这里主要介绍手工颜色变化。

原始图像如下,假设你需要判断裤子的种类(牛仔裤还或棉布裤子),类似阴暗图像很难判断:

在这里插入图片描述

网上现有的解决方法中,主要包含直方图变化和gamma变换,例如下面几篇文章OpenCV调整图像对比度和亮度、qunshansj/opencv-python-image-dehazing-algorithm
、OpenCV-Python-(4)-对比度增强。

尽管这几篇文章都能起到“给图片增加亮度”的效果,但是gamma变换之后的图像总感觉有一层雾气覆盖,因此又结合了何凯明的去雾算法,最终完成了处理。

处理步骤1-对比度增强

使用gamma增强后,图片中人的右腿的对比度更加强烈,与原始图片相比,已经能够看清右腿上的褶皱,甚至鞋底的花纹都变得更明显。在人眼尺度下,此时基本已经能判断出这是一条棉布裤子
在这里插入图片描述
处理代码如下,其中的gamma可以是0到无穷大,0-1之间较为合理。可以参考这个链接。

python">import cv2  
import numpy as np 
import mathdef gamma_trans(img, gamma):  # gamma函数处理gamma_table = [np.power(x / 255.0, gamma) * 255.0 for x in range(256)]  # 建立映射表gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)  # 颜色值为整数return cv2.LUT(img, gamma_table)  # 图片颜色查表。另外可以根据光强(颜色)均匀化原则设计自适应算法。def process_image_gamma(image_path, output_path, gamma_factor):  # 读取图像  image = cv2.imread(image_path)  # 检查图像是否成功读取  if image is None:  print("Error: 图像无法读取。")  return  # 将图像的像素值转换为float32类型,以便进行数学运算  image_float = image.astype(np.float32)  img_gray = cv2.imread(image_path, 0)  # 灰度图读取,用于计算gamma值mean = np.mean(img_gray)gamma_val = math.log10(gamma_factor) / math.log10(mean / 255)  # 公式计算gammaimage_gamma_correct = gamma_trans(image, gamma_val)  # gamma变换# 保存修改后的图像  cv2.imwrite(output_path, image_gamma_correct)  print("处理完成,图像已保存至:", output_path)  # 使用示例  
image_path = r'E:\data\3.jpg'  # 替换为你的图像路径  
output_path = r'E:\data\3_1.jpg'  # 替换为你希望保存输出图像的路径  
process_image_gamma(image_path, output_path, gamma_factor=0.5)  # 可以调整gamma_factor参数来改变颜色变化的幅度

处理步骤2-去雾

在步骤1中,如果仔细观察,你会发现图片表面仍然有一层类似于雾气的白色覆盖,如果想要进一步处理,就需要用去雾算法了。目前使用何凯明的传统算法就能达到不错的效果:

在这里插入图片描述
如果与文章开始的图片对比,你会发现鞋底花纹、裤子纹路以及原本处于阴暗位置的数目和小草都变得更加容易识别。处理代码如下。你需要把bGamma参数设为true。

python">import cv2
import numpy as np
def zmMinFilterGray(src, r=7):'''最小值滤波,r是滤波器半径''''''if r <= 0:return srch, w = src.shape[:2]I = srcres = np.minimum(I  , I[[0]+range(h-1)  , :])res = np.minimum(res, I[range(1,h)+[h-1], :])I = resres = np.minimum(I  , I[:, [0]+range(w-1)])res = np.minimum(res, I[:, range(1,w)+[w-1]])return zmMinFilterGray(res, r-1)'''return cv2.erode(src, np.ones((2 * r + 1, 2 * r + 1)))  # 使用opencv的erode函数更高效
def guidedfilter(I, p, r, eps):'''引导滤波'''height, width = I.shapem_I = cv2.boxFilter(I, -1, (r, r))m_p = cv2.boxFilter(p, -1, (r, r))m_Ip = cv2.boxFilter(I * p, -1, (r, r))cov_Ip = m_Ip - m_I * m_pm_II = cv2.boxFilter(I * I, -1, (r, r))var_I = m_II - m_I * m_Ia = cov_Ip / (var_I + eps)b = m_p - a * m_Im_a = cv2.boxFilter(a, -1, (r, r))m_b = cv2.boxFilter(b, -1, (r, r))return m_a * I + m_b
def getV1(m, r, eps, w, maxV1):  # 输入rgb图像,值范围[0,1]'''计算大气遮罩图像V1和光照值A, V1 = 1-t/A'''V1 = np.min(m, 2)  # 得到暗通道图像V1 = guidedfilter(V1, zmMinFilterGray(V1, 7), r, eps)  # 使用引导滤波优化bins = 2000ht = np.histogram(V1, bins)  # 计算大气光照Ad = np.cumsum(ht[0]) / float(V1.size)for lmax in range(bins - 1, 0, -1):if d[lmax] <= 0.999:breakA = np.mean(m, 2)[V1 >= ht[1][lmax]].max()V1 = np.minimum(V1 * w, maxV1)  # 对值范围进行限制return V1, A
def deHaze(m, r=81, eps=0.001, w=0.95, maxV1=0.80, bGamma=True):Y = np.zeros(m.shape)V1, A = getV1(m, r, eps, w, maxV1)  # 得到遮罩图像和大气光照for k in range(3):Y[:, :, k] = (m[:, :, k] - V1) / (1 - V1 / A)  # 颜色校正Y = np.clip(Y, 0, 1)if bGamma:Y = Y ** (np.log(0.5) / np.log(Y.mean()))  # gamma校正,默认不进行该操作return Yinput_path = r'E:\data\3_1.jpg'  # 替换为你的图像路径  
output_path = r'E:\data\3_2.jpg'  # 替换为你希望保存输出图像的路径  image = cv2.imread(input_path)  m = deHaze(image / 255.0) * 255
height, width = m.shape[:2]
cv2.imwrite(output_path, m)

其他效果对比

以下两组实验省去了中间过程,只保留了输入图像和最终的图像,都达到了去阴暗的目的。

这是一张风景图,原图中,中间位置的房子基本不可识别,而处理后则可轻易识别出房子。

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

这是一张行人图片,原图可以识别出每一个人物,经过处理后,还可以识别人员身上的衣服花纹,图像右侧边缘正中间的花坛也呈现了更艳丽的紫色。

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


http://www.ppmy.cn/news/1511395.html

相关文章

【docker】docker compose进阶

docker compose docker compose简介docker compose yaml格式1、docker-compose部署tomcat2、docker-compose部署mysql3、docekr-compose部署lnmp项目需求准备依赖文件、配置nginx配置mysql配置php编写docker-compose.yml配置mysql 4、容器部署registry&#xff0c;进行容器上传…

【qt】跳转到另一个界面

如何在一个界面跳转到另一个界面呢&#xff1f; 1.具体步骤 1.先新建一个界面 2.选择qt设计师界面 3.选择W 4.新界面名称 5.界面设计 因为我们要实现通信&#xff0c;需要一个发送信息栏&#xff0c;一个发送按钮&#xff0c;一个清空发送栏按钮 6.实现跳转 我们可以参…

HTML补充——表格表单

一、表格 1、在现实生活中&#xff0c;我们经常需要使用表格来表示一些格式化数据&#xff1a;课程表、人名表、成绩单 同样在网页中我们也需要使用表格&#xff0c;我们通过table标签创建表格。 2、在table标签中使用tr表示表格中的一行&#xff0c;有几个tr就有几行&#xff…

掌握ChatGPT写作艺术:从入门到精通的四个层次

这些周末我仔细研究了如何通过优化提示词提升ChatGPT输出内容的质量。 关于如何使用ChatGPT辅助我们的写作&#xff0c;我归纳了以下规律&#xff0c;希望能为你带来启发。 一、写作步骤 撰写一篇文章&#xff0c;思路上必须是从抽象到具体逐步深入。 首先我们需要明确写什么…

SQL注入(原理、分类、union、POST注入)

目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 SQL注入简介 SQL注入原理 SQL注入类型 MySQL与SQL注入的相关知识 information_schema 数据库的结构 数据库查询语句 limit的用法 需要记住的几个函数 注释符号 SQL注入探测方法 SQL注入漏洞攻击流程…

回溯算法——LeetCode47 全排列 II

题目 力扣题目链接 思路 47.全排列 II 代码 注意注释部分&#xff0c;以及去重的逻辑&#xff08;很重要&#xff01;&#xff09; class Solution { private:vector<vector<int>> res;vector<int> path;void backtracking(vector<int>& num…

Linux第十节课 - gdb + 冯诺依曼体系结构

科普&#xff1a;开发流程 一个项目开发&#xff1a;项目经理 产品经理 程序员 测试&#xff08;可能有&#xff09;--->&#xff08;开发团队&#xff09; 产品经理提出来需求 --->>> 项目经理分配任务 ---> 程序员开发 --->>> 测试部门提交…

docker做Llm开发时可能会遇到的问题

如果没有开启GPU&#xff0c;会报错 docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]]. 原因可能是 &#xff1a;没有安装 GPU Docker 运行时 则按照如下参照安装&#xff0c; 基于 Docker 的深度学习环境&…