基于OpenCV的圖像陰影去除


我們經(jīng)常需要通過(guò)掃描將紙上的全部?jī)?nèi)容轉(zhuǎn)換為圖像。有很多在線工具可以提高圖像的亮度,或者消除圖像中的陰影。但是我們可以手動(dòng)刪除陰影嗎?當(dāng)然可以,我們只需要將圖像加載到相應(yīng)的代碼中,無(wú)需任何應(yīng)用程序即可在幾秒鐘內(nèi)獲得輸出。這個(gè)代碼可以通過(guò)Numpy和OpenCV基本函數(shù)來(lái)實(shí)現(xiàn)。為了說(shuō)明該過(guò)程,使用了以下圖像進(jìn)行操作。

Test_image
1.圖像中有一個(gè)非常明顯的陰影需要?jiǎng)h除。首先當(dāng)然是將必要的軟件包導(dǎo)入環(huán)境。
import cv2import numpy as npimport matplotlib.pyplot as plt
2.刪除陰影時(shí),有兩件事要注意。由于圖像是灰度圖像,如果圖像背景較淺且對(duì)象較暗,則必須先執(zhí)行最大濾波,然后再執(zhí)行最小濾波。如果圖像背景較暗且物體較亮,我們可以先執(zhí)行最小濾波,然后再進(jìn)行最大濾波。
那么,最大過(guò)濾和最小過(guò)濾到底是什么?
3.最大濾波:讓我們假設(shè)我們有一定大小的圖像I。我們編寫(xiě)的算法應(yīng)該逐個(gè)遍歷I的像素,并且對(duì)于每個(gè)像素(x,y),它必須找到該像素周?chē)泥徲颍ù笮镹 x N的窗口)中的最大灰度值,并進(jìn)行寫(xiě)入A中相應(yīng)像素位置(x,y)的最大灰度值。所得圖像A稱(chēng)為輸入圖像I的最大濾波圖像?,F(xiàn)在讓我們通過(guò)代碼來(lái)實(shí)現(xiàn)這個(gè)概念。
max_filtering()函數(shù)接受輸入圖像和窗口大小N。
它最初在輸入數(shù)組周?chē)鷦?chuàng)建一個(gè)“墻”(帶有-1的填充),當(dāng)我們遍歷邊緣像素時(shí)會(huì)有所幫助。
然后,我們創(chuàng)建一個(gè)“ temp”變量,將計(jì)算出的最大值復(fù)制到其中。
然后,我們遍歷該數(shù)組并圍繞大小為N x N的當(dāng)前像素創(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.amax(window)temp[y,x] = numA = temp[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)].copy()return A
4.最小濾波:此算法與最大濾波完全相同,但是我們沒(méi)有找到附近的最大灰度值,而是在該像素周?chē)腘 x N鄰域中找到了最小值,并將該最小灰度值寫(xiě)入B中的(x,y)。所得圖像B稱(chēng)為圖像I的經(jīng)過(guò)最小濾波的圖像,代碼如下。
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.amin(window_min)temp_min[y,x] = num_minB = temp_min[(N//2):wall_min.shape[0]-(N//2), (N//2):wall_min.shape[1]-(N//2)].copy()return B
5.因此,如果圖像的背景較淺,我們要先執(zhí)行最大過(guò)濾,這將為我們提供增強(qiáng)的背景,并將該最大過(guò)濾后的圖像傳遞給最小過(guò)濾功能,該功能將負(fù)責(zé)實(shí)際的內(nèi)容增強(qiáng)。
6.因此,執(zhí)行最小-最大濾波后,我們獲得的值不在0-255的范圍內(nèi)。因此,我們必須歸一化使用背景減法獲得的最終陣列,該方法是將原始圖像減去最小-最大濾波圖像,以獲得去除陰影的最終圖像。
#B is the filtered image and I is the original imagedef background_subtraction(I, B):O = I - Bnorm_img = cv2.normalize(O, None, 0,255, norm_type=cv2.NORM_MINMAX)return norm_img
7.變量N(用于過(guò)濾的窗口大?。⒏鶕?jù)圖像中粒子或內(nèi)容的大小進(jìn)行更改。對(duì)于測(cè)試圖像,選擇大小N = 20。增強(qiáng)后的最終輸出圖像如下所示:

Test_image_output
輸出圖像相較于原始圖像已經(jīng)沒(méi)有任何的陰影啦。
代碼鏈接:https://github.com/kavyamusty/Shading-removal-of-images
交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱(chēng)+學(xué)校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~
