如何给一千张图片去水印?还好我会python,100行代码轻松搞定

写在前面

近期好多网友私信我,问我编程该怎么学习、怎么入门。我觉得编程学习,就像写文章一样,需要积累。如果把代码每个字符拆开,大伙都认识,但是组合在一起,就是另外一回事了。所以我的建议是,学习编程,从项目入手,从自己感兴趣的项目入手,遇到不懂的语法、算法,就去翻阅书、看视频。如果一开始就去看生硬v x g H的语法、晦涩的算法,就像背单词一样,背到第一个单词abandon,就放弃了。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

废话不多说,直接上项目,这次是一个批量去除水印的项目。

  • 环境配置:

python版本: 3.6.0

编辑器: pycharm

ps: 每一步都有代码和排版截图! 6 W ? ] # i F,方便学习

  • 代码目录结构
如何给一千张图片去水印?还好我会python,100行代码轻松搞定

切记刚开始学习的时候,目录结构保持和源码一致

第一步:导入相关的python包

# encoding:utf-8
import os
from PIL import Image
i? 0 1 3mport numpy as np
import imghw W dr

python包的作用:

os: 本项目只用到了对文件、文件夹的操作。

PIL: Python Imaging Library,是Python平台的图像处理标准库。PIL功能非常强大,API也非常简O $ k e单易用。安装命令:pip inQ { 9 Mstall pillow

numpy: (Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。安装命令: pip install numpy

imghdr: 是一个用来检测图片类型的模块,传递给它的可以是一个文件M - 3对象,也可以是一个字节流。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

第二步:参数配置类

class CONF:
input_path = \"input_img\" # 待处理的图片存放的位置
output_path = \"output_im} 9 5 ; h G W _g\" # 去除水印a P 6 v后的图片存放位置
level_black = 108 # 用于去除水印的特u J w G征值
level_whitw 0 q M _ J p Z 3e = 170 # 用于去除水印的特征值
in _ @ B e ?s_log = True # 是否打印日志信息

这里是个人编程r V 4 , , | Z的习惯,我习惯把一些配置,例如:文件路径、模D 1 o a O 7 &型存放路径、模型参数统一放在一个类中。当然,实际项目开发的时候,是用config 文本文件存放,, y - K G } )不会直接写在代码里,这里为了演示方便,就写在一起,也方便运行K E F ]。这块B # ; H Z %代码放在代码文件的b a e E m t o开头也方便查看和修改。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

第三步:类的初始化

