1. 全局直方圖均衡化
cv2.equalizeHist(src, dst=None)函數只能處理單通道的數據,src為輸入圖像對象矩陣,必須為單通道的uint8類型的矩陣數據。直方圖均衡化可以看作是圖像增強的一個手段,示例代碼如下:
import cv2 as cv
src = cv.imread("D:/Open CV/opencv/sources/samples/data/rice_01.jpg")
# 1. 全局直方圖均衡化
def globalEqualHist(image):
# 如果想要對圖片做均衡化,必須將圖片轉換為灰度圖像
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
dst = cv.equalizeHist(gray) # 在說明文檔中有相關的注釋與例子
# equalizeHist(src, dst=None)函數只能處理單通道的數據,src為輸入圖像對象矩陣,必須為單通道的uint8類型的矩陣數據
# dst: 輸出圖像矩陣(src的shape一樣)
cv.imshow("global equalizeHist", dst)
# print(len(image.shape)) # 彩色圖像的shape長度為3
# print(len(gray.shape)) # 灰度圖像的shape長度為2
# print(gray.shape) # 灰度圖像只有高、寬
globalEqualHist(src)
cv.imshow("original image", src)
cv.waitKey(0)
cv.destroyAllWindows()
運行效果如下:
由運行的效果圖,我們可以看出經過equalizeHist()函數的處理,圖像的對比度在全局上已經得到了增強。但是如果選擇其他的圖像,采用全局直方圖均衡化的函數就不一定能夠得到很好地效果了,例如,選擇一張帥哥的圖像做全局直方圖均衡化處理:
import cv2 as cv
import numpy as np
src = cv.imread("./images/handsomeboy01.jpg")
# 1. 全局直方圖均衡化
def globalEqualHist(image):
# 如果想要對圖片做均衡化,必須將圖片轉換為灰度圖像
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
dst = cv.equalizeHist(gray) # 在說明文檔中有相關的注釋與例子
# dst: 輸出圖像矩陣(src的shape一樣)
cv.imshow("global equalizeHist", dst)
globalEqualHist(src)
cv.imshow("original image", src)
cv.waitKey(0)
cv.destroyAllWindows()
運行效果如下:
很明顯,這種情況下經過全局的均衡化處理之后反而不是我們想要得到的圖像,因為它將圖像的關鍵部分處理的相當不清楚。所以此時,就不能利用全局均衡化了,而需要使用局部直方圖自適應均衡化。
2. 局部直方圖自適應均衡化
相比全局直方圖均衡化,自適應直方圖均衡化將圖像划分為不重疊的小塊,在每一塊進行直方圖均衡化,如果小塊內有噪聲,則影響就會很大,需要通過限制對比度來進行抑制。即通過對比度自適應直方圖均衡化。如果限制對比度的閾值設置為40,那么在圖像中像素值出現次數大於40的次數就會將大於40的部分像素點去掉,平均成其它的像素點。
示例代碼如下:
import cv2 as cv
import numpy as np
src = cv.imread("./images/handsomeboy01.jpg")
def localEqualHist(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
clahe = cv.createCLAHE(clipLimit=5, tileGridSize=(7,7))
dst = clahe.apply(gray)
cv.imshow("clahe image", dst)
globalEqualHist(src)
cv.imshow("original image", src)
cv.waitKey(0)
cv.destroyAllWindows()
此時如果選擇我們剛才的那張帥哥的圖片的話,就會出現以下效果:
此時的效果就非常的好了。
3. 直方圖比較
直方圖比較可以通過cv2中的API: cv2.HISTCMP_BHATTACHARYYA()計算兩張圖像的巴氏距離;cv2.HISTCMP_CORREL()計算圖像之間的相關性;cv2.HISTCMP_CHISQR()計算卡方。
# 直方圖比較
def create_rgb_hist(image):
h, w, c = image.shape
rgbHist = np.zeros([16*16*16, 1], np.float32)
bsize = 256/16
# enumerate() 函數可以永健一個可遍歷的數據對象(如列表、元組或字符串)組合為一個索引序列,同時列出數據以及對應的下標,一般用在for循環中。
# range()函數用於創建一個整數列表
for row in range(h):
for col in range(w):
b = image[row, col, 0]
g = image[row, col, 1]
r = image[row, col, 2]
index = np.int((b/bsize)/16*16 + (g/bsize)*16 + (r/bsize))
rgbHist[np.int(index), 0] = rgbHist[np.int(index), 0] + 1
return rgbHist
def hist_compare(image1, image2):
hist1 = create_rgb_hist(image1)
hist2 = create_rgb_hist(image2)
match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA)
match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)
match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)
print("巴氏距離: %s, 相關性: %s, 卡方: %s"%(match1, match2, match3))
cv.imshow("image1", image1)
cv.imshow("image2", image2)
image1 = cv.imread("./images/raindropGirl.jpg")
image2 = cv.imread("./images/raindropGirl01.jpg")
hist_compare(image1, image2)
cv.waitKey(0)
cv.destroyAllWindows()
運行結果如下: