OpenCV如何去除图片中的阴影的实现
作者:ZackSock 发布时间:2023-07-08 22:49:29
一、前言
如果你自己打印过东西,应该有过这种经历。如果用自己拍的图片,在手机上看感觉还是清晰可见,但是一打印出来就是漆黑一片。比如下面这两张图片:
因为左边的图片有大片阴影,所有打印出来的图片不堪入目(因为打印要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会不太理解上面的语法。我们来详细说一下:
创建ndarray数组:我们通过np.array可以将现有的列表装换成一个ndarray对象,这个很好理解
判断数组中有没有0:我们可以直接用ndarray对象来判断,比如:arr == 0,他会返回一个元素结构和数量一样的ndarray对象。但是返回的对象原始类型式bool,我们来看看res的输出:
[False True False False]
从结果可以看出,我们比较arr==0就是对数组中每个元素进行比较,并返回比较的布尔值。
将数组中为0的元素赋值为10:而最难理解的arr[res]操作。它其实就是拿到res中为True的视图,比如上面的结果是第二个为True则只会返回第二个元素的视图。我们执行下面的代码:
arr[res] = 10
就是把对应res为True的部分赋值为10,也就是将arr中值为0的部分赋值为10。
下面是arr最后的结果:
[ 1 10 1 1]
可以看到原本的0处理为了1。
四、去除阴影
现在我们知道了布尔索引,我们可以对图片进行处理了。我们只需要读取图片,然后将像素值大于30的部分处理为白色就好了。下面是我们的代码:
import cv2
# 读取图片
img = cv2.imread('page.jpg', 0)
# 将像素值大于30的部分修改为255(白色)
img[img > 30] = 255
# 保存修改后的图片
cv2.imwrite('res.jpg', img)
上面的代码非常简单,我们使用cv2.imread函数读取图片,第一个参数是图片路径,第二个参数表示读取为灰度图。我们来看看效果图:
可以看到阴影部分被很好地去除了。有些字比较模糊,我们可以通过调节灰白色地范围调整。比如:
img[img > 40] = 255
具体的值就要根据要处理的图片来决定了。
五、改进
对于上面地处理,还可以做一个小小地改进。我们可以让纸张颜色不那么白,我们来看改进后的代码:
import cv2
import numpy as np
img = cv2.imread('page.jpg', 0)
# 计算灰白色部分像素的均值
pixel = int(np.mean(img[img > 140]))
# 把灰白色部分修改为与背景接近的颜色
img[img > 30] = pixel
cv2.imwrite('res.jpg', img)
在上面的代码中我们不再是将灰白色部分设置为255,而是事先计算了一个数值。
pixel = int(np.mean(img[img > 140]))
猜测阴影部分的颜色值小于140,因此先索引出图像中大于140的部分。然后求平均值,这样我们算出来的大致就是原图的背景颜色,然后将图片不是文字的部分处理为背景颜色,就是最终结果了。下面是我们的效果图:
可以看到这次效果要更好了。但是因为背景都是一个颜色,所以看起来还是会有一些差别。
不过有一点需要说一下,上面的操作只适用于比较简单的图片,比如试卷这种。
来源:https://blog.csdn.net/ZackSock/article/details/115293278
猜你喜欢
- 本文实例讲述了Python实现分割文件及合并文件的方法。分享给大家供大家参考。具体如下:分割文件split.py如下:#!/usr/bin/
- 支付宝或者微信支付导出的收款二维码,除了二维码部分,还有很大一块背景图案,例如下面就是微信支付的收款二维码:有时候我们仅仅只想要图片中间的方
- 问题:每次打开pycharm打开py文件光标都是insert模式, 像下面图片那样解决方案:讲Tools里面的Vim Emulator勾选去
- 可以的,看看下面的代码和说明:<%sessionID = session.SessionIDtimeout&nbs
- 1. Numpy(Numberical Python)Anaconda中已经集成了NumPy,可以直接使用。如果想要自行安装的话,可以使用流
- /* --注意:准备数据(可略过,非常耗时) CREATE TABLE CHECK1_T1 ( ID INT, C1 CHAR(8000)
- 异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变
- 前言词云的使用相信大家已经不陌生了,使用很简单,直接调用wordcloud包就可以了。它的主要功能是根据文本词汇和词汇频率生成图片,从中可以
- 在Python中将字符串转换为集合使用 set() 类将字符串转换为集合,例如 my_set = set(my_str)。 set() 类将
- 前言React核心的单向数据流、一切皆数据的state、不会改变的props,以及状态提升等等经常使用便不多总结,需要的看官方文档。JSXJ
- 学习https://matplotlib.org/gallery/index.html 记录,描述不一定准确,具体请参考官网Matplotl
- 本文介绍了用ASP的AdoDb.Stream读取/写入UTF-8编码格式的文件的方法:函数名称:ReadTextFile 作用:利用AdoD
- 目录1.按照一列数值进行排序1.1按照五缺失值的一列进行排序1.1.1升序排列1.1.2 降序排列1.2按照有缺失值的一列进行排序1.2.1
- 要真说出来哪一个函数能够做得到,还真难。但我们可用下面的代码来进行识别,返回“假”即偶数,返回“真”则奇数: function&n
- 我们都一定对比过编程的轻松与简单性。虽然我们都确认php和perl是最容易学习和编程的语言,但我仍旧想知道,如果用php、asp、jsp以及
- np.newaxis 新增一个轴 如何将数组[0,1,2]转换成列向量用ndarray[: , np.newaxis]代码实质就是将原本的(
- python 里面与时间有关的模块主要是 time 和 datetime如果想获取系统当前时间戳:time.time(),是一个float型
- html页面一般都会指定一个编码,如何获取到是处理html页面的第一步,因为错误的编码必然带来后面处理的问题。这里我用python的正则表达
- 本文实例讲述了PHP面向对象继承用法。分享给大家供大家参考,具体如下:继承先看两个类<?phpclass CdProduct { &n
- 对于大前端来说,JS可谓是我们的神器,从页面的效果到数据的传递,再到后台的业务,无处不充斥着JS的身影,但是万能的JS也有贪玩的时候,某一时