基於OpenCV(PYTHON)的圖像陰影去除

基於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()

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *