2022年 11月 9日

【Python学习向】 图片去水印

import os


os.path.abspath()

作用:获取指定文件或目录的绝对路径。

P.S. 在Windows中路径的分隔符是’\’

获取本文件的绝对路径:

  1. import os
  2. file_path = os.path.abspath(__file__)
  3. print(file_path)
  4. 运行结果:
  5. X:\aaa\bbb\ccc\ddd.py

P.S.os.path.abspath取决于os.getcwd,如果是一个绝对路径,就返回,如果不是绝对路径,根据编码执行getcwd/getcwdu.然后把path和当前工作路径连接起来。abspath括号内的内容仅拼接在当前文件路径上。

os.path.split()

作用:通过一对链表的头和尾来划分路径名。链表的tail是是最后的路径名元素。head则是它前面的元素。

划分路径 X:\aaa\bbb\ccc\ddd.py :

  1. path = 'X:\aaa\bbb\ccc\ddd.py'
  2. head = os.path.split(path)[0]
  3. tail = os.path.split(path)[1]
  4. print(head)
  5. print(tail)
  6. 运行结果:
  7. X:\aaa\bbb\ccc
  8. ddd.py

os.path.join()

作用:连接两个或更多的路径名组件

        1.如果各组件名首字母不包含’\’,则函数会自动加上

        2.从右往左从第一个以”\”开头的参数开始拼接,之前的参数全部丢弃,当有多个时,从最后一个开始

        3.如果最后一个组件为空,则生成的路径以一个’\’分隔符结尾

将目录和文件拼接成路径:

  1. path = 'X:\aaa\bbb\ccc'
  2. newpath = os.path.join(path, 'ddd.py')
  3. print(newpath)
  4. 运行结果:
  5. X:\aaa\bbb\ccc\ddd.py

os.path.exists()

作用:判断文件是否存在,参数可以是文件路径。

判断当前目录中是否存在ddd.py:

  1. result = os.path.exists('ddd.py')
  2. print(result)
  3. 运行结果:
  4. True
  5. False

os.mkdir()

作用:创建目录(创建一级目录)。如果目录有多级,则创建最后一级,如果最后一级目录的上级目录有不存在的,则会抛出一个 OSError。

在X:\aaa\bbb\ccc下创建一个eee目录:

  1. path = 'X:\aaa\bbb\ccc'
  2. os.mkdir(path)

from PIL import Image


Image.open()

作用:读取图片文件,生成图片对象。

读取X:\aaa\bbb\ccc下的aaa.jpg:

  1. path = X:\aaa\bbb\ccc\aaa.jpg
  2. img = Image.open(path)

对于图片对象img:

img.size

作用:获取图片的宽和高

  1. path = 'aaa.png'
  2. img = Image.open(path)
  3. width, height = img.size #图片的宽和高

img.getpixel()

作用:获取图像中某一点的像素的RGB颜色值,getpixel的参数是一个像素点的坐标。对于图象的不同的模式,getpixel函数返回的值不同。

获取像素点(1,1)的rgb值:

rgb = img.getpixel((1,1))[:3] #取数组前3个值

img.putpixel()

作用:修改某一像素的值。对于单波段图像,颜色作为单个数值给出;对于multi-band图像,颜色作为元组给出。

修改点(1,1)处的rgb值为(255, 255, 255)  (白色):

img.putpixel((1, 1), (255, 255, 255))

img.save()

作用:另存为图片对象到某一路径。

  1. path = 'X:\aaa\bbb\ccc\pic.png'
  2. img.save(path)

from itertools import product


product()

作用:product(A,B)函数,返回A和B中的元素组成的笛卡尔积的元组。product(list1,list2)依次取出list1中每1个元素,与list2中的每1个元素,组成元组,将所有元组组合成一个列表返回。

  1. width = 3
  2. height = 2
  3. for pos in product(range(width), range(height)):
  4. print(pos)
  5. 运行结果:
  6. (0, 0)
  7. (0, 1)
  8. (1, 0)
  9. (1, 1)
  10. (2, 0)
  11. (2, 1)

去水印代码:

  1. from PIL import Image
  2. from itertools import product
  3. import os
  4. def remove_img(image_file, result_path):
  5. img = Image.open(image_file)
  6. width, height = img.size
  7. for pos in product(range(width), range(height)):
  8. rgb = img.getpixel(pos)[:3] #取数组前3个值
  9. if sum(rgb) >= 700 : # 检测浅白色像素,即水印,根据水印类型调整
  10. img.putpixel(pos, (255, 255, 255)) # 替换水印,根据背景像素调整
  11. name = input('请输入输出图片名称(包括拓展名):')
  12. result_file = os.path.join(result_path, name)
  13. img.save(result_file)
  14. file_path = os.path.split(os.path.abspath(__file__))[0]
  15. while 1:
  16. image_file = input('请输入待去除水印图片绝对路径:')
  17. if not os.path.exists(image_file):
  18. print('文件不存在,请重新输入!')
  19. else:
  20. break
  21. results = os.path.join(file_path, 'results')
  22. if not os.path.exists(results):
  23. os.mkdir(results)
  24. remove_img(image_file, results)

        需要根据水印的类型和图片的整体背景对检测rgb数值以及替换像素值进行调整,才能够达到一个较好的去除效果~