龙空技术网

暗光也清晰的图像增强算法

哈铁家园 235

前言:

眼前姐妹们对“增强对比度的算法”都比较讲究,我们都想要学习一些“增强对比度的算法”的相关内容。那么小编同时在网上汇集了一些对于“增强对比度的算法””的相关内容,希望小伙伴们能喜欢,咱们快快来学习一下吧!

某天跑完步以后拍出了这样一张照片,由于晚上开闪光不太好,所以想自己处理一下(为了更好的看出处理效果,所以采用尺寸较大的原图像,没有进行尺寸缩小):

在光线较暗的情况下拍摄的图像整体的灰度值偏低,可以从直方图中很直接的看出,图像的像素值都分布在50以内(直方图就是统计图像中0-255这256个级别对应的像素值个数,比如图像有1000个像素点,像素值为0的有10个,值为1的有5个。。。。值为255的有3个)像素值很多都接近于0并且少部分分布在100-255之间。

这里并没有对RGB三个通道分别进行统计,而是将RGB转为灰度图再进行统计(我会在另外的文章中单独的介绍直方图和直方图均衡算法)。

import imageioimport matplotlib.pyplot as pltimport numpy as npdef rgb2gray(rgb):     gray = rgb[:, :, 0] * 0.299 + rgb[:, :, 1] * 0.587 + rgb[:, :, 2] * 0.114     gray = gray.astype(np.uint8)     return graydef get_histgram(image, nums=256):    """    calculate histgram of a gray image    Args:        image:gray image        nums:pixel grade, defualt is 256    Return:        histgram    """    if len(image.shape) != 2:        raise ValueError("Input image is not a gray image")    h = image.shape[0]    w = image.shape[1]        hist = {}         for i in range(0, nums):        hist[i] = 0        for i in range(0, h):        for j in range(0, w):            hist[image[i][j]] += 1    return histimage_rgb = np.array(imageio.imread("dark.jpg"))image = rgb2gray(image_rgb)hist = get_histgram(image, nums=256)x = hist.keys()  y = hist.values()  plt.bar(x, y)plt.savefig("hist")

所以,要增加图像的亮度,既然直方图显示整体像素值偏低,那么就可以直接的把全体的像素值直接加上一个数值:

其中c是一个可以自由选择的常数,通过线性加法获得了下面的照片:

代码如下(由于大于195的像素值加60以后大于255,所以要限制最大像素值的方式):

# y = pixel*k + b# y = pixel*k + bimport imageioimport numpy as npimport matplotlib.pyplot as pltplt.figure(figsize=(10,10))dark_image = imageio.imread("dark.jpg")plt.subplot(1,2,1)plt.imshow(dark_image/255)plt.subplot(1,2,2)invert_image = dark_image + 60invert_image = invert_image.astype(np.uint8)plt.imshow(invert_image/255)plt.show()

然后统计一下线性变换以后的直方图:

现在,像素值不再是集中在0-50之间,而是向50-100靠拢,可是照片中窗口颜色明显失真,看来这种增强方式不可行。

所以,尝试使用了分段线性变换的方式(由于计算速度太慢,所以resize了),分段线性就是针对不同的灰度区间采取不同变换函数,选择a=(x1,y1),b=(x2,y2)两个分段点,对0-a之间和a-b之间与b-255之间,这三个不同灰度区间采用不同的变换:

# 灰度分层from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltdark_image = np.array(Image.open("dark.jpg").resize((300,450),Image.ANTIALIAS))# dark_image = np.array(Image.open("dark.jpg"))def seg_linear(dark_image,x1,y1,x2,y2):    if (x1>x2 or y1>y2):        raise ValueError("must make sure x1<x2 and y1<y2")    seg_image = np.zeros(shape=dark_image.shape, dtype=np.float32)    for i in range(dark_image.shape[2]):        for j in range(dark_image.shape[1]):            for k in range(dark_image.shape[0]):                if dark_image[k][j][i] < x1:                    seg_image[k][j][i] = (y1/x1)*dark_image[k][j][i]                elif dark_image[k][j][i] < x2:                    seg_image[k][j][i] = ((y2-y1)/(x2-x1))*(dark_image[k][j][i]-x1) + y1                else:                    seg_image[k][j][i] = ((255-y2)/(255-x2))*(dark_image[k][j][i]-x2) + y2    return seg_imageseg_image = seg_linear(dark_image,40,150,70,220)plt.figure(figsize=(10,10))plt.subplot(1,2,1)plt.imshow(dark_image/255)plt.subplot(1,2,2)plt.imshow(seg_image/255)plt.show()

获得了下面这种结果:

效果感觉还行,就是图像对比度不满意,但是这两个分段点太难选了。

统计一下直方图,发现像素值的分布在不同区间均匀了很多,这样图像的整体像素并没有全部升高,但是亮度还是增加 了不少:

最后尝试了一下采用伽马矫正,这个名字我也不是很理解,感觉就是幂函数:

代码如下:

import imageioimport numpy as npimport matplotlib.pyplot as pltplt.figure(figsize=(10,10))dark_image = imageio.imread("dark.jpg")gama_image = (dark_image.astype(np.float32)/255)**0.25plt.figure(figsize=(10,10))plt.subplot(1,2,1)plt.imshow(dark_image/255)plt.subplot(1,2,2)plt.imshow(gama_image)imageio.imsave("gama.jpg",gama_image*255)

可以调节不同的gama值,就能得到不同程度的亮度增加,直方图如下,像素值整体迁移到了更高的区间,图像的 亮度很自然的增加了:

总结一下:想增强图像的亮度有很多种方式,但是核心就是增大像素值。

标签: #增强对比度的算法