數字影象處理筆記(四):灰度變換
1 - 引言
影象處理分為空間域和變換域(在影象的傅立葉變換上進行處理),空間域是指影象平面本身,主要是直接以影象中的畫素操作為基礎進行影象處理,空間域的處理主要分為灰度變換和空間濾波兩類,本文主要介紹灰度變換和空間濾波在影象增強方面的應用,使得輸出的影象比原始影象更適合特定需求的一種處理。
下面我們來介紹一下經典的灰度變換和空間濾波技術。
2 - 一些基本的灰度變換函式
灰度變換是所有影象處理技術中最簡單的技術。r和s 分別代表處理前後的畫素值。
2.1 - 影象反轉
使用這種方式反轉一副影象的灰度級,可得到等效的照片底片,這種型別的處理特別使用於增強嵌入在一副影象的暗區域中的白色和灰色細節,特別是當黑色面積在尺寸上占主導地位時。
import numpy as np import cv2 as cv image = cv.imread('images/timg.jpg') cv.imshow("imshow_", image) shape = image.shape height = shape[0] width = shape[1] channels = shape[2] for row in range(height): for col in range(width): for cn in range(channels): """獲取image單個畫素點的某個通道,順序是BGR""" pv = image[row, col, cn] """255-原本的顏色就變成了反色""" image[row, col, cn] = 255 - pv cv.imshow("imshow_inverse", image) cv.waitKey(0)
2.2 - 對數變換
對數變換的通用形式為
我們使用這種型別的變換來擴充套件影象中的暗畫素值,同時壓縮更高灰度級的值(反對數變換相反)。
主要有兩個作用
-
因為對數曲線在畫素值較低的區域斜率較大,畫素值較高的區域斜率比較低,所以影象經過對數變換之後,在較暗的區域對比度將得到提升,因而能增強影象暗部的細節。
-
影象的傅立葉頻譜其動態範圍可能寬達 。直接顯示頻譜的話顯示裝置的動態範圍往往不能滿足要求,這個時候就需要使用對數變換,使得傅立葉頻譜的動態範圍被合理地非線性壓縮。
import numpy as np
import cv2 as cv
image = cv.imread('images/16.jpg')
cv.imshow("imshow_", image)
shape = image.shape
height = shape[0]
width = shape[1]
channels = shape[2]
for row in range(height):
for col in range(width):
for cn in range(channels):
"""獲取image單個畫素點的某個通道,順序是BGR"""
pv = image[row, col, cn]
"""使用對數變換可以顯示影象黑暗中的細節"""
image[row, col, cn]= 32*np.log10(1+pv)
cv.imshow("image_log", image)
cv.waitKey(0)
可以看到影象中隱藏在黑暗中的細節被展示了出來
2.3 - 冪律(伽馬)變換
冪律變換的基本形式為:
與對數變換的情況類似,部分
值的冪律曲線將較窄範圍的暗色輸入對映為較寬範圍的輸出值,相反地,對於輸入高灰度級值也成立。然而,與對數函式不同的是,我們注意到,隨著
值的變化,將簡單的得到一族可能的變換曲線。
例 1 使用冪律變換進行對比度增強
當影象整體偏暗的時候,需要擴充套件活度計,可以使用指數為分數的冪律來變換完成。
import numpy as np
import cv2 as cv
image = cv.imread('images/gamma.jpg')
cv.imshow("imshow_", image)
shape = image.shape
height = shape[0]
width = shape[1]
channels = shape[2]
for row in range(height):
for col in range(width):
for cn in range(channels):
"""獲取image單個畫素點的某個通道,順序是BGR"""
pv = image[row, col, cn]
"""使用冪律可以顯示影象黑暗中的細節"""
image[row, col, cn] = 5*np.power(pv,0.6)
cv.imshow("image_gamma", image)
cv.waitKey(0)
例 2 矯正曝光度過高的圖片
當伽馬值取大於1的時候,可以壓縮灰度級。
import numpy as np
import cv2 as cv
image = cv.imread('images/gamma+2.jpg')
cv.imshow("imshow_", image)
shape = image.shape
height = shape[0]
width = shape[1]
channels = shape[2]
for row in range(height):
for col in range(width):
for cn in range(channels):
"""獲取image單個畫素點的某個通道,順序是BGR"""
pv = image[row, col, cn]
"""先使用歸一化,再使用冪律可以顯示影象黑暗中的細節"""
image[row, col, cn] = np.power(pv/255,4)*255
cv.imshow("image_gamma", image)
cv.waitKey(0)
2.4 - 分段線性變換函式
通過分段線性函式我們可以將我們感興趣的灰度值突顯出來
2.4.1 - 對比度拉伸
通過分段函式來輸出不同程度的灰度級擴充套件,從而來影響輸出影象的對比度。
其變換公式為:
我們假設函式為:
g(x,y) = a*f(x,y)+b
- f(x,y)代表源影象x行,y列的畫素點的c通道的數值 g(x,y)代表目
- 標影象x行,y列的畫素點的c通道的數值
- a引數(a>0)表示放大的倍數(一般在0.0~3.0之間)
- b引數一般稱為偏置,用來調節亮度
import numpy as np
import cv2 as cv
a = 3
b = 10
image = cv.imread('images/test_1.jpg')
cv.imshow("imshow_", image)
shape = image.shape
height = shape[0]
width = shape[1]
channels = shape[2]
for row in range(height):
for col in range(width):
for cn in range(channels):
"""獲取image單個畫素點的某個通道,順序是BGR"""
pv = image[row, col, cn]
"""先使用歸一化,再使用冪律可以顯示影象黑暗中的細節"""
image[row, col, cn] = (pv/255*a+b)*255
cv.imshow("image_gamma", image)
cv.waitKey(0)
2.4.2 - 灰度級分層
突出影象中特定灰度範圍的亮度通常是重要的,其應用包括增強特徵。
例如一副靠近腎臟區域的大動脈血管造影照片,我們關注的是血管部分,我們使用灰度級分層來突出主要血管,使其更亮一些。
import numpy as np
import cv2 as cv
a = 3
b = 10
image = cv.imread('images/test_2.jpg')
cv.imshow("image",image)
shape = image.shape
height = shape[0]
width = shape[1]
channels = shape[2]
for row in range(height):
for col in range(width):
for cn in range(channels):
"""獲取image單個畫素點的某個通道,順序是BGR"""
pv = image[row, col, cn]
if pv > 120:
pv = 255
image[row, col, cn] = pv
else:
pv = 30
image[row, col, cn] = pv
cv.imshow("image_gamma", image)
cv.waitKey(0)
2.4.3 - 位元平面分層
(0~2)對應第1位元層,
(2~4)對應第2位元層,
(4~8)對應第3位元層,
(8~16)對應第4位元層,
(16~32)對應第5位元層,
(32~64)對應第6位元層,
(64~128)對應第7位元層,
(128~256)對應第8位元層。
若影象存在對應位元層的灰度值,畫素值賦值為255(白),不在該範圍內,賦值
import numpy as np
import cv2 as cv
a = 3
b = 10
image = cv.imread('images/lena.jpg')
shape = image.shape
height = shape[0]
width = shape[1]
channels = shape[2]
for row in range(height):
for col in range(width):
for cn in range(channels):
"""獲取image單個畫素點的某個通道,順序是BGR"""
pv = image[row, col, cn]
#分離位元層,從0~8層
if pv > np.power(2,7) and pv < np.power(2,8):
pv = 255
image[row, col, cn] = pv
else:
pv = 0
image[row, col, cn] = pv
cv.imshow("image_gamma", image)
cv.waitKey(0)
原始影象:
第1至4層:
第4至8層: