发现不一样的自己---生成字符画

python 图像转成字符画

前言

最近没什么事研究一下python,发现一个图像转字符图的demo,我试了一下
发现最后生成的是txt文件,感觉不太好看。
所以我改了一下,让他最后生成的是png图像

实现步骤

首先选一张图片—>转化成字符txt文档—>读取txt文档,转换成图像—>保存

实现代码

环境

python3.6

import PIL
import PIL.ImageFont
import PIL.Image
import PIL.ImageDraw
import PIL.ImageOps
import tkinter.filedialog
from tkinter import messagebox
import os
import datetime

代码

1.选择图片
	default_dir=r"d:\\"
    # 选择图片所在位置
    file_path=tkinter.filedialog.askopenfilename(title=u'选择图片jpg,png格式',initialdir=(os.path.expanduser(default_dir)))
    print(file_path)
    messagebox.showinfo("提示","正在生成字符画请稍后")
    #打开图片
    im=PIL.Image.open(file_path)
2.修改图片的尺寸

有的图片太大的话,生成的txt文件也大,处理的会很慢,最后一步生成图像时会更慢,还会导致内存不够

    #获取图片的宽和高
    newWidth=im.width
    newHeight=im.height
    #判断原图的尺寸,原图越大,修改后的尺寸越小
    if(newWidth>1500 or newHeight>1500):
        w = int(im.width*0.45)
        h = int(im.height/4)
    elif(newWidth>1000 or newHeight*1.8>1000):
        w = int(im.width * 1.8 / 2)
        h = int(im.height / 2)
    else:
        w = int(im.width * 0.9)
        h = int(im.height/2)
    #修改图片的尺寸
    im=im.resize((w,h),PIL.Image.NEAREST)
3.把图像中的像素的颜色值转换成字符
 for i in range(h):
        for j in range(w):
            txt+=get_char(*im.getpixel((j,i)))
        txt+='\n'
 #生成字符画所使用的的字符
 ascii_char=list(r"$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'.")
 #将256灰度映射到字符集上
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)] #不同灰度对应不同字符
    #通过灰度来区分色块


4.保存txt文件

保存txt文件,这时候你就得到了一个txt类型的字符画

 #选择文件保存的位置
    txtpath=file_path.replace('jpg','txt').replace('png','txt').replace('gif','txt')
    with open(txtpath,'w') as f:
        f.write(txt)
5.把txt文件转换成image文件

先生成img图像,在保存

5.1生成img图像

首先读取txt文件,把txt文件中的字符保存到一个元组中,
然后使用PIL创建一个空白图像
最后把txt文件中的字符作为文本添加到空白图像中,再去掉图像的空白部分就成功了

#txt转image
def text_image(text_path,font_path=None):
    grayscale='L'
    #解析txt文件,读取文件每行的字符,放到一个元组中
    with open(text_path) as text_file:
        lines=tuple(l.rstrip() for l in text_file.readlines())
        #rstrip :删除字符串结尾字符
        #tuple :元组
    large_font=10 #字体大小 字体越小生成的图片的大小也会越小
    font_path=font_path or 'cour.tff' 
    #创建一个字体对象
    try:
        font=PIL.ImageFont.truetype(font_path,size=large_font)
    except IOError:
        font=PIL.ImageFont.load_default()
        
    #制作背景图像根据 字体和线条
    pt2px=lambda pt: int(round(pt*96.2/72))
   
    # 获取lines元组中宽度最大的一个字符串
    #作为最后的图像的宽度
    max_width_line = max(lines, key=lambda s: font.getsize(s)[0])
   
    test_string=r"$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'."
    #获取字符串test_string的高度,转换成像素的高度
    max_height=pt2px(font.getsize(test_string)[1])

    #获取txt中宽度最大的字符串的宽度,转换成像素的宽度
    max_width=pt2px(font.getsize(max_width_line)[0])

    #图像的高度
    #每一行字符串的高度*字符串的行数
    height=max_height*len(lines)

    #图像的宽度
    width=int(round(max_width+20))
    
    #创建一张空白图片 grayscale:模式,L,RGB...
    image=PIL.Image.new(grayscale,(width,height),color=PIXEL_OFF)
    
    #创建一个可以用来对image进行操作的对象
    draw=PIL.ImageDraw.Draw(image)
    
    vertical_position=5 #垂直
    horizontal_position=5 #水平
    line_spacing=int(round(max_height*0.8)) #行间距
    
    #向空白图像上写入文本
    for line in lines:
        #向图片上写文字
        # (horizontal_position,vertical_position):开始的位置
        # line:内容
        #fill=PIXEL_ON,颜色
        # font=font 字体   draw.text((horizontal_position,vertical_position),line,fill=PIXEL_ON,font=font)
        vertical_position+=line_spacing
    print("结束写入文本:%s", datetime.datetime.now())
    #将输入图像转换为反色图像
    c_box=PIL.ImageOps.invert(image).getbbox()
    # image.resize((500, 500), PIL.Image.NEAREST)
    print("去掉图像的边框开始:%s", datetime.datetime.now())
    #去掉图像的边框
    image=image.crop(c_box)

    print("去掉图像的边框结束:%s", datetime.datetime.now())
    return image
5.2保存图像

保存图像之后在调整一下图像的大小,让新生成的字符画图像和原图大小一致,这样基本上就完成了

	#保存图像
    newPath=txtpath.replace('txt','png')
    image.save(newPath)
    #调整图像的大小
    ims = PIL.Image.open(newPath)
    out = ims.resize((newWidth, newHeight),PIL.Image.ANTIALIAS) 
    out.save(newPath, 'png')

最后

注意:原图不要太大,因为PIL操作图像时会造成内存泄漏,原图越大使用的内存越大,并且原图越大生成字符画所使用的的时间也越长
原代码在我的github上有需要的可以下载:https://github.com/p910/img-charImg
原代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将图片转化为字符。需要先安装PIL。推荐下载PIL包来实现。 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - - - - - - - - - - - - - - * * * * * * * * * * * * * * * * + + + + + + + + + + + + + + + + + + + + * - - - - - - - - - - - - - - - * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * - - - - - - - - - - - - - - - * * * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / / / / / / / / / / / / / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / / / / / / / / / / / / / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # / / / / / / / / / / / / / # # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # / / / / / / / / / / / / / # # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # / / / / / / / / / / / / / # # + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # # # # # # # # + / / - - - - - - - / # # # # # # # + + + + + + + + + + + + + + + + + + + + + + # # # # # # # # # # # # + / / - - - - - - - / # # # # # # # + + + + + + + + + + + + + + + + + + + # # # # # # # # # # # # # # # + / / / / / - - / / / # # # # # # # # # # + + + + + + + + + + + + + + + + # # # # # # # # # # # # # # # + / / / / / - - / / / # # # # # # # # # # + + + + + + + + + + + + + + + + # # # # # # # # # # # # # # # + / / / / / - - / / / # # # # # # # # # # + + + + + + + + + + + + + + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * + + + + + + + + + / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * + + + + + / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / / # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / / # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / /
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值