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

26 篇文章 1 订阅
19 篇文章 1 订阅

背景说明

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

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

在这里插入图片描述

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

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

处理步骤1-对比度增强

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

import cv2  
import numpy as np 
import math
  

def 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)  # 公式计算gamma

    image_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。

import cv2
import numpy as np
def zmMinFilterGray(src, r=7):
    '''最小值滤波,r是滤波器半径'''
    '''if r <= 0:
        return src
    h, w = src.shape[:2]
    I = src
    res = np.minimum(I  , I[[0]+range(h-1)  , :])
    res = np.minimum(res, I[range(1,h)+[h-1], :])
    I = res
    res = 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.shape
    m_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_p
    m_II = cv2.boxFilter(I * I, -1, (r, r))
    var_I = m_II - m_I * m_I
    a = cov_Ip / (var_I + eps)
    b = m_p - a * m_I
    m_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 = 2000
    ht = np.histogram(V1, bins)  # 计算大气光照A
    d = np.cumsum(ht[0]) / float(V1.size)
    for lmax in range(bins - 1, 0, -1):
        if d[lmax] <= 0.999:
            break
    A = 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 Y

input_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)

其他效果对比

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

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

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

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

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

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值