python动态图片转字符画_用Python实现图画转换字符画

| 作者:阿广(中科院在读博士生)

| 来源:视学算法

在完成基于Python生成铅笔素描图后,朋友们对其非常感兴趣。不满足于现状,却局限于现状,对静态和动态的图画进行了字符画的转变,何尝不呈现出“几多风流、几多闲愁”的诗情画意。我不是画画的创造者,我是图画的修理工。

准备工作

对于静态图片,我们使用PIL做图像处理,所以需要安装下面的库:

fromPIL importImage, ImageDraw, ImageFont

importos

importtime

对于动态图片,我们需要导入以下库:

fromPIL importImage, ImageFont, ImageDraw

importargparse

importos

importimageio

识别原理

字符画是一系列字符的组合,我们可以把字符看作是比较大块的像素,一个字符能表现一种颜色,字符的种类越多,可以表现的颜色也越多,图片也会更有层次感。

问题来了,我们是要转换一张彩色的图片,这么多的颜色,要怎么对应到单色的字符画上去?这里就要介绍灰度值的概念了。

灰度值:指黑白图像中点的颜色深度,范围一般从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)

foryin range(0, im.size[1]):

forxin 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)

将处理之后的图片保存下来:

defsave(img, file_name):

ifos.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):

ifalpha == 0:

return''

length = len(ascii_char)

gray = int(0.2126* r + 0.7152* g + 0.0722* b)

unit = (256.0+1)/length

returnascii_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 = []

fori in range(height):

forjin 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码进行上色

fori 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:

while1:

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

ford in dirs:

ifd.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

结果

3bf7e6db0a934c72823d8d055e16b098.jpeg

当我跑完代码之后,出现了上边这张黑糊糊的图,这是什么鬼?

3246fabf8f8c436d877fdd941bcd96b0.jpeg

看了下边这个图才看出来一些模样~

确实好丑啊

59f8af7ceef94300ab047065f63524e6.jpeg

从清华巧那儿学到了爱的五种语言

1.语言上对对方的赞美

2.物质上的表达

3.拿出一些时间陪伴对方

4.讨好彼此,服务彼此的行动;你喜欢的,我为你泡杯茶

5.身体上的接触

e186e178cc9e4ace8553b270a7b33295.jpeg

敲得代码都是爱你的形状。

ccdc7d1d715946c3a0b75a329f07d6e2.jpeg

爱情是什么?我把它比作

张爱玲的

“你还不来,我怎敢老去?”

方文山的

“天青色等烟雨,而我在等你。”

元稹的

“曾经沧海难为水,除却巫山不是云”

冯唐的

“春水初生,春林初盛,春风十里,不如你。”

45583b9ec1e34309b85950acaaae6482.jpeg

红豆生南国,春来发几枝。

愿君多采撷,此物最相思。

d8ad69b6ce2942a2900579822c5d6a80.jpeg

b35dc18d7e1244fa837fccb6d5a04dbd.gif

醒醒,别一直看这个图了!

(我至少看了n遍)

e53316b50d6a45da9d2c96be0deebefa.gif

活着本来没有什么意义

但是活着,就可以找到有趣的事情。

就像你发现了这多花

而我发现了你

7cd676cc780e430a8ae91ff9a6c1e564.gif

人生在世只有一次

不必勉强选择自己不喜欢的路

随性而生或随性而死都没关系

不过,无论选择哪条路

都不要忘记保护自己所珍惜的人

ebcb61c73eee4a59a224a13f03a9b8c9.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值