基於OpenCV(PYTHON)的圖像陰影去除
基於OpenCV(PYTHON)的圖像陰影去除
資料來源: https://mp.weixin.qq.com/s?__biz=MzA4MDExMDEyMw==&mid=2247490657&idx=1&sn=2ddbcb559ae5671074f1e3fd199154c0&chksm=9fa86b25a8dfe2333295ebcc22641644701c49a27d4157e8f9ad5cf14de8db5c6c43edab656e&scene=126&sessionid=1607303546&key=acbfa0a404122fa5b0fff40270ee513b8f261f29345b13da8fe3f458e6c9a4530cc2b9979b1179f46d7b59530b11f35261c092bac976889754c50e481b06b2251eda5572467c316b8be79410612adea2ac24d70d38587c825e9b9e69aa344b140360df17acab137ce361b6aa2987dd9d5796de834b1ea0b2883485d5001a00a2&ascene=1&uin=MjIwODk2NDgxNw%3D%3D&devicetype=Windows+10+x64&version=6300002f&lang=zh_TW&exportkey=AtHoikfwnNayhJXXWJDKvIA%3D&pass_ticket=MO1%2F7jo2htVKI2%2BGAjKDIjtKkJhX4E3y4KbwwjTrlIX2T0KmAw4tjOZ1eP%2BEr%2B71&wx_header=0
https://github.com/kavyamusty/Shading-removal-of-images/blob/master/Article%20submission.ipynb
有兩件事要注意:
由於圖像是灰度圖像,如果圖像背景較淺且對象較暗,則必須先執行最大濾波,然後再執行最小濾波。
如果圖像背景較暗且物體較亮,我們可以先執行最小濾波,然後再進行最大濾波。
那麼,最大過濾和最小過濾到底是什麼?
☆最大濾波器:讓我們假設我們有一定大小的圖像I。我們編寫的算法應該逐個遍歷I的像素,並且對於每個像素(x,y),它必須找到該像素周圍的鄰域(大小為N x N的窗口)中的最大灰度值,並進行寫入A中相應像素位置(x,y)的最大灰度值。所得圖像A稱為輸入圖像I的最大濾波圖像。現在讓我們通過代碼來實現這個概念。
max_filtering()函數接受輸入圖像和窗口大小N。
它最初在輸入數組周圍創建一個“牆”(帶有-1的填充),當我們遍歷邊緣像素時會有所幫助。
然後,我們創建一個“ temp”變量,將計算出的最大值複製到其中。
然後,我們遍歷該數組並圍繞大小為N x N的當前像素創建一個窗口。
然後,我們使用“ amax()”函數在該窗口中計算最大值,並將該值寫入temp數組。
我們將該臨時數組複製到主數組A中,並將其作為輸出返回。
A是輸入I的最大濾波圖像。
☆最小濾波器:此算法與最大濾波完全相同,但是我們沒有找到附近的最大灰度值,而是在該像素周圍的N x N鄰域中找到了最小值,並將該最小灰度值寫入B中的(x,y)。所得圖像B稱為圖像I的經過最小濾波的圖像。
實測圖片與結果
輸入圖:
結果圖:
完整程式碼:
import cv2 import numpy as np import matplotlib.pyplot as plt 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] = num A = temp[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)].copy() return A 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_min B = temp_min[(N//2):wall_min.shape[0]-(N//2), (N//2):wall_min.shape[1]-(N//2)].copy() return B def background_subtraction(I, B): O = I - B norm_img = cv2.normalize(O, None, 0,255, norm_type=cv2.NORM_MINMAX) return norm_img def min_max_filtering(M, N, I): if M == 0: #max_filtering A = max_filtering(N, I) #min_filtering B = min_filtering(N, A) #subtraction normalised_img = background_subtraction(I, B) elif M == 1: #min_filtering A = min_filtering(N, I) #max_filtering B = max_filtering(N, A) #subtraction normalised_img = background_subtraction(I, B) return normalised_img P = cv2.imread('Theory.jpg',0) plt.imshow(P,cmap='gray') plt.title("original image") plt.show() #We can edit the N and M values here for P and C images O_P = min_max_filtering(M = 0, N = 20, I = P) #Display final output plt.imshow(O_P, cmap = 'gray') plt.title("Final output") plt.show()