class DocWipe:
def __init__(self, input_path, output_pa* @ / - ] 6 R 4 Sth, level_black, level_white, is_lo, P v u ? ` @ Rg):
self.input_path = input_path
self.output_path = output_path
self.level_black = level_black
self.level_white = level_whitB % { x e 6 a e
self.is_log = is_log


\"\"\" 初始化 \"\K 2"\"
@classmethod
def initialize(cls, config):
input_path = config.input_path
output_path = config.output_path
level_black = config.level_black
level_whiteZ z w 7 B F H = config.level_white
is_log = config.is_log
return cls(i@ 9 U T k $ ^ + Knput_path, output_path, leb y R t + p Yvel_black, level_white, is_log)

initialize() 函数和 __init__() 函数 是对象初始化和实例化,其中包括基本9 q e X 参数的赋值、最后返回用户一个对象。这里作为一个类的基本操作,是属于一个通用模板,在大多数项目中,都可以这么去写。为了养成良好的编程习惯,大. R n家可以把这个模板记下来,后续直接套用,修改部分参数就可以了。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

第四步: 类的主流程函数d m ,

\"\"\" 主流程 \# V _ T T F ]"\"\"
def wipe_procesm m m H S n Vs(self,):
if os.path.exists(self.in^ w ; = &put_path) a( a , k p 2 h V =nd os.path.isdir(self.output_path):
self.visit_d+ i 2 a b $ir_files(self.input_path, seQ ? [ s klf.output_path, self.C O S T 8 Z - R 9input_path)
i3 & O m r 1f self.is_log:
print(u\'完成!所有图片已保存至路径\' + self.outr . 5 ` &put_path)
else:
print(u\'待处理的图片存放的位置 %s, 如果没有请新建目录 %s\' % (self.input_path, self.input_path))
print(u\'去除水印后的图片存放位置 %s, 如果没有请新建E h @ @ p p M F目录 %s\' % (sel; j * Z ~ ;f.output_path, self.output_path))

在写代码的时候,一定要抓住主线,就是代码运行的主流程。因为一个完整可靠的项目,它是有很多细枝末节考虑,很多步骤是要分模块来写。主流程就是把主心干确定好,各个模块的入口确定好。这样开发的时A ` G } 0 ~候,思路会比较清晰,不会被细节吸引住。这里主心干只有个函数 visit_dir_files() 的调用,但是它的外围都是一些边w m ) x ]界条件的判定,不重要,但是没有它们程序会出现BUG。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

第五步:图像处理算法

\"\"\" 图片处理 \"\"\"
def img_deal(self, img_path, save_path):
img = Im? G K @ T c K `age.open(im) 5 G ; ` $ /g_path)P | -
img = self.levels_deal(img, self.level_black, self.level_white)
im# V Dg_res = Image.fromarray(T m Q } R 6 r I Eimg.astype(\'uint8\'))
if self.is_log:
print(u\H ` n D ^ n ` M'图片[\' + img_path + u\']处理完毕\')
img_res.save(save_path)

\, V r T t I w )"\"\" 图像矩阵处理 \A t 4"\"\"
def levels_deal(self, im_ D % 5 N V # Eg, black, whi p nte):
if white > 255:
white = 255
i& r & + + ~ ^ Kf black < 0:
black = 0
if black >= white:
black = white - 2
img_array = np.array(img, dtype=int)
c_rate = -(white - black) / 255.0 * 0.05! 8 F n
rgb_g U diff =w 7 Q $ Y E np.maximum(img_array - black, 0)
img_array = np.around(rgb_diff * c_rate, 0)S e H 0
img_array = img_array.astype(int)
return img_array

在计算机看来,彩色图片是三个二维数据分别是R通道、G通道、B通道,而灰度图是一个二维数组。数值类型是uint8,简单的说,就是每个像素点是0~255的数值。去除水印的算法,其实就是对每个像P O | y i x *素点进行运算,为了加快运算速度和代码的整洁度,使用了numpy包的矩阵运算。

这块的细节理解起来是比较有难度的,它涉及了图像处理的算法,这块可以先跳过,知道它的功能是干嘛的就行。T G ~后续有时间,再来细细琢磨。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

  • 第六步: 递归访问文件
\"\"\/  s M 2 H G" 创建文件夹 \"\"\"
def mkdir(self, path):
path = path.strip().rstrip(\"\\\\\")
is_ex[ ! 4 F 7 = l 0 )ists = os.path.exists(path)
if not is_exists:
os.makedirs(path)
return True
else:
return False


\"\"\" 递归访问文件/文件夹 \"\"\"
def visit_dir_files2 p { ( x k X ) U(self, org_input_dir, org_output_dir, recursion_dir):
siV T 3 . } E 7 N *ngle_file = False
if os.path.isdir(recursion_dir):
dir_list = os.listdir(recuN & [ m 8 E v wr~ $ ( jsion_dir)
else:
dir_list = [recursion_dir]
single_file = True
for i in range(0, len(dir_list)):
path = os.path.join(recursion_dir, dir_lV G x F R 8ist[i])
if os.path.isdir(path):
self.visit_dir_files(org_input_dir, org_output_dir, path)
else:
if imghdr.what(path):
abs_output_dir = org_output_4 C udir + recursiR / b J ! Son_dir[len(org_input_dir):]
target_pa* f [ Y G y ^ Lth = os.path.join(abs_output_dir, dir_liO o r ( - q Lstm G 5 e l ( -[i])
if single_file:
target_path = os.path.join(org_outputE B 9 c K_dirY r # [ l 9, os.path.basename(dir_list[i]))
target_dir_n| C K S X v $ +ame = os.path.| 7 Q G M 3 cdir+ z 9name(target_path)
if not os.path.exist` 6 | z G ]s(target_dir_name)A # i m b f:
self.mkdir(target_dir_name)
self.img_deal(path, target_path)

这里也有一个难点,递归访问文件/文件夹。递归,就是自己调用自己。可以把它当成“分治法”,打个比方,如果你想解决一个很大的难题,直接计算是非常困难的,可以把它拆解成多个小问题,一个一个来解决。而递归,就是起到一个“分治”的作用。它调用的过程,就是数% 9 U H据结构里面的“”(先进后出)。

我当时开始学习算法的时候,递归算法也是研究了一个星期才懂它的原理。所以大家学习的时候,不要着急,先L 9 h C # P .在纸上模拟调用过程,慢慢就会懂了。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

第七步: 主函数入口

if __name__ == \'__main__\':

# 对象初始化
df R h M & : x Y aoc_w^ { LipV = 7e = DocWipe.initialize(config=CONF)
# 调用主流程
doc_wipe.wipe_process()

e w ? u K此,加上一个main函数去调用,所有程序的入口。我们终于完成了。

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

最后,测试一下

用我之前写的《最近很火的文章自动生成器》,来生成随机一篇文章,并加上水印。再转成图片,作为程序的输入,运行结果:

如何给一千张图片去水印?还好我会python,100行代码轻松搞定

左边有水印x 6 T,右边是经过python去除了水印

注意: 仅对浅色的黑白/彩色水印有效,如WPS水印,课程水印等

最后,给一点点学习建议,不懂的时候,先弄明白它的功能以及会使用它,让代码先运行起来。等有时间就一个一个细节去攻破它,编程和写D E ~ B U 8文章一样,需要慢慢积累,E v :加油。


如果有疑问想获取源码(其实代码都( M * x y ! W 5在上面),可以关注后,在后台私信我,回复:python去水印。 我把源码发你。最后,感谢大家的阅读,祝大家工作生活愉快!

上一篇

他正式回应了,就在不久之前,马布里为纽约买口罩被批评

下一篇

芯海科技专注全信号链芯片设计

评论已经被关闭。

插入图片
返回顶部