微信改版,加星标不迷路!
基于Python实现图画转换字符画
作者:阿广
概述
前言
准备工作
识别原理
静态图像处理
动态图像处理
结果
阿广说
群聊交流
福利一刻
推荐阅读
前言
前几天写了基于Python生成铅笔素描图,朋友们对其非常感兴趣。不满足于现状,却局限于现状,对静态和动态的图画进行了字符画的转变,何尝不呈现出“几多风流、几多闲愁”的诗情画意。我不是画画的创造者,我是图画的修理工。
准备工作
对于静态图片,我们使用PIL做图像处理,所以需要安装下面的库:
from PIL import Image, ImageDraw, ImageFont
import os
import time
对于动态图片,我们需要导入以下库:
from PIL import Image, ImageFont, ImageDraw
import argparse
import os
import imageio
识别原理
字符画是一系列字符的组合,我们可以把字符看作是比较大块的像素,一个字符能表现一种颜色,字符的种类越多,可以表现的颜色也越多,图片也会更有层次感。
问题来了,我们是要转换一张彩色的图片,这么多的颜色,要怎么对应到单色的字符画上去?这里就要介绍灰度值的概念了。
灰度值:指黑白图像中点的颜色深度,范围一般从0到255,白色为255,黑色为0,故黑白图片也称灰度图像
我们可以使用灰度值公式将像素的 RGB 值映射到灰度值:
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
这样就好办了,我们可以创建一个不重复的字符列表,灰度值小的用列表开头的符号,灰度值大的用列表末尾的符号。
静态图像处理
主函数如下:
def main():
im = Image.open(img_name + '.jpg').convert('L')
im = im.resize((f_num_x, int(f_num_x * im.size[1] / im.size[0])))
level = im.getextrema()[-1] / (len(font_map) - 1)
im = im.point(lambda i: int(i / level))
imn = Image.new('L', (im.size[0] * f_size, im.size[1] * f_size))
f = ImageFont.truetype('arial.ttf', f_size)
d = ImageDraw.Draw(imn)
for y in range(0, im.size[1]):
for x in range(0, im.size[0]):
pp = im.getpixel((x, y))
d.text((x * f_size, y * f_size), font_map[len(font_map) - pp - 1], fill=255, font=f)
save(imn, img_name)
将处理之后的图片保存下来:
def save(img, file_name):
if os.path.isfile(file_name + '.jpg'):
save(img, file_name + '-')
else:
img.save(file_name + '.jpg', 'JPEG')
调用主函数:
if __name__ == '__main__':
tt = time.time()
main()
print(time.time() - tt)
动态图像处理
命令行输入参数处理:
parser = argparse.ArgumentParser()
parser.add_argument('file')
parser.add_argument('-d','--duration',type = float, default = 1)#播放时间
获取参数:
args = parser.parse_args()
File = args.file
DURARION = args.duration
像素对应ASCII码:
ascii_char = list("MNHQ$OC67+>!:-. ")
获取ASCCI码:
def get_char(r,g,b,alpha = 256):
if alpha == 0:
return ''
length = len(ascii_char)
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
unit = (256.0+1)/length
return ascii_char[int(gray/unit)]
将txt转化为图片:
def txt2png(file_name):
im = Image.open(file_name).convert('RGB')
#gif拆分后的图像,需要转换,否则报错,由于gif分割后保存的是索引颜色
raw_width = im.width
raw_height = im.height
width = int(raw_width/6)
height = int(raw_height/15)
im = im.resize((width,height),Image.NEAREST)
txt=""
colors = []
for i in range(height):
for j in range(width):
pixel = im.getpixel((j,i))
colors.append((pixel[0],pixel[1],pixel[2]))
if(len(pixel) == 4):
txt += get_char(pixel[0],pixel[1],pixel[2],pixel[3])
else:
txt += get_char(pixel[0],pixel[1],pixel[2])
txt += '\n'
colors.append((255,255,255))
im_txt = Image.new("RGB",(raw_width,raw_height),(255,255,255))
dr = ImageDraw.Draw(im_txt)
font=ImageFont.load_default().font
x=y=0
font_w,font_h=font.getsize(txt[1]) #获取字体的宽高
font_h *= 1.37 #调整后更佳
#ImageDraw为每个ascii码进行上色
for i in range(len(txt)):
if(txt[i]=='\n'):
x+=font_h
y=-font_w
dr.text([y,x],txt[i],colors[i])
y+=font_w
name = file_name.split('.')[0]+'-txt'+'.png'
print(name)
im_txt.save(name)
拆分gif:
def gif2png(file_name):
im = Image.open(file_name)
path = os.getcwd()
if(not os.path.exists(path+"/Cache")):
os.mkdir(path+"/Cache")
os.chdir(path+"/Cache")
try:
while 1:
current = im.tell()
name = file_name.split('.')[0]+'-'+str(current)+'.png'
im.save(name)#gif分割后保存的是索引颜色
print(name)
txt2png(name)
im.seek(current+1)
except:
os.chdir(path)
转换为gif:
def png2gif(dir_name):
path = os.getcwd()
os.chdir(dir_name)
dirs = os.listdir()
images = []
num = 0
for d in dirs:
if d.split('-')[-1] == 'txt.png':
images.append(imageio.imread(d))
num += 1
os.chdir(path)
imageio.mimsave(d.split('-')[0]+'-txt_c.gif',images,duration = DURARION)
主函数:
if __name__=='__main__':
gif2png(File)
path = os.getcwd()
png2gif(path+"/Cache")
详情请查看源码请自行去github,或者点击文末的阅读原文获取源码。
https://github.com/zandaoguang/pic_to_char
结果
当我跑完代码之后,出现了上边这张黑糊糊的图,这是什么鬼?
看了下边这个图才看出来一些模样~
确实好丑啊
![640?wx_fmt=jpeg](https://i-blog.csdnimg.cn/blog_migrate/45d31d9ee80a27796eae8b325ffe913c.jpeg)
从清华巧那儿学到了爱的五种语言
1.语言上对对方的赞美
2.物质上的表达
3.拿出一些时间陪伴对方
4.讨好彼此,服务彼此的行动;你喜欢的,我为你泡杯茶
5.身体上的接触
敲得代码都是爱你的形状。
爱情是什么?我把它比作
张爱玲的
“你还不来,我怎敢老去?”
方文山的
“天青色等烟雨,而我在等你。”
元稹的
“曾经沧海难为水,除却巫山不是云”
冯唐的
“春水初生,春林初盛,春风十里,不如你。”
红豆生南国,春来发几枝。
愿君多采撷,此物最相思。
醒醒,别一直看这个图了!
(我至少看了n遍)
活着本来没有什么意义
但是活着,就可以找到有趣的事情。
就像你发现了这多花
而我发现了你
人生在世只有一次
不必勉强选择自己不喜欢的路
随性而生或随性而死都没关系
不过,无论选择哪条路
都不要忘记保护自己所珍惜的人
群聊交流
我创建了两个群,为读者提供了分享知识、传递正能量的平台:
视学算法硕博学术交流群
视学算法就业交流群
添加学姐微信,拉你进群
务必备注:硕博或者就业
福利一刻
视学算法特此感谢电子工业出版社的独家赞助,电子工业出版社已出版《你也能看得懂的Python算法书》
此前,本书正处于预售状态。11月26号视学算法将和电子工业出版社联合赠送数十本。