訂閱
糾錯(cuò)
加入自媒體

使用Numpy+OpenCV來(lái)增強(qiáng)灰度圖像

在日常生活中,我們經(jīng)常會(huì)掃描紙張把它們轉(zhuǎn)換成圖像,但這些圖像往往存在陰影,我們有各種各樣的工具可以在線增強(qiáng)這些圖像,使它們的亮度更亮,并消除這些圖像中的陰影。那有沒(méi)有方法可以手動(dòng)去除陰影呢?比如我們可以將任何圖像作為灰度圖像加載到我們的代碼中,并在幾秒鐘內(nèi)獲得輸出,而無(wú)需任何應(yīng)用程序的幫助。這是可以通過(guò)使用基本的Numpy操作和一些openCV函數(shù)來(lái)實(shí)現(xiàn)。我們使用了下面的圖片作為例子,它是用手機(jī)拍的。

很明顯,它有一個(gè)陰影需要?jiǎng)h除。將必要的軟件包導(dǎo)入你的環(huán)境。為了易于顯示圖像,我們使用Jupyter Notebook。import cv2
import numpy as np
import matplotlib.pyplot as plt

刪除陰影時(shí),有兩件事要注意。

(1)由于圖像是灰度圖像,如果圖像背景較淺且對(duì)象較暗,則必須先執(zhí)行最大值濾波,然后再執(zhí)行最小值濾波;(2)如果圖像背景較暗且物體較亮,我們可以先執(zhí)行最小值濾波,然后再進(jìn)行最大值濾波。那么,最大值濾波和最小值濾波到底是什么呢?最大值濾波:假設(shè)我們有一個(gè)特定大小的圖像 I ,我們編寫(xiě)的算法應(yīng)逐個(gè)遍歷 I 的像素,并且對(duì)于每個(gè)像素(x,y)都必須找到該像素周?chē)泥徲?大小為N x N的窗口)中的最大灰度值,并將該最大灰度值寫(xiě)入A中相應(yīng)的像素位置(x,y),所得圖像 A 稱為輸入圖像 I 的最大值濾波圖像。讓我們?cè)诖a中實(shí)現(xiàn)這個(gè)過(guò)程。max_filtering()函數(shù)接受輸入圖像和窗口大小N。它最初在輸入數(shù)組周?chē)鷦?chuàng)建一個(gè)“wall”(帶有-1的填充),當(dāng)我們遍歷邊緣像素時(shí)會(huì)使用這個(gè)數(shù)據(jù)。然后,我們創(chuàng)建一個(gè)“ temp”變量,將計(jì)算出的最大值復(fù)制到該變量中。然后,我們遍歷數(shù)組,并圍繞當(dāng)前像素大小N x N創(chuàng)建一個(gè)窗口。然后,我們使用“ amax()”函數(shù)在該窗口中計(jì)算最大值,并將該值寫(xiě)入temp數(shù)組。我們將該臨時(shí)數(shù)組復(fù)制到主數(shù)組A中,并將其作為輸出返回。A是輸入I的最大值濾波圖像。def max_filtering(N, I_temp):
   wall = np.full((I_temp.shape[0]+(N//2)*2, I_temp.shape[1]+(N//2)*2), -1)
   wall[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)] = I_temp.copy()
   temp = np.full((I_temp.shape[0]+(N//2)*2, I_temp.shape[1]+(N//2)*2), -1)
   for y in range(0,wall.shape[0]):
       for x in range(0,wall.shape[1]):
           if wall[y,x]!=-1:
               window = wall[y-(N//2):y+(N//2)+1,x-(N//2):x+(N//2)+1]
               num = np.a(chǎn)max(window)
               temp[y,x] = num
   A = temp[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)].copy()
   return A

最小值濾波:此算法與最大值濾波完全相同,區(qū)別在于我們不再去找鄰近的最大灰度值,而是找該像素周?chē)鶱 x N鄰近的最小值,并將該最小灰度值寫(xiě)入B中的(x,y),所得的圖像 B 稱為圖像 I 的經(jīng)過(guò)最小值濾波的圖像。讓我們對(duì)該過(guò)程進(jìn)行編碼。def min_filtering(N, A):
   wall_min = np.full((A.shape[0]+(N//2)*2, A.shape[1]+(N//2)*2), 300)
   wall_min[(N//2):wall_min.shape[0]-(N//2), (N//2):wall_min.shape[1]-(N//2)] = A.copy()
   temp_min = np.full((A.shape[0]+(N//2)*2, A.shape[1]+(N//2)*2), 300)
   for y in range(0,wall_min.shape[0]):
       for x in range(0,wall_min.shape[1]):
           if wall_min[y,x]!=300:
               window_min = wall_min[y-(N//2):y+(N//2)+1,x-(N//2):x+(N//2)+1]
               num_min = np.a(chǎn)min(window_min)
               temp_min[y,x] = num_min
   B = temp_min[(N//2):wall_min.shape[0]-(N//2), (N//2):wall_min.shape[1]-(N//2)].copy()
   return B

因此,如果圖像的背景較淺,我們要先執(zhí)行最大值濾波,這會(huì)為我們提供增強(qiáng)的背景,并將該最大值濾波后的圖像傳遞給最小值濾波函數(shù),該函數(shù)將負(fù)責(zé)實(shí)際的內(nèi)容增強(qiáng)。執(zhí)行最小-最大值濾波后,我們獲得的值不在0-255的范圍內(nèi),所以我們必須歸一化使用背景減法獲得的最終陣列,該方法是用原始圖像減去最小最大值濾波后的圖像,以獲得去除了陰影的最終圖像。#B is the filtered image and I is the original image
def background_subtraction(I, B):
   O = I - B
   norm_img = cv2.normalize(O, None, 0,255, norm_type=cv2.NORM_MINMAX)
   return norm_img

變量N(用于過(guò)濾的窗口大小)將根據(jù)圖像中粒子或內(nèi)容的大小進(jìn)行更改。對(duì)于測(cè)試圖像,選擇大小N = 20。增強(qiáng)后的最終輸出圖像如下所示:

輸出圖像是原始圖像增強(qiáng)后的結(jié)果,所實(shí)現(xiàn)的代碼是在openCV中手動(dòng)實(shí)現(xiàn)一些庫(kù)函數(shù)以增強(qiáng)圖像的拙劣嘗試,帶有圖像的整個(gè)notebook可以在下面的Github鏈接中找到。

聲明: 本文由入駐維科號(hào)的作者撰寫(xiě),觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問(wèn)題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過(guò)于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無(wú)評(píng)論

暫無(wú)評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)