為了得到更加清晰的圖像我們需要通過技術對圖像進行處理,比如使用對比度增強的方法來處理圖像,對比度增強就是對圖像輸出的灰度級放大到指定的程度,獲得圖像質量的提升。本文主要通過代碼的方式,通過OpenCV的內置函數將圖像處理到我們理想的結果。
灰度直方圖###
灰度直方圖通過描述灰度級在圖像矩陣中的像素個數來展示圖像灰度級的信息,通過灰度直方圖的統計我們可以看到每個灰度值的占有率。下面是一個灰度直方圖的實現:
import cv2
import numpy as np
import sys
import matplotlib.pyplot as plt
#計算灰度直方圖
def calcGrayHist(image):
rows,clos = image.shape
#創建一個矩陣用於存儲灰度值
grahHist = np.zeros([256],np.uint64)
print('這是初始化矩陣')
print(grahHist )
for r in range(rows):
for c in range(clos):
#通過圖像矩陣的遍歷來將灰度值信息放入我們定義的矩陣中
grahHist[image[r][c]] +=1
print('這是賦值后的矩陣')
print(grahHist)
return grahHist
if __name__=="__main__":
image = cv2.imread("../img/aa.jpg",cv2.IMREAD_GRAYSCALE)
grahHist = calcGrayHist(image)
x_range = range(256)
plt.plot(x_range,grahHist,'-',linewidth= 3,c='k')
#設置坐標軸的范圍
y_maxValue = np.max(grahHist)
plt.axis([0,255,0,y_maxValue])
#設置標簽
plt.xlabel('gray Level')
plt.ylabel("number of pixels")
#顯示灰度直方圖
plt.show()
運行結果
線性變換###
線性變換的公式為:
圖像的線性變換無疑就是利用矩陣的乘法就行線性變換,比如一個矩陣I ,2I,3I (np.unt8 ndarry類型就是unt8類型)就是一個矩陣的變換.
import cv2
import numpy as np
import sys
if __name__=="__main__":
img = cv2.imread("../img/ae.jpg",cv2.IMREAD_GRAYSCALE)
a=2
#線性變換 定義float類型
O = float(a)*img
#數據截取 如果大於255 取 255
O[0>255] = 255
#數據類型的轉換
O = np.round(O)
O = O.astype(np.uint8)
cv2.imshow("img",img)
cv2.imshow('enhance',O)
cv2.waitKey(0)
cv2.destroyAllWindows()
運行結果:
灰度級范圍越大就代表對比度越高,反之對比度越低視覺上清晰度就越低。我們通過a=2的線性對比度拉伸將灰度級范圍擴大到[0,255]之間,如上圖我們改變灰度級的范圍后圖像變的清晰。
直方圖正規化###
將圖像O中的最小灰度級記為\(O_{min}\),最大灰度級記為\(O_{max}\),假如輸出的圖像P的灰度級范圍為[\(P_{min},P_{max}\)],則O 與 P的關系為:
其中P(r,c)就代表P的第r行第c列的灰度值。這個過程就是直方圖的正規化。我們一般令P的范圍是[0,255],所以直方圖的正規化是在求a,b變換的值的方法,我們可以得到:
下面我們使用OpenCV來實現上面的理論:
import cv2
import numpy as np
import sys
from enhance.GrayHist import mget
if __name__=="__main__":
img = cv2.imread("../img/o3.jpg",cv2.IMREAD_GRAYSCALE)
#求出img 的最大最小值
Maximg = np.max(img)
Minimg = np.min(img)
print(Maximg, Minimg, '-----------')
#輸出最小灰度級和最大灰度級
Omin,Omax = 0,255
#求 a, b
a = float(Omax - Omin)/(Maximg - Minimg)
b = Omin - a*Minimg
print(a,b,'-----------')
#線性變換
O = a*img + b
O = O.astype(np.uint8)
#利用灰度直方圖進行比較 mget為GrayHist中的寫方法
mget(img)
mget(O)
cv2.imshow('img',img)
cv2.imshow('enhance',O)
cv2.waitKey(0)
cv2.destroyAllWindows()
伽瑪變換###
將一張圖的灰度值歸至[0,1]后,對於8位圖來說,除以255即可。伽瑪變換就是令O(r,c)=\(I(r,c)^\gamma\),0\(\leq r<H,0\leq\)c<W.
當\(\gamma\)等於1時圖像不發生變換,而當\(\gamma\)大於0且小於1時就可以增強圖像的對比度,相反的當\(\gamma\)大於1時就可以使圖像對比度降低。 以下是伽瑪變換在OpenCV中的實現:
import cv2
import numpy as np
import sys
# 伽瑪變換 power函數實現冪函數
if __name__ == "__main__":
img = cv2.imread("../img/ae.jpg", cv2.IMREAD_GRAYSCALE)
# 歸1
Cimg = img / 255
# 伽瑪變換
gamma = 0.5
O = np.power(Cimg,gamma)
#效果
cv2.imshow('img',img)
cv2.imshow('O',O)
cv2.waitKey(0)
cv2.destroyAllWindows()
運行結果:
直方圖的均衡化###
- 計算圖像的灰度直方圖
- 計算灰度直方圖的累加直方圖
- 根據累加的直方圖和直方圖均衡化的原理得到輸入灰度級與輸出灰度級之間的映射關系
- 使用循環的方式得到輸出圖像的每一個像素的灰度級
import cv2
import numpy as np
from enhance.GrayHist import calcGrayHist
#直方圖的均衡化
if __name__ == "__main__":
image = cv2.imread("../img/ae.jpg", cv2.IMREAD_GRAYSCALE)
rows,cols = image.shape
#計算灰度直方圖
grayHist = calcGrayHist(image)
#計算累加灰度直方圖
zeroCumuMoment = np.zeros([256], np.uint32)
for p in range(256):
if p == 0:
zeroCumuMoment[p] = grayHist[0]
else:
zeroCumuMoment[p] = zeroCumuMoment[p-1] + grayHist[p]
#根據累加的灰度直方圖得到輸入與輸出灰度級之間的映射關系
output = np.zeros([256],np.uint8)
cofficient = 256.0/(rows*cols)
for p in range(256):
q = cofficient * float(zeroCumuMoment[p])-1
if q >=0:
output[p] = np.math.floor(q)
else:
output[p] = 0
#得出均衡化圖像
equalHistimg = np.zeros(image.shape,np.uint8)
for r in range(rows):
for c in range(cols):
equalHistimg[r][c] = output[image[r][c]]
cv2.imshow('image',image)
cv2.imshow('histimage',equalHistimg)
cv2.waitKey(0)
cv2.destroyAllWindows()
運行結果: