前言:
Hello大家好,我是Dream。 均衡化是數字圖像處理中常用的一種技術,用于增強圖像的視覺效果和對比度。,今天我們將實現對同一張圖像的直方圖均衡化
和自適應直方圖均衡化
處理,學習一下兩者的的基本原理和實現過程,一起來看看吧~
一、直方圖均衡化
直方圖均衡化(Histogram Equalization)是一種圖像處理技術,通過重新分配圖像灰度級別來增強圖像的對比度和視覺效果。它基于整個
圖像的灰度直方圖來調整像素的灰度值分布。通過增加較暗區域的亮度和減少較亮區域的亮度
,直方圖均衡化可以使圖像的灰度級別分布更均勻
,從而增強圖像的細節和對比度。
1.得到灰度圖
通過三同道的彩色圖生成單通道的灰度圖
首先,我們使用PIL庫中的Image.open()
函數讀取彩色圖像,并將其轉換為數組。然后,我們獲取圖像的高度和寬度,并創建一個與原始圖像大小相同、數據類型為uint8
的全黑數組gray_img
,用于保存灰度圖像。
接著,我們遍歷每個像素,將三個通道的值求平均,并將結果保存到灰度圖像中。由于RGB圖像的三個通道具有相同的權重,因此將三個通道的值求平均可以得到一個比較準確的灰度值。
然后,我們將灰度圖像轉換為PIL圖像對象,并使用Matplotlib庫中的plt.imshow()
函數顯示彩色圖像和灰度圖像。最后,我們使用PIL庫中的Image.save()
函數將灰度圖像保存為文件。
import numpy as np
import cv2
from PIL import Image
import matplotlib.pyplot as plt# 讀取彩色圖像
img = Image.open('image.jpg')# 將圖像轉換為數組
img_arr = np.array(img)# 獲取圖像的高度和寬度
h, w, _ = img_arr.shape# 創建一個新的數組,用于保存灰度圖像
gray_img = np.zeros((h, w), dtype=np.uint8)# 遍歷每個像素,將三個通道的值求平均,并保存到灰度圖像中
for i in range(h):for j in range(w):gray_img[i, j] = int(np.mean(img_arr[i, j]))# 將灰度圖像轉換為PIL圖像對象
gray_pil_img = Image.fromarray(gray_img)
plt.imshow(img)
plt.title('imge')
plt.axis('off')
plt.show()
plt.imshow(gray_pil_img, cmap='gray')
plt.title('gray_pil_imge')
plt.axis('off')
plt.show()
# 保存灰度圖像
gray_pil_img.save('gray_image.jpg')
2. 直方圖統計
使用PIL庫中的Image.open()
函數讀取灰度圖像,并使用convert('L')
方法將圖像轉換為灰度模式。然后,我們獲取圖像的寬度和高度,并創建一個長度為256的全0列表hist
,用于保存直方圖統計結果。
接著,遍歷每個像素,獲取其灰度值,并將對應的直方圖計數器加1。最后,我們輸出直方圖統計結果,即每個灰度值出現的像素數。
# 讀取灰度圖像
gray_img = Image.open('gray_image.jpg').convert('L')
width, height = gray_img.size# 統計直方圖
hist = [0] * 256
for y in range(height):for x in range(width):pixel = gray_img.getpixel((x, y))hist[pixel] += 1
print(hist)
# 輸出直方圖統計結果
for i in range(len(hist)):print("灰度值 %d: %d 個像素" % (i, hist[i]))
3. 繪制直方圖
# 繪制直方圖
plt.bar(range(256), hist)
plt.show()
4. 直方圖均衡化
使圖片有更好的視覺效果,有更高的對比度,即像素的灰度分布更平均
首先,我們使用PIL庫中的histogram()
函數對灰度圖像進行直方圖統計,得到一個長度為256的列表equ_img
,其中每個元素表示對應灰度級別的像素數量。
接著,我們創建一個空列表lut
,用于保存灰度級別的映射表。然后,通過遍歷equ_img
列表,將每個灰度級別的像素數量除以255得到一個步長step
,表示每個灰度級別在均衡化后的直方圖中所占的比例。接下來,我們定義一個變量n
,初始化為0,用于記錄當前累積的像素數量。
在內層循環中,我們遍歷256個灰度級別,并將當前累積的像素數量除以步長step
得到一個映射值n / step
。這個映射值表示當前灰度級別在均衡化后的直方圖中所對應的灰度級別。
最后,我們使用PIL庫中的point()
方法,根據映射表lut
將灰度圖像進行映射,得到均衡化后的圖像equ_img
。在這里,lut
列表中的值被用作灰度級別的映射,'L'
參數表示輸出圖像的模式為灰度模式。
這樣,經過直方圖均衡化處理后,圖像的灰度分布將更加均勻,增強了圖像的對比度和細節。
# 直方圖均衡化
equ_img = gray_img.histogram()
lut = []
for b in range(0, len(equ_img), 256):step = sum(equ_img[b:b+256]) / 255n = 0for i in range(256):lut.append(n / step)n += equ_img[b+i]
equ_img = gray_img.point(lut, 'L')# 顯示原始圖像和均衡化后的圖像
plt.imshow(gray_img, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.show()plt.imshow(equ_img, cmap='gray')
plt.title('Equalized Image')
plt.axis('off')
plt.show()# 保存原始圖像和均衡化后的圖像
gray_img.save('Original.jpg')
equ_img.save('Equalized.jpg')# 統計均衡化后的直方圖
hist_equ = equ_img.histogram()# 繪制均衡化前后的直方圖
plt.hist(gray_img.histogram(), 256, [0, 256])
plt.title('Original Image')
plt.xlim([0, 256])
plt.show()plt.hist(hist_equ, 256, [0, 256])
plt.title('Equalized Image')
plt.xlim([0, 256])
plt.show()
二、自適應直方圖均衡化
自適應直方圖均衡化(Adaptive Histogram Equalization)是直方圖均衡化的一種變體,它考慮到圖像中不同區域的局部差異。與直方圖均衡化不同,自適應直方圖均衡化將圖像分成多個小塊
,并在每個小塊內獨立地應用直方圖均衡化
。通過這種方式,自適應直方圖均衡化可以更好地保留圖像的細節,并避免過度增強噪聲
。自適應直方圖均衡化可以根據圖像的局部特征自動調整每個小塊的灰度級別
,以實現更精細的圖像增強。
1.自適應直方圖均衡化(AHE)
AHE是一種局部直方圖均衡化方法,它將圖像分成若干個小區域,對每個小區域進行直方圖均衡化處理,從而增強圖像的對比度。該算法的核心思想是在每個小區域內計算直方圖,并將其變換為累積分布函數(CDF),然后將CDF拉伸以增加對比度。因此,AHE可以有效地增強圖像中的局部細節信息。
在此處,我們的輸入參數包括原始圖像img
和窗口大小window_size
。首先,函數遍歷每個像素,獲取以該像素為中心的大小為window_size
的窗口。如果窗口越界,則跳過該像素。然后,計算窗口的直方圖,并計算其累積分布函數。接著,將CDF歸一化并拉伸,以增加窗口內像素的對比度。最后,將均衡化后的像素值放回原圖中,得到均衡化后的結果。
# 自適應直方圖均衡化(AHE)
def adaptive_histogram_equalization(img, window_size):# 獲取圖像大小height, width = img.shape[:2]# 創建一個全黑的圖像result = np.zeros((height, width), dtype=np.uint8)# 遍歷每個像素for i in range(height):for j in range(width):# 獲取窗口中心點center_x, center_y = i + window_size // 2, j + window_size // 2# 如果窗口越界,則跳過if center_x < window_size // 2 or center_x >= height - window_size // 2 or center_y < window_size // 2 or center_y >= width - window_size // 2:continue# 獲取窗口window = img[center_x - window_size // 2:center_x + window_size // 2 + 1, center_y - window_size // 2:center_y + window_size // 2 + 1]# 計算窗口的直方圖hist, _ = np.histogram(window.ravel(), 256, [0, 256])# 計算累積分布函數cdf = hist.cumsum()# 歸一化cdf_normalized = cdf * 255 / cdf[-1]# 將均衡化后的像素值放回原圖中result[i][j] = cdf_normalized[img[i][j]]return result
2.限制對比度自適應直方圖均衡化(CRHE)
CRHE是在AHE的基礎上增加了對比度限制。它通過在AHE之后對像素值進行限制,以避免過度增加對比度而導致噪聲的出現。該算法的核心思想是先使用AHE增強圖像的對比度,然后使用限制對比度的方法對像素值進行截斷,從而控制對比度的增加。
在代碼中,輸入參數包括原始圖像img
、窗口大小window_size
和對比度限制因子clip_limit
。首先,調用自己實現的自適應直方圖均衡化函數adaptive_histogram_equalization
對原始圖像進行直方圖均衡化處理,得到均衡化后的結果。接著,使用OpenCV庫中的cv2.createCLAHE
函數創建一個限制對比度的CLAHE對象,并將均衡化后的圖像作為輸入進行處理。
# 限制對比度自適應直方圖均衡化(CRHE)
def contrast_limited_adaptive_histogram_equalization(img, window_size, clip_limit):# 使用自己實現的自適應直方圖均衡化ahe_img = adaptive_histogram_equalization(img, window_size)# 使用OpenCV庫實現限制對比度自適應直方圖均衡化clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(window_size, window_size))result = clahe.apply(ahe_img)return result
3.讀取圖片
# 讀取圖片
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)
4.自適應直方圖均衡化
首先創建一個與原始圖像img
相同大小的全黑圖像ahe_result
,用于保存處理后的結果。然后,使用一個循環遍歷多個窗口尺寸,依次調用自適應直方圖均衡化函數adaptive_histogram_equalization
對原始圖像進行處理,并將處理后的結果加到ahe_result
中。最后得到多個尺寸的均衡化結果的平均值,作為最終的均衡化結果。
我們使用了不同尺寸的窗口,分別為50、100、150和200。最后將這四個結果取平均值作為最終結果,這種方法可以提高均衡化的效果,因為不同尺寸的窗口可以捕捉到圖像中不同尺度的局部細節信息,從而增強圖像的對比度和細節信息,避免過大或過小的窗口對結果產生較大影響。
# 自適應直方圖均衡化
# 創建一個和原始圖像大小相同的全零數組ahe_result,用于存儲最終的自適應直方圖均衡化結果ahe_result = np.zeros_like(img)# 遍歷不同的窗口大小,從50到200,步長為50
for window_size in range(50, 201, 50):# 對原始圖像img進行自適應直方圖均衡化操作,使用當前窗口大小window_sizeahe_img = adaptive_histogram_equalization(img, window_size)# 將每次處理后的圖像ahe_img累加到ahe_result中ahe_result += ahe_img# 將ahe_result除以4取整,得到最終的自適應直方圖均衡化結果
ahe_result //= 4
5.限制對比度自適應直方圖均衡化
首先創建一個與原始圖像img
相同大小的全黑圖像crhe_result
,用于保存處理后的結果。然后,使用一個循環遍歷多個窗口尺寸,依次調用限制對比度自適應直方圖均衡化函數對原始圖像進行處理,并將處理后的結果加到crhe_result
中。在本例中,設置對比度限制因子clip_limit
為2.0。
我們使用了不同尺寸的窗口,分別為50、100、150和200。最后將這四個結果取平均值作為最終結果,避免過大或過小的窗口對結果產生較大影響。
# 限制對比度自適應直方圖均衡化
# 創建一個和原始圖像大小相同的全零數組crhe_result,用于存儲最終的限制對比度自適應直方圖均衡化結果crhe_result = np.zeros_like(img)# 遍歷不同的窗口大小,從50到200,步長為50
for window_size in range(50, 201, 50):# 對原始圖像img進行限制對比度自適應直方圖均衡化操作,使用當前窗口大小window_size和對比度限制參數2.0crhe_img = contrast_limited_adaptive_histogram_equalization(img, window_size, 2.0)# 將每次處理后的圖像crhe_img累加到crhe_result中crhe_result += crhe_img# 將crhe_result除以4取整,得到最終的限制對比度自適應直方圖均衡化結果
crhe_result //= 4
6.可視化顯示結果
# 顯示結果
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(12, 8))
ax[0].imshow(img, cmap='gray')
ax[0].set_title('Original1 Image')
ax[1].imshow(ahe_result, cmap='gray')
ax[1].set_title('AHE1 Image')
ax[2].imshow(crhe_result, cmap='gray')
ax[2].set_title('CRHE1 Image')
plt.show()
三、對比總結
直方圖均衡化(Histogram Equalization)和自適應直方圖均衡化(Adaptive Histogram Equalization)都是用于圖像增強的技術
,目的是改善圖像的對比度和視覺效果
。它們的主要區別在于處理圖像的方式和局部性。
直方圖均衡化是一種全局
的方法,它基于整個圖像的灰度直方圖來調整像素的灰度值分布
。通過使灰度級別在圖像中更均勻地分布,直方圖均衡化可以增強圖像的對比度和細節。它使用累積分布函數將原始圖像中的灰度級別映射到一個新的灰度范圍,從而實現圖像的均衡化。
然而,直方圖均衡化是一種全局的方法,它沒有考慮到圖像中不同區域的局部差異。這可能會導致圖像的某些區域過度增強或細節丟失的問題。為了解決這個問題,自適應直方圖均衡化應運而生。
自適應直方圖均衡化是一種局部
的方法,在處理圖像時會考慮到不同區域的灰度分布情況
。它將圖像分成許多小區域,對每個區域獨立地應用直方圖均衡化。通過這種方式,自適應直方圖均衡化可以更好地保留圖像細節,并避免過度放大噪聲。
自適應直方圖均衡化的一種常見變體是自適應直方圖均衡化(CLAHE),它在每個小區域中使用對比度限制來防止過度放大噪聲。CLAHE的核心思想是將圖像分成許多小塊,然后對每個小塊進行局部直方圖均衡化,并對像素值進行裁剪以限制對比度的增強程度。通過這種方式,CLAHE在增強圖像細節的同時有效控制了噪聲的增強。
總而言之,直方圖均衡化是一種全局的方法,通過整個圖像的灰度直方圖來增強圖像對比度。 而 自適應直方圖均衡化是一種局部的方法,通過對圖像的小塊進行獨立的直方圖均衡化來增強圖像,并通過對比度限制來控制噪聲的放大。