圖像增強目的使得模糊圖片變得更加清晰、圖片模糊的原因是因為像素灰度差值變化不大,圖片各區域產生視覺效果似乎都是一樣的, 沒有較為突出的地方,看起來不清晰的感覺
解決這個問題的最直接簡單辦法,放大像素灰度值差值、使圖像中的細節更加清晰。
目前較為常用的幾個方法:伽馬變換、線性變換、分段線性變換、直方圖均衡化,對于圖像對比度增強,都能取得不錯的效果!
本文將對每種方法 簡單介紹一下,并借助于 Python 、OpenCV 進行代碼實現,提前說一下哈,下面處理的圖像對象都是單通道灰度圖,不是三通道彩色圖!
1,線性變換
線性變換的原理是對所有像素值乘上一個擴張因子 ,像素值大的變得越大,像素值小的變得越小,從而達到圖像增強的效果,這里利用 Numpy 的數組進行操作;
需要注意的是,像素值最大為255,因此在數組相乘之后需要進行數值截斷操作,最終代碼如下:
def?line_trans_img(img,coffient):
????if?len(img.shape)?==?3:
????????img?=?cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
????out?=?2*img
????#像素截斷;;;
????out[out>255]?=?255
????out?=?np.around(out)
????return?out
這里 設置為 2 ,變換結果如下,會看到強光處出現失真效果

(這里對排列圖片做一下說明,從左到右依次為 原圖灰度圖、原圖灰度直方圖、處理之后的灰度圖、處理之后的灰度直方圖,以下的圖片排列方式相同)
2,伽馬變換
伽馬變換對像素值做的是冪次方變換,主要是圖像的灰度級發生改變,轉換的原理公式為:
參數 ?的設定 可以參照下面:

當>1 時,會減小灰度級較高的地方,增大灰度級較低的地方;
當 <1 時,會增大灰度級較高的地方,減小灰度級較低的地方;
def?gama_transfer(img,power1):
????if?len(img.shape)?==?3:
?????????img=?cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
????img?=?255*np.power(img/255,power1)
????img?=?np.around(img)
????img[img>255]?=?255
????out_img?=?img.astype(np.uint8)
????return?out_img
這里 Gamma 分別取 1.5,0.5,結果如下:


結果來看,相對來說 ?對圖像增強的結果會更好一點
3,分段線性分割
分段線性分割,提前把圖像的灰度級分為幾部分,然后對每一部分的像素值做不同的線性變換,像素值基本變換原理:
這里寫的代碼總感覺效率特別慢(逐像素改變),知道改進方法的小伙伴們望告知:
def?seg_augment_img(img,start,c1,end,c2,b2,c3,b3):
????if?len(img.shape)?==?3:
?????????img=?cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
????out_img?=?np.zeros(img.shape)
????for?i?in?range(img.shape[0]):
????????for?j?in?range(img.shape[1]):
????????????if?img[i][j]?????????????????out_img[i][j]?=?img[i][j]*c1
????????????elif?img[i][j]?????????????????out_img[i][j]?=?img[i][j]?*c2?+?b2
????????????else:
????????????????out_img[i][j]?=?img[i][j]?*?c3?+b3
????out_img[out_img>255]?=?255
????out?=?np.around(out_img)
????out?=?out.astype(np.uint8)
????return?out
函數中的參數分別為 50,0.5,150,3.6,-310,0.238,194,結果如下:

4,直方圖均衡化
每個灰度圖像都有自己的灰度直方圖,均衡化的原理是,先根據灰度直方圖計算累加灰度直方圖,根據灰度圖與累加灰度圖的映射關系關聯輸入圖像與輸出圖圖像的映射關系
映射關系原理如下:
因此,這里幾個重要部分:1,計算出灰度直方圖;2,計算累加灰度直方圖;3,根據 1 和 2 得到映射關系,最終輸出灰度像素值;
def?get_imghist(img):
????#?判斷圖像是否為三通道;
????if?len(img.shape)?==?3:
????????img?=?cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
????#?無?Mask,256個bins,取值范圍為[0,255]
????hist?=?cv2.calcHist([img],[0],None,[256],[0,255])
????return?hist
def?cal_equalhist(img):
????if?len(img.shape)?==?3:
?????????img=?cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
????h,w?=?img.shape[:2]
????grathist?=?get_imghist(img)
????zerosumMoment?=?np.zeros([256],np.uint32)
????for?p?in?range(256):
????????if?p?==0:
????????????zerosumMoment[p]?=?grathist[0]
????????else:
????????????zerosumMoment[p]?=?zerosumMoment[p-1]?+grathist[p]
????output_q?=?np.zeros([256],np.uint8)
????cofficient?=?256.0/(h*w)
????for?p?in?range(256):
????????q?=?cofficient?*float(zerosumMoment[p])?-?1
????????if?q?>=?0:
????????????output_q[p]?=?math.floor(q)
????????else:
????????????output_q[p]?=?0
????equalhistimage?=?np.zeros(img.shape,np.uint8)
????for?i?in?range(h):
????????for?j?in?range(w):
????????????equalhistimage[i][j]?=?output_q[img[i][j]]
????#?第二種方法,opencv 庫函數自帶一種:
????#equalhistimage?=?cv2.equalizeHist(img)
????return?equalhistimage
結果如下,看起來還是不錯的!(這里圖片失真是因為燈光的原因)

5,小總結
根據以上幾個增強方法來看,針對于本案例選取的圖像,線性增強方法相對效果并不太好,可能會適用于其它的種類圖像,而 Gamma轉換 ?和直方圖均衡化取得相對不錯的結果
但圖像增強、銳化沒有最優方法,每種方法都有自己的特點,需要根據自己選擇合適的
最后還是要提醒一下感興趣的小伙伴們,記得跟著敲一下代碼,加深一下應用原理!
推薦閱讀
不用 PS 摳圖,Python + OpenCV ?實現自動海報場景替換!
用 Python 對圖片主體輪廓進行提取、顏色標記、并計算區域面積