1.概述¶
伽瑪變換又名指數變換、冪次變換或冪律變換,是另一種常用的非線性變換
伽馬變換主要用於圖像的校正,將灰度過高或者灰度過低的圖片進行修正,增強對比度。變換公式就是對原圖像上每一個像素值做乘積運算:
其中 c 和 γ 為正常數,有時考慮到偏移量,也將表達式寫為:
與對數變換不同,伽瑪變換可以根據 $\gamma$ 的不同取值選擇性地增強低灰度區域的對比度或是高灰度區域的對比度。$\gamma$是圖像灰度校正中非常重要的一個參數,其取值決定了輸入圖像和輸出圖像之間的灰度映射方式,即決定了是增強低灰度( 陰影區域)還是增強高灰度(高亮區域)。其中:

- $ \gamma $ > 1 時,圖像的高灰度區城對比度得到增強
- $ \gamma $ < 1 時,圖像的低灰度區城對比度得到增強
- $ \gamma $ = 1 時,圖像是線性變換,對比度保持不變
針對於數字圖像處理,我們可以將公式寫為:
由於冪運算值域變化范圍可能太大,對於當前主要的8 bit顯示器,我們采用歸一化手段:
2. 補償系數的作用¶
導入庫:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
定義伽馬變換函數:
def gamma_trans(input, gamma=2, eps=0 ):
return 255. * (((input + eps)/255.) ** gamma)
測試補償系數為0時的效果:
input_arr = np.array( [ [0, 50, 100, 150],
[0, 50, 100, 150],
[0, 50, 100, 150],
[0, 50, 100, 150]] )
fig = plt.figure()
ax0 = fig.add_subplot(221)
ax0.set_title("input")
ax0.imshow(input_arr, cmap='gray',vmin=0,vmax=255)
gamma = 0.25
output = gamma_trans(input_arr, gamma=gamma, eps=0)
ax1 = fig.add_subplot(222)
ax1.set_title("output, gamma = " + str(gamma))
ax1.imshow(output, cmap='gray', vmin=0, vmax=255)
gamma = 0.75
output = gamma_trans(input_arr, gamma=gamma, eps=0)
ax1 = fig.add_subplot(223)
ax1.set_title("output, gamma = " + str(gamma))
ax1.imshow(output, cmap='gray', vmin=0, vmax=255)
gamma = 1.5
output = gamma_trans(input_arr, gamma=gamma, eps=0)
ax1 = fig.add_subplot(224)
ax1.set_title("output, gamma = " + str(gamma))
ax1.imshow(output, cmap='gray', vmin=0, vmax=255)
print(output)
plt.show()
[[ 0. 22.14037214 62.62242911 115.04474833]
[ 0. 22.14037214 62.62242911 115.04474833]
[ 0. 22.14037214 62.62242911 115.04474833]
[ 0. 22.14037214 62.62242911 115.04474833]]
由圖可以看到,如果補償系數 $\epsilon = 0$,則灰度等於0的區域將不會產生任何變化,我們添加一個補償系數$\epsilon = 0.5$:
input_arr = np.array( [ [0, 50, 100, 150],
[0, 50, 100, 150],
[0, 50, 100, 150],
[0, 50, 100, 150]] )
fig = plt.figure()
ax0 = fig.add_subplot(221)
ax0.set_title("input")
ax0.imshow(input_arr, cmap='gray',vmin=0,vmax=255)
gamma = 0.25
output = gamma_trans(input_arr, gamma=gamma, eps=0.5)
ax1 = fig.add_subplot(222)
ax1.set_title("output, gamma = " + str(gamma))
ax1.imshow(output, cmap='gray', vmin=0, vmax=255)
gamma = 0.75
output = gamma_trans(input_arr, gamma=gamma, eps=0.5)
ax1 = fig.add_subplot(223)
ax1.set_title("output, gamma = " + str(gamma))
ax1.imshow(output, cmap='gray', vmin=0, vmax=255)
gamma = 1.5
output = gamma_trans(input_arr, gamma=gamma, eps=0.5)
ax1 = fig.add_subplot(224)
ax1.set_title("output, gamma = " + str(gamma))
ax1.imshow(output, cmap='gray', vmin=0, vmax=255)
print(output)
plt.show()
[[2.21403721e-02 2.24733066e+01 6.30926839e+01 1.15620451e+02]
[2.21403721e-02 2.24733066e+01 6.30926839e+01 1.15620451e+02]
[2.21403721e-02 2.24733066e+01 6.30926839e+01 1.15620451e+02]
[2.21403721e-02 2.24733066e+01 6.30926839e+01 1.15620451e+02]]
可以看到整體的對比度都有變化,灰度值為0的問題可以避免
3. 伽馬變換矯正顯示失真¶
老式電視機CRT會有顯示失真的問題,不同的電視有不同的失真指數 我們假設某老式電視失真指數$\gamma = 0.5$,我們使用伽馬變換進行矯正,只需取矯正指數$\gamma ' = \frac{1}{\gamma}$
原圖像:
gray_img = np.asarray(Image.open('./img/intensity_ramp.tif').convert('L'))
fig = plt.figure()
ax0 = fig.add_subplot()
ax0.set_title("origin")
ax0.imshow(gray_img, cmap='gray',vmin=0,vmax=255)
plt.show()
失真圖像和伽馬矯正:
gray_img = np.asarray(Image.open('./img/intensity_ramp.tif').convert('L'))
fig = plt.figure()
ax0 = fig.add_subplot(131)
ax1 = fig.add_subplot(132)
ax2 = fig.add_subplot(133)
gamma=0.5
ax0.set_title("origin")
ax0.imshow(gray_img, cmap='gray',vmin=0,vmax=255)
ax1.set_title("distortion")
distortion = gamma_trans(gray_img, gamma=gamma, eps=0)
ax1.imshow(distortion, cmap='gray',vmin=0,vmax=255)
ax2.set_title("correct")
correct = gamma_trans(distortion, gamma=1/gamma, eps=0)
ax2.imshow(correct, cmap='gray',vmin=0,vmax=255)
plt.show()
此處看起來是脫褲子放屁多此一舉,但是實際中失真指數是不知道的,需要去得到矯正指數
4. 伽馬變換拉伸對比度¶
對於暗色照片,我們可以進行伽馬系數小於一的伽馬變換從而提高低灰度值的對比度
原圖像:
gray_img = np.asarray(Image.open('./img/fractured_spine.tif').convert('L'))
fig = plt.figure()
ax0 = fig.add_subplot()
ax0.set_title("origin")
ax0.imshow(gray_img, cmap='gray',vmin=0,vmax=255)
plt.show()
伽馬變換:
gray_img = np.asarray(Image.open('./img/fractured_spine.tif').convert('L'))
fig = plt.figure()
ax0 = fig.add_subplot(121)
ax1 = fig.add_subplot(122)
gamma=0.4
ax0.set_title("origin")
ax0.imshow(gray_img, cmap='gray',vmin=0,vmax=255)
ax1.set_title("correct")
correct = gamma_trans(gray_img, gamma=gamma, eps=0)
ax1.imshow(correct, cmap='gray',vmin=0,vmax=255)
plt.show()
- 注意此處的伽馬系數0.4是一種探索得出的數字,不一定是最佳值,下面的2.0同理
對於亮色照片,我們可以進行伽馬系數大於一的伽馬變換從而提高低灰度值的對比度
原圖像:
gray_img = np.asarray(Image.open('./img/washed_out.tif').convert('L'))
fig = plt.figure()
ax0 = fig.add_subplot()
ax0.set_title("origin")
ax0.imshow(gray_img, cmap='gray',vmin=0,vmax=255)
plt.show()
伽馬變換:
gray_img = np.asarray(Image.open('./img/washed_out.tif').convert('L'))
fig = plt.figure()
ax0 = fig.add_subplot(121)
ax1 = fig.add_subplot(122)
gamma = 2.0
ax0.set_title("origin")
ax0.imshow(gray_img, cmap='gray',vmin=0,vmax=255)
ax1.set_title("correct")
correct = gamma_trans(gray_img, gamma=gamma, eps=0)
ax1.imshow(correct, cmap='gray',vmin=0,vmax=255)
plt.show()
可以看到伽馬變換帶來的圖像增強效果還是顯著的
