文章目錄
- 一、圖像預處理
- 17 直方圖均衡化
- 17.1繪制直方圖
- 17.2直方圖均衡化
- 1. 自適應直方圖均衡化
- 2. 對比度受限的自適應直方圖均衡化
- 3. 示例
- 19 模板匹配
一、圖像預處理
17 直方圖均衡化
- 直方圖:反映圖像像素分布的統計圖,橫坐標就是圖像像素的取值,縱坐標是該像素的個數。也就是對一張圖像中不同像素值的像素個數的統計。
- 增加對比度:黑的更黑,白的更白。
17.1繪制直方圖
就是以像素值為橫坐標,像素值的個數為縱坐標繪制一個統計圖。
-
關鍵3步
-
hist=cv2.calcHist(images, channels, mask, histSize, ranges)
-
作用
- 統計像素出現的次數
-
參數
images
:輸入圖像列表
,可以是一幅或多幅圖像(通常是灰度圖像或者彩色圖像的各個通道)。channels
:一個包含整數的列表,指示在每個圖像上計算直方圖的通道編號。如果輸入圖像是灰度圖,它的值就是[0]
;如果是彩色圖像的話,傳入的參數可以是 [0],[1],[2] 它們分別對應著通道 B,G,R。mask
(可選):掩模,非黑色區域(目標區域)參與直方圖計算的區域;None為全部計算。histSize
:一個整數列表,也就是直方圖的區間個數(BIN 的數目)。用中括號括起來,例如:[256]
。ranges
:每維數據的取值范圍,它是一個二維列表,每一維對應一個通道的最小值和最大值,例如對灰度圖像可能是[0, 256]
。
-
返回值
- hist: 是一個長度為255的數組,數組中的每個值表示圖像中對應灰度等級的像素計數
-
-
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)
-
參數:hist是上面的返回值數組
-
返回值:
- 獲取直方圖的最小值、最大值及其對應最小值的位置索引、最大值的位置索引
-
-
cv2.line(img, pt1, pt2, color, thickness)
-
img:原始圖像,即要在上面畫線的numpy數組(一般為uint8類型)。
-
pt1 和 pt2:分別為線段的起點和終點坐標,它們都是元組類型
-
color:線段的顏色
-
thickness:線段的寬度,默認值是1
-
示例:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as pltdef draw():img = cv.imread('./images/lvbo.png')# 統計像素出現的次數hist = cv.calcHist(img, [0], None, [256], [0, 256])print(hist.shape)# 獲取最大和最小值的個數 和 索引(在hist數組中)minval, maxval, minloc, maxloc = cv.minMaxLoc(hist)# 創建全黑圖像,用于繪制直方圖hist_img = np.zeros([256, 256, 3], np.uint8)for i in range(256):# 除最大值:將所有出現的個數歸一化(0~1)# 乘0.9*255:將所有個數限制在 0~0.9*255 之間h = int(hist[i].item() / maxval * (0.9*256))cv.line(hist_img,(i, 256),(i, 256-h), (255, 255, 255), 1)cv.imshow('hist', hist_img)cv.waitKey(0)cv.destroyAllWindows()
draw()
17.2直方圖均衡化
一副效果好的圖像通常在直方圖上的分布比較均勻,直方圖均衡化就是用來改善圖像的全局亮度和對比度。
- 直方圖均衡化作用:
- 增強對比度
- 提高圖像質量
1. 自適應直方圖均衡化
自適應直方圖均衡化(Adaptive Histogram Equalization, AHE),通過調整圖像像素值的分布,使得圖像的對比度和亮度得到改善。
- 語法:
- dst = cv.equalizeHist(imgGray)
- 參數:灰度圖
imgGray為需要直方圖均衡化的灰度圖,返回值為處理后的圖像
優點:方法適用于圖像的灰度分布不均勻,且灰度分布集中在更窄的范圍,圖像的細節不夠清晰且對比度較低的情況。
缺點:會出現太亮的部分,會出現特征丟失
- 示例
img = cv.imread('./images/lvbo.png')
img = cv.resize(img, (256, 256))
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
h = cv.equalizeHist(gray)
cv.imshow('gray', gray)
cv.imshow('h', h)
cv.waitKey(0)
cv.destroyAllWindows()
2. 對比度受限的自適應直方圖均衡化
很明顯,因為全局調整亮度和對比度的原因,臉部太亮,大部分細節都丟失了。自適應均衡化就是用來解決這一問題的:它在每一個小區域內(默認8×8)進行直方圖均衡化。當然,如果有噪點的話,噪點會被放大,需要對小區域內的對比度進行了限制,所以這個算法全稱叫:對比度受限的自適應直方圖均衡化(Contrast Limited Adaptive Histogram Equalization, CLAHE)。
其主要步驟為:
- 圖像分塊(Tiling):
- 圖像首先被劃分為多個不重疊的小塊(tiles)。這樣做的目的是因為在全局直方圖均衡化中,單一的直方圖無法反映圖像各個局部區域的差異性。通過局部處理,AHE能夠更好地適應圖像內部的不同光照和對比度特性。(tiles 的 大小默認是 8x8)
- 計算子區域直方圖:
- 對于每個小塊,獨立計算其內部像素的灰度直方圖。直方圖反映了該區域內像素值的分布情況。
- 子區域直方圖均衡化:
- 對每個小塊的直方圖執行直方圖均衡化操作。這涉及重新分配像素值,以便在整個小塊內更均勻地分布。均衡化過程會增加低頻像素的數量,減少高頻像素的數量,從而提高整個小塊的對比度。
- 對比度限制(Contrast Limiting):
- 如果有噪聲的話,噪聲會被放大。為了防止過大的對比度增強導致噪聲放大,出現了限制對比度自適應直方圖均衡化(CLAHE)。CLAHE會在直方圖均衡化過程中引入一個對比度限制參數。當某一小塊的直方圖在均衡化后出現極端值時,會對直方圖進行平滑處理(使用線性或非線性的鉗制函數),確保對比度增強在一個合理的范圍內。
- 重采樣和鄰域像素融合:
- 由于小塊之間是不重疊的,直接拼接經過均衡化處理的小塊會產生明顯的邊界效應。因此,在CLAHE中通常采用重采樣技術來消除這種效應,比如通過雙線性插值將相鄰小塊的均衡化結果進行平滑過渡,使最終圖像看起來更為自然和平滑。
- 合成輸出圖像:
- 將所有小塊均衡化后的結果整合在一起,得到最終的自適應直方圖均衡化后的圖像。
-
語法:
-
clahe = cv2.createCLAHE(clipLimit=None, tileGridSize=None)
-
clipLimit(可選):對比度限制參數,用于控制直方圖均衡化過程中對比度增強的程度。如果設置一個大于1的值(如2.0或4.0),CLAHE會限制對比度增強的最大程度,避免過度放大噪聲。如果不設置,OpenCV會使用一個默認值。
-
tileGridSize(可選):圖像分塊的大小,通常是一個包含兩個整數的元組,如
(8, 8)
,表示將圖像劃分成8x8的小塊進行獨立的直方圖均衡化處理。分塊大小的選擇會影響到CLAHE的效果以及處理速度。
-
-
-
創建CLAHE對象后,可以使用
.apply()
方法對圖像進行CLAHE處理:-
img=clahe.apply(image)
-
image:要均衡化的圖像。
-
img均衡后的圖像
-
-
3. 示例
import cv2 as cv
import numpy as np
# 繪制直方圖的方法
def draw(img):# 統計像素出現的次數hist = cv.calcHist([img], [0], None, [256], [0, 256])# 獲取最大和最小值的個數 和 索引(在hist數組中)minval, maxval, minloc, maxloc = cv.minMaxLoc(hist)# 創建全黑圖像,用于繪制直方圖hist_img = np.zeros([256, 256, 3], np.uint8)for i in range(256):# 除最大值:將所有出現的個數歸一化(0~1)# 乘0.9*255:將所有個數限制在 0~0.9*255 之間h = int(hist[i].item() / maxval * (0.9 * 256))cv.line(hist_img, (i, 256), (i, 256 - h), (255, 255, 255), 1)return hist_img
# 均衡化的兩個方法
def draw3():img = cv.imread('./images/zhifang.png')gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# 繪制灰度圖的直方圖hts_fray = draw(gray)# 普通的直方圖均衡化eqe = cv.equalizeHist(gray)hts_eqe = draw(eqe)# 繪制直方圖# 對比度受限的均衡化clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))img_clahe = clahe.apply(gray)hts_clahe = draw(img_clahe) # 繪制CLAHE后的直方圖cv.imshow('hts_fray', hts_fray)cv.imshow('hts_eqe', hts_eqe)cv.imshow('hts_clahe', hts_clahe)cv.waitKey(0)cv.destroyAllWindows()
draw3()
- 輸出
19 模板匹配
未完待續…