OpenCV—python 色阶调整(直方图均衡化 图像去雾)

一、色阶调整( Levels Adjustment )原理

色阶:就是用直方图描述出的整张图片的明暗信息。如图
从左至右是从暗到亮的像素分布,
黑色三角代表最暗地方(纯黑—黑点值为0),
白色三角代表最亮地方(纯白—白点为 255)。
灰色三角代表中间调。(灰点为1.00)

对于一个RGB图像, 可以对R, G, B 通道进行独立的色阶调整,即对三个通道分别使用三个色阶定义值。还可以再对 三个通道进行整体色阶调整。
因此,对一个图像,可以用四次色阶调整。最终的结果,是四次调整后合并产生的结果。
cv2.equalizeHist(img) 函数

img = cv2.imread('./20181106194742.png',0)
equ = cv2.equalizeHist(img) # 只能传入灰度图

res = np.hstack((img,equ))  # 图像列拼接(用于显示)

cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

二、自动色阶图像处理算法

cv2.createCLAHE() 对比度有限自适应直方图均衡
直方图均衡后背景对比度有所改善。但导致亮度过高,我们丢失了大部分信息。这是因为它的直方图并不局限于特定区域。
因此,为了解决这个问题,使用自适应直方图均衡。在此,图像被分成称为“图块”的小块(在OpenCV中,tileSize默认为8x8)。然后像往常一样对这些块中的每一个进行直方图均衡。所以在一个小区域内,直方图会限制在一个小区域(除非有噪音)。如果有噪音,它会被放大。为避免这种情况,应用对比度限制。如果任何直方图区间高于指定的对比度限制(在OpenCV中默认为40),则在应用直方图均衡之前,将这些像素剪切并均匀分布到其他区间。均衡后,为了去除图块边框中的瑕疵,应用双线性插值。

import numpy as np
import cv2

img = cv2.imread('20181106194742.png',0)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)

cv2.imshow('img',img)
cv2.imshow('cl1',cl1)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
自适应色阶去雾气【参看代码请点击】 主要使用numpy优化了计算耗时。

import numpy as np
import cv2


def ComputeMinLevel(hist, pnum):
    index = np.add.accumulate(hist)
    return np.argwhere(index>pnum * 8.3 * 0.01)[0][0]


def ComputeMaxLevel(hist, pnum):
    hist_0 = hist[::-1]
    Iter_sum = np.add.accumulate(hist_0)
    index = np.argwhere(Iter_sum > (pnum * 2.2 * 0.01))[0][0]
    return 255-index


def LinearMap(minlevel, maxlevel):
    if (minlevel >= maxlevel):
        return []
    else:
        index = np.array(list(range(256)))
        screenNum = np.where(index<minlevel,0,index)
        screenNum = np.where(screenNum> maxlevel,255,screenNum)
        for i in range(len(screenNum)):
            if screenNum[i]> 0 and screenNum[i] < 255:
                screenNum[i] = (i - minlevel) / (maxlevel - minlevel) * 255
        return screenNum


def CreateNewImg(img):
    h, w, d = img.shape
    newimg = np.zeros([h, w, d])
    for i in range(d):
        imghist = np.bincount(img[:, :, i].reshape(1, -1)[0])
        minlevel = ComputeMinLevel(imghist,  h * w)
        maxlevel = ComputeMaxLevel(imghist, h * w)
        screenNum = LinearMap(minlevel, maxlevel)
        if (screenNum.size == 0):
            continue
        for j in range(h):
            newimg[j, :, i] = screenNum[img[j, :, i]]
    return newimg


if __name__ == '__main__':
    img = cv2.imread('./20181106194742.png')
    newimg = CreateNewImg(img)
    cv2.imshow('original_img', img)
    cv2.imshow('new_img', newimg / 255)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值