在平常生活中,咱们常常会扫描纸张把它们转换成图像,但这些图像每每存在阴影,咱们有各类各样的工具能够在线加强这些图像,使它们的亮度更亮,并消除这些图像中的阴影。那有没有方法能够手动去除阴影呢?好比咱们能够将任何图像做为灰度图像加载到咱们的代码中,并在几秒钟内得到输出,而无需任何应用程序的帮助。
这是能够经过使用基本的Numpy操做和一些openCV函数来实现。咱们使用了下面的图片做为例子,它是用手机拍的。
很明显,它有一个阴影须要删除。
将必要的软件包导入你的环境。为了易于显示图像,咱们使用Jupyter Notebook。git
import cv2 import numpy as np import matplotlib.pyplot as plt
删除阴影时,有两件事要注意。(1)因为图像是灰度图像,若是图像背景较浅且对象较暗,则必须先执行最大值滤波,而后再执行最小值滤波;(2)若是图像背景较暗且物体较亮,咱们能够先执行最小值滤波,而后再进行最大值滤波。
那么,最大值滤波和最小值滤波究竟是什么呢?
3.最大值滤波:假设咱们有一个特定大小的图像 I ,咱们编写的算法应逐个遍历 I 的像素,而且对于每一个像素(x,y)都必须找到该像素周围的邻域(大小为N x N的窗口)中的最大灰度值,并将该最大灰度值写入A中相应的像素位置(x,y),所得图像 A 称为输入图像 I 的最大值滤波图像。
让咱们在代码中实现这个过程。github
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
4.最小值滤波:此算法与最大值滤波彻底相同,区别在于咱们再也不去找邻近的最大灰度值,而是找该像素周围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
5.所以,若是图像的背景较浅,咱们要先执行最大值滤波,这会为咱们提供加强的背景,并将该最大值滤波后的图像传递给最小值滤波函数,该函数将负责实际的内容加强。
6.执行最小-最大值滤波后,咱们得到的值不在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
7.变量N(用于过滤的窗口大小)将根据图像中粒子或内容的大小进行更改。对于测试图像,选择大小N = 20。加强后的最终输出图像以下所示:
输出图像是原始图像加强后的结果,所实现的代码是在openCV中手动实现一些库函数以加强图像的拙劣尝试,带有图像的整个notebook能够在下面的Github连接中找到。ide