乐趣区

关于python:Python-让我舅舅的书法作品和-PIL-库发生点美的误会

1. 前言

不久之前写过一篇文章,具体介绍了 PIL 库中的 Image 模块的应用。已经学习过、应用过一段时间的 PS,意识 PIL 后,感觉这这玩意太好玩了,有了想应用 PIL 库实现 PS 中的图片特效的想法。

好,当初间接上案例,不另废其它话。

2. 遮罩图片

本文案例中所用的图片素材,取自于我舅舅的书法作品(有点小名气的书法家)。

第一张书法作品:心佛。

这张 心中有佛 的作品,我只须要下面的 佛字,进行后续操作之前,首要任务是截取佛字,也就整张图片的下面一部分。

这里应用两种计划实现。

2.1 应用 Image 模块的裁剪办法

此办法简略间接,裁剪时须要指定裁剪的矩形区域,左上角坐标容易确定(0,0),右下角的坐标这里就大略判断,眼观一下,佛字大略是整幅作品的 四 分之一。

也能够稍精准的计算机出右下角的地位。

佛字 和上面的内容之间有一条较完整的红色宰割区域。能够从上向下以行为单位扫描整幅图片,如果发现那一行像素点的 R,G,B 的值近似相等且值都大于 200 以上,则可判断出地位。有趣味者能够试试。

from PIL import Image
# 关上原图片
fo_img = Image.open("fo.jpg")
# 因后续要应用此图片做遮罩,须要通明通道,所以要转换成 RGBA 模式 
fo_img = fo_img.convert("RGBA")
# 获取图片自身大小
w, h = fo_img.size
# h/4-55 齐全是试出来的偏差值 
fo_img = fo_img.crop((0, 0, w, h / 4 - 55))
fo_img.show()

如下是裁剪进去的图片成果。

2.2 一个像素点一个像素点的裁剪

当把 RGB 模式转换成 RGBA 模式后,Python 解释器会给多进去的 a 通道赋值 255。

因前面要应用这个佛字做遮罩。这里须要把佛字图片中的红色区域的 a 通道值修改为 0(红色区域全副变成通明区域)。

因是书法图片,整张图片整体上出现显著的黑白两极散布,红色区域的 R、G、B 重量值大略是在 200 左右,彩色文字的 R,G,B 色彩重量值大略在 100 以下。

Tip: 当应用一张图片做遮罩时,图片的 a 通道值为 0 的中央,被遮罩图片所遮住的图片会变成通明。a 通道为 255 的中央,示意齐全不通明,从 0 到 255 之间由通明逐步梯度变成不通明。

from PIL import Image
fo_img = Image.open("fo.jpg")
# 先转换成 RGBA 模式
fo_img = fo_img.convert("RGBA")
# 获取图片自身大小
w, h = fo_img.size
# 创立一张空白的新图片,大小和要裁剪的佛字图片一样大小
fo_only_img = Image.new(fo_img.mode, (w, int(h / 4) - 55))
w, h = fo_only_img.size
for i in range(w):
    for j in range(h):
        # 获取每一像素点的色彩重量
        r, g, b, a = fo_img.getpixel((i, j))
        # 把红色区域的 a 值批改为 0,红色区域的 R,G,B 值相近
        if r > 180 or g>180 or b>180:
            a = 0
        # 为新图片指定新的色彩模式
        fo_only_img.putpixel((i, j), (r, g, b, a))
fo_only_img.show()

以上代码需注意,截取进去的图片数据被写入一张新图片中。

两种计划比拟:

  • 第一种计划提取后,还是须要再批改每一个像素点的通明信息。
  • 第 2 种计划一步到位。

解决完佛字图片后,再筹备一张 春归的书法作品 做被遮罩图片。

为了让便于了解遮罩图片与被遮罩图片的关系,这里画一个示意图。


在如下的代码还会创立一张做背景的红色图片。

from PIL import Image
fo_img = Image.open("fo.jpg")
# 先转换成 RGBA 模式
fo_img = fo_img.convert("RGBA")
# 获取图片自身大小
w, h = fo_img.size
# 创立一张空白的新图片,大小和要裁剪的佛字图片一样大小
fo_only_img = Image.new(fo_img.mode, (w, int(h / 4) - 55))
w, h = fo_only_img.size
for i in range(w):
    for j in range(h):
        # 获取每一像素点的色彩重量
        r, g, b, a = fo_img.getpixel((i, j))
        # 把红色区域的 a 值批改为 0
        if r > 180:
            a = 0
        # 为新图片指定新的色彩模式
        fo_only_img.putpixel((i, j), (r, g, b, a))
# 开始筹备做遮罩成果之前,关上被遮罩图
chun_gui_img = Image.open("chungui.jpg")
# 批改 chun_gui_img 图片和遮罩图片一样大小
chun_gui_img = chun_gui_img.resize(fo_only_img.size)
# 创立一张新的、空白的、纯白色的背景图片
new_img = Image.new("RGBA", chun_gui_img.size)
# 开始粘贴
new_img.paste(chun_gui_img, mask=fo_only_img)
new_img.show()

