一、前言
如果你自己打印过东西,应该有过这种经历。如
本文来源gao!daima.com搞$代!码网
果用自己拍的图片,在手机上看感觉还是清晰可见,但是一打印出来就是漆黑一片。比如下面这两张图片:
因为左边的图片有大片阴影,所以打印出来的图片不堪入目(因为打印要3毛钱,所以第二张图片只是我用程序模拟的效果)。
那有什么办法可以解决吗?答案是肯定的,今天我们就来探讨几个去除阴影的方法。
二、如何去除阴影?
首先为了方便处理,我们通常会对图片进行灰度转换(即将图片转换成只有一个图层的灰色图像)。
然后我们分析一下,在上面的图片中有三个主色调,分别是字体颜色(黑色)、纸张颜色(偏白)、阴影颜色(灰色)。知道这点后我们就好办了。我们只需要把灰色和白色部分都处理为白色就好了。
那要我怎么才知道白色和灰色区域呢?对于一个8位的灰度图,黑色部分的像素大致在0-30左右。白色和灰色应该在31-255左右(这个范围只是大致估计,实际情况需要看图片)。如图:
左边是原图,右边是处理后的图片。我们将灰色和接近白色的部分都处理成了白色。
那下面我们就开始处理吧。
三、numpy的ndarray数组
可能有些读者没有接触过numpy,这里简单说一下。
numpy是一个第三方的模块,用它我们可以很方便的处理多维数组(ndarray数组)。而图片在OpenCV中的存储方式正好是ndarray,所以我们对数组的操作就是对图片的操作。
在使用之前我们需要安装一下OpenCV模块:
pip install opencv-python
在安装OpenCV时会自动安装numpy。
下面我们主要是看看布尔索引的操作,先看下面代码:
import numpy as np # 创建一个元素为1, 0, 1, 1的ndarray数组 arr = np.array([1, 0, 1, 1]) # 判断数组中有没有0 res = arr == 0 # 将数组中为0的元素赋值为10 arr[res] = 10
如果没有接触过numpy会不太理解上面的语法。我们来详细说一下:
1.创建ndarray数组:我们通过np.array可以将现有的列表转换成一个ndarray对象,这个很好理解
2.判断数组中有没有0:我们可以直接用ndarray对象来判断,比如:arr == 0,他会返回一个元素结构和数量一样的ndarray对象。但是返回的对象原始类型是bool,我们来看看res的输出:
[False True False False]
从结果可以看出,我们比较arr==0就是对数组中每个元素进行比较,并返回比较的布尔值。
3.将数组中为0的元素赋值为10:而最难理解的arr[res]操作。它其实就是拿到res中为True的视图,比如上面的结果是第二个为True则只会返回第二个元素的视图。我们执行下面的代码:
arr[res] = 10
就是把对应res为True的部分赋值为10,也就是将arr中值为0的部分赋值为10。
下面是arr最后的结果:
[ 1 10 1 1]
可以看到原本的0处理为了10。
四、去除阴影
现在我们知道了布尔索引,我们可以对图片进行处理了。我们只需要读取图片,然后将像素值大于30的部分处理为白色就好了。下面是我们的代码:
import cv2 # 读取图片 img = cv2.imread('page.jpg', 0) # 将像素值大于30的部分修改为255(白色) img[img > 30] = 255 # 保存修改后的图片 cv2.imwrite('res.jpg', img)