使用Numpy+OpenCV來增強灰度圖像
在日常生活中,我們經常會掃描紙張把它們轉換成圖像,但這些圖像往往存在陰影,我們有各種各樣的工具可以在線增強這些圖像,使它們的亮度更亮,并消除這些圖像中的陰影。那有沒有方法可以手動去除陰影呢?比如我們可以將任何圖像作為灰度圖像加載到我們的代碼中,并在幾秒鐘內獲得輸出,而無需任何應用程序的幫助。這是可以通過使用基本的Numpy操作和一些openCV函數來實現。我們使用了下面的圖片作為例子,它是用手機拍的。
很明顯,它有一個陰影需要刪除。將必要的軟件包導入你的環(huán)境。為了易于顯示圖像,我們使用Jupyter Notebook。import cv2
import numpy as np
import matplotlib.pyplot as plt
刪除陰影時,有兩件事要注意。
(1)由于圖像是灰度圖像,如果圖像背景較淺且對象較暗,則必須先執(zhí)行最大值濾波,然后再執(zhí)行最小值濾波;(2)如果圖像背景較暗且物體較亮,我們可以先執(zhí)行最小值濾波,然后再進行最大值濾波。那么,最大值濾波和最小值濾波到底是什么呢?最大值濾波:假設我們有一個特定大小的圖像 I ,我們編寫的算法應逐個遍歷 I 的像素,并且對于每個像素(x,y)都必須找到該像素周圍的鄰域(大小為N x N的窗口)中的最大灰度值,并將該最大灰度值寫入A中相應的像素位置(x,y),所得圖像 A 稱為輸入圖像 I 的最大值濾波圖像。讓我們在代碼中實現這個過程。max_filtering()函數接受輸入圖像和窗口大小N。它最初在輸入數組周圍創(chuàng)建一個“wall”(帶有-1的填充),當我們遍歷邊緣像素時會使用這個數據。然后,我們創(chuàng)建一個“ temp”變量,將計算出的最大值復制到該變量中。然后,我們遍歷數組,并圍繞當前像素大小N x N創(chuàng)建一個窗口。然后,我們使用“ amax()”函數在該窗口中計算最大值,并將該值寫入temp數組。我們將該臨時數組復制到主數組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] = num
A = temp[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)].copy()
return A
最小值濾波:此算法與最大值濾波完全相同,區(qū)別在于我們不再去找鄰近的最大灰度值,而是找該像素周圍N x N鄰近的最小值,并將該最小灰度值寫入B中的(x,y),所得的圖像 B 稱為圖像 I 的經過最小值濾波的圖像。讓我們對該過程進行編碼。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
因此,如果圖像的背景較淺,我們要先執(zhí)行最大值濾波,這會為我們提供增強的背景,并將該最大值濾波后的圖像傳遞給最小值濾波函數,該函數將負責實際的內容增強。執(zhí)行最小-最大值濾波后,我們獲得的值不在0-255的范圍內,所以我們必須歸一化使用背景減法獲得的最終陣列,該方法是用原始圖像減去最小最大值濾波后的圖像,以獲得去除了陰影的最終圖像。#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(用于過濾的窗口大小)將根據圖像中粒子或內容的大小進行更改。對于測試圖像,選擇大小N = 20。增強后的最終輸出圖像如下所示:
輸出圖像是原始圖像增強后的結果,所實現的代碼是在openCV中手動實現一些庫函數以增強圖像的拙劣嘗試,帶有圖像的整個notebook可以在下面的Github鏈接中找到。

請輸入評論內容...
請輸入評論/評論長度6~500個字
最新活動更多
-
7月8日立即報名>> 【在線會議】英飛凌新一代智能照明方案賦能綠色建筑與工業(yè)互聯
-
7月22-29日立即報名>> 【線下論壇】第三屆安富利汽車生態(tài)圈峰會
-
7.30-8.1火熱報名中>> 全數會2025(第六屆)機器人及智能工廠展
-
7月31日免費預約>> OFweek 2025具身智能機器人產業(yè)技術創(chuàng)新應用論壇
-
免費參會立即報名>> 7月30日- 8月1日 2025全數會工業(yè)芯片與傳感儀表展
-
即日-2025.8.1立即下載>> 《2024智能制造產業(yè)高端化、智能化、綠色化發(fā)展藍皮書》
推薦專題