python 自动图像描边(2020年5月2日)


说明

利用python第三方库PIL实现,大一下学期疫情时代宅家所作。未查阅借鉴其他编程博客,全部为原创内容,程序结构还有待提升,描边算法还有待继续优化(还需过滤掉单独的颗粒状像素点)

效果展示

24975120-682ca6215bb526ea

24975120-e6483c2991033552

24975120-09eb280a5cbfceb5

24975120-99a211aa4a396383

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
图片自动描边
输入一张图片,返回一张图片的差值,根据相邻像素的颜色差异来涂色
2020年5月2日
by littlefean
"""
from PIL import Image
from math import sqrt
from time import time


def distance(color1, color2):
"""
输入两个颜色数据,返回它们的差值
此差值是rgb构成的三维空间中的欧氏距离
:param color1: 颜色1 如:(20, 34, 67)
:param color2: 颜色2
:return: 差值
"""
d = sqrt((color1[0] - color2[0]) ** 2 + (color1[1] - color2[1]) ** 2 + (color1[2] - color2[2]) ** 2)
return d


def right(im, d):
"""
传入一个图片路径和颜色差值参数d,在此py文件目录下保存一张图片
此函数将传入图片的每个像素对比其右边一个像素,
颜色差异距离超过d的像素位置对应输出图片中的白色,其余是黑色
:param im: 图片路径
:param d: 差值
:return:
"""
putColor = (255, 255, 255) # 差异过大时候涂的白色
img = Image.open(im)
w1 = img.width # 图片的宽
h1 = img.height # 图片的高
im3 = Image.new('RGB', (w1, h1), 'black')
for y in range(h1):
for x in range(w1):
src_str_list = img.load() # 当前图片的所有像素信息列表
if x < (w1 - 2):
if distance(src_str_list[x, y], src_str_list[x + 1, y]) >= d:
im3.putpixel((x, y), putColor)
else:
im3.putpixel((x, y), (0, 0, 0))
im3.save(f'DSr_{d}_{time()}.png')


def right_down(im, d, black=False):
"""
同right函数,对比差异过大条件为右侧一个像素或下方一个像素与原位置颜色差值超过d
参考 right函数
black可选参数:若为True则输出黑底白边的图片,默认白底黑边
"""
img = Image.open(im)
w1, h1 = img.width, img.height # 图片的宽高
if black:
putColor = (255, 255, 255) # 差异过大时候涂的白色
im3 = Image.new('RGB', (w1, h1), 'black')
else:
putColor = (0, 0, 0)
im3 = Image.new('RGB', (w1, h1), (255, 255, 255))
for y in range(h1):
for x in range(w1):
src_str_list = img.load() # 当前图片的所有像素信息列表
if (x < (w1 - 2)) and (y < (h1 - 2)):
if (distance(src_str_list[x, y], src_str_list[x + 1, y]) >= d) /
or (distance(src_str_list[x, y], src_str_list[x, y + 1]) >= d):
im3.putpixel((x, y), putColor)
else:
im3.putpixel((x, y), (0, 0, 0))
im3.save(f'DSrd_{d}_{time()}.png')


def right_down_stage(im, d):
"""
参考right_down函数
每个像素对比自己右边和下面的一个像素并输出一张图片,
这张图片上越白的地方表示差异程度越大的地方
"""
img = Image.open(im)
w1 = img.width # 图片的宽
h1 = img.height # 图片的高
im3 = Image.new('RGB', (w1, h1), 'black')
for y in range(h1):
for x in range(w1):
if (x < (w1 - 2)) and (y < (h1 - 2)):
src_str_list = img.load() # 当前图片的所有像素信息列表
d1 = distance(src_str_list[x, y], src_str_list[x + 1, y])
d2 = distance(src_str_list[x, y], src_str_list[x, y + 1])
if d1 > d2:
d = d1
else:
d = d2
pc = int(255 * d / sqrt(255 ** 2 + 255 ** 2 + 255 ** 2))
im3.putpixel((x, y), (pc, pc, pc))
else:
im3.putpixel((x, y), (0, 0, 0))
im3.save(f'DSrds_{d}_{time()}.png')


if __name__ == '__main__':
right_down('屏幕截图(451).png', 25, black=True)