图像分段线性变化_暗光也清晰的图像增强算法
個人學習筆記:像素反轉、伽馬矯正、對數變換、線性變換、分段變換。
某天跑完步以后拍出了這樣一張照片,由于晚上開閃光不太好,所以想自己處理一下(為了更好的看出處理效果,所以采用尺寸較大的原圖像,沒有進行尺寸縮小):
在光線較暗的情況下拍攝的圖像整體的灰度值偏低,可以從直方圖中很直接的看出,圖像的像素值都分布在50以內(直方圖就是統計圖像中0-255這256個級別對應的像素值個數,比如圖像有1000個像素點,像素值為0的有10個,值為1的有5個。。。。值為255的有3個)像素值很多都接近于0并且少部分分布在100-255之間。
這里并沒有對RGB三個通道分別進行統計,而是將RGB轉為灰度圖再進行統計(我會在另外的文章中單獨的介紹直方圖和直方圖均衡算法)。
import imageio import matplotlib.pyplot as plt import numpy as npdef rgb2gray(rgb):gray = rgb[:, :, 0] * 0.299 + rgb[:, :, 1] * 0.587 + rgb[:, :, 2] * 0.114gray = gray.astype(np.uint8)return graydef get_histgram(image, nums=256):"""calculate histgram of a gray imageArgs:image:gray imagenums:pixel grade, defualt is 256Return: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] = 0for i in range(0, h):for j in range(0, w):hist[image[i][j]] += 1return 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 + b import imageio import numpy as np import matplotlib.pyplot as plt plt.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 + 60 invert_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 Image import numpy as np import matplotlib.pyplot as plt dark_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) + y1else:seg_image[k][j][i] = ((255-y2)/(255-x2))*(dark_image[k][j][i]-x2) + y2return seg_image seg_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 imageio import numpy as np import matplotlib.pyplot as plt plt.figure(figsize=(10,10)) dark_image = imageio.imread("dark.jpg") gama_image = (dark_image.astype(np.float32)/255)**0.25 plt.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值,就能得到不同程度的亮度增加,直方圖如下,像素值整體遷移到了更高的區間,圖像的 亮度很自然的增加了:
總結一下:想增強圖像的亮度有很多種方式,但是核心就是增大像素值。
總結
以上是生活随笔為你收集整理的图像分段线性变化_暗光也清晰的图像增强算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: layui遍历json数组_shell脚
- 下一篇: tta部署_YOLOv5项目介绍