一、方法说明
由于图像是灰度图像,删除阴影时,有两件事要注意:
- 如果图像背景较浅且对象较暗,则必须先执行最大滤波,然后再执行最小滤波。
- 如果图像背景较暗且物体较亮,我们可以先执行最小滤波,然后再进行最大滤波。
1.1 最大滤波
假设有一定大小的图像 image1。算法逐个遍历 image1 的像素,并且对于每个像素 (x,y),它必须找到该像素周围的邻域(大小为 N × N N \times N N×N 的窗口)中的最大灰度值,并进行写入 image2 中相应像素位置 (x,y) 的最大灰度值。所得图像 image2 称为输入图像 image1 的最大滤波图像。
代码实现:
def max_filtering(N, image1):
wall = np.full((image1.shape[0]+(N//2)*2, image1.shape[1]+(N//2)*2), -1)
wall[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)] = image1.copy()
temp = np.full((image1.shape[0]+(N//2)*2, image1.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
image2 = temp[(N//2):wall.shape[0]-(N//2), (N//2):wall.shape[1]-(N//2)].copy()
return image2
1.2 最小滤波
此算法与最大滤波完全相同,但是我们没有找到附近的最大灰度值,而是在该像素周围的 N × N N \times N N×N 邻域中找到了最小值,并将该最小灰度值写入 image2 中的 (x,y) 。所得图像 image2 称为图像 image1 的经过最小滤波的图像。
代码实现:
def min_filtering(N, image1):
wall_min = np.full((image1.shape[0]+(N//2)*2, image1.shape[1]+(N//2)*2), 300)
wall_min[(N//2):wall_min.shape[0]-(N//2), (N//2):wall_min.shape[1]-(N//2)] = image1.copy()
temp_min = np.full((image1.shape[0]+(N//2)*2, image1.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
image2 = temp_min[(N//2):wall_min.shape[0]-(N//2), (N//2):wall_min.shape[1]-(N//2)].copy()
return image2
1.3 后处理
- 因此,如果图像的背景较浅,我们要先执行最大过滤,这将为我们提供增强的背景,并将该最大过滤后的图像传递给最小过滤功能,该功能将负责实际的内容增强。
- 执行
最小-最大滤波
后,我们获得的值不在 0-255 的范围内。因此,我们必须归一化使用背景减法获得的最终阵列,该方法是将原始图像减去最小-最大滤波
图像,以获得去除阴影的最终图像。
Note: 变量
N
(用于过滤的窗口大小)将根据图像中粒子或内容的大小进行更改。
代码实现:
def background_subtraction(image1, image2):
sub_img = image1 - image2
norm_img = cv2.normalize(sub_img, None, 0, 255, norm_type=cv2.NORM_MINMAX)
return norm_img