执行代码后,可看到如下的图片成果。这个成果在 PS 中更容易实现(毕竟人家是业余的图片处理软件)。

几个变动:

  1. 反转成果

    后面是把佛字图片的红色区域的 a 值设定为 0,则红色区域所对应的春归图片会变成通明。当初反过来,把文字区域的 a 值设为 0。就能够看到和上图相同的一个成果。

from PIL import Image
import random

fo_img = Image.open("fo.jpg")
# 先转换成 RGBA 模式
fo_img = fo_img.convert("RGBA")
# 获取图片自身大小
w, h = fo_img.size
# 创立一张空白的新图片,大小和要裁剪的佛字图片一样大小
fo_only_img = Image.new(fo_img.mode, (w, int(h / 4) - 55))
w, h = fo_only_img.size
# 步长值
step = 1
step1 = 1
for i in range(0, w, 1):
    for j in range(h):
        # 获取每一像素点的色彩重量
        r, g, b, a = fo_img.getpixel((i, j))
        # 文字区域的 a 值设置为 0
        if r < 80:
            a = 0
        # 为新图片指定新的色彩模式
        fo_only_img.putpixel((i, j), (r, g, b, a))
# 开始筹备做遮罩成果之前,先关上底图
chun_gui_img = Image.open("chungui.jpg")
# 批改 chun_gui_img 图片和遮罩图片一样大小
chun_gui_img = chun_gui_img.resize(fo_only_img.size)
# 创立一张新的图片
new_img = Image.new("RGBA", chun_gui_img.size,(100,200,80))
# 开始粘贴
new_img.paste(chun_gui_img, mask=fo_only_img)
new_img.show()

如果把背景色彩设置为金色,佛字就会变成金色。同理,能够抉择任一喜爱的色彩。

new_img = Image.new("RGBA", chun_gui_img.size,ImageColor.getrgb("gold"))

  1. 颗粒成果

颗粒成果实现的思路和后面差不多,应用随机模块让文字区域的通明值随机变动,让文字区域有的中央通明,有的中央不通明,有的中央半透明。

from PIL import Image
import random
fo_img = Image.open("fo.jpg")
# 先转换成 RGBA 模式
fo_img = fo_img.convert("RGBA")
# 获取图片自身大小
w, h = fo_img.size
# 创立一张空白的新图片,大小和要裁剪的佛字图片一样大小
fo_only_img = Image.new(fo_img.mode, (w, int(h / 4) - 55))
w, h = fo_only_img.size
print(w)
# 步长值
step = 1
for i in range(0, w, 1):
    for j in range(h):
        # 获取每一像素点的色彩重量
        r, g, b, a = fo_img.getpixel((i, j))
        if r > 180:
            a = 0
        elif r < 100:
            # 随机
            a -= random.randint(0, 255)
        # 为新图片指定新的色彩模式
        fo_only_img.putpixel((i, j), (r, g, b, a))
# 开始筹备做遮罩成果之前,先关上底图
chun_gui_img = Image.open("chungui.jpg")
# 批改 chun_gui_img 图片和遮罩图片一样大小
chun_gui_img = chun_gui_img.resize(fo_only_img.size)
# 创立一张新的图片
new_img = Image.new("RGBA", chun_gui_img.size)
# 开始粘贴
new_img.paste(chun_gui_img, mask=fo_only_img)
new_img.show()

3. 字符串图片

把图片中的每一像素点用不同的字符串替换,而后保留字符串信息。如下代码中,红色区域的像素点应用“仁”字替换。彩色文字区域的像素点应用“佛”字替换。

from PIL import Image
import random
fo_img = Image.open("fo.jpg")
# 先转换成 RGBA 模式
fo_img = fo_img.convert("RGBA")
# 获取图片自身大小
w, h = fo_img.size
# 创立一张空白的新图片,大小和要裁剪的佛字图片一样大小
fo_only_img = Image.new(fo_img.mode, (w, int(h / 4) - 55))
w, h = fo_only_img.size
# 步长值
old_rgb = None
s = ''
for i in range(w):
    for j in range(h):
        # 获取每一像素点的色彩重量
        r, g, b, a = fo_img.getpixel((i, j))
        fo_only_img.putpixel((i, j), (r, g, b, a))

fo_only_img = fo_only_img.resize((300, 300))
w, h = fo_only_img.size
for i in range(h):
    for j in range(w):
        r, g, b, a = fo_only_img.getpixel((j, i))
        if r > 100:
            s += "仁"
        else:
            s += '佛'
    s += "\n"
with open("d:/fo.txt", 'w') as f:
    f.write(s)

找到对应文本文件、关上、放大,能够清晰看到一个大大的“佛”字。如果放大,则会发现,整个佛字是由很多小佛字组成。

4. 总结

编程与书法一样,都是一门艺术,艺术是为生存服务的。程序能够让人类的生存更不便,书法则能够让人类精力世界更美妙。当两者碰在一起后,世界充斥仁和爱。

获取更多技术文章,请关注我的公众号!

退出移动版