原理很简单的,我们先来看看“字符”的产生,如果我们把一个方格放大N格,成为一个一个的格式,并用颜色替换,就会形成我们的字符如下图,那么由像素组成的图片也是如此的,只是每个格子里面放的是不同的色阶的颜色,也是我们常说的GRB色。
无标题.png

好丑的520,哈哈。把边框去了看看
111.png

现在总的来说一下实现的过程,就是在常见的RGB(A)模式图片中,利用每个像素点的R,G,B值按照公式转换成灰度值(0~255),然后在自己创建的字符表中找到灰度值对应的字符,添加到一个文本文件中,就实现了图片转字符画(黑白)。

但是此方法不适用于颜色种类丰富的图片,虽然有对应256个灰度值正好存在256个字符,可以完全区分不同的灰度值,但是毕竟一个像素和一个字符大小相差悬殊,转换后价值不大。

如果要转换一张宽高像素比较大的图片,除了使用ps等修图工具将像素改小,还可以使用pillow库改变图片大小。

以下是我利用pillow库函数把图片像素改小后的转换代码,代码是:

#!/usr/bin/python
#-*- coding:utf-8 -*-
from PIL import Image
import argparse

# 创建解析对象
parser = argparse.ArgumentParser()

# 向对象中添加命令行参数和选项
# 添加输入文件参数
parser.add_argument('file')
# 添加输出文件参数
parser.add_argument('-o', '--output')
# 添加输出字符画宽参数
parser.add_argument('-width', type = int, default = 80)
# 添加输出字符画高参数
parser.add_argument('-height', type = int, default = 80)
# 获取参数数据,使用parse_args()解析 解析对象
args = parser.parse_args()

其中o,width,height为非必须参数,参数数据类型默认为字符串,除非设置type属性,default为参数默认数据。

不加’-‘表示必须参数,同时也是参数名称,此时名称不可以通过添加’- -‘修改;

加’-‘表示可选参数,此时参数名称为当前,如果后面有加’- -‘的,则参数名称改为’- -‘紧接的字符串,此时’-o’和’–output’均可作为输入时的参数声明;

必须参数必须按照add_argument()的顺序添加参数值(中间可插入非必须参数),非必须参数可以打乱顺序,但需要参数名称和参数值一一对应

接下为是重头了,先来看看成果图

你能看出这是什么吗:
搜狗截图18年06月12日2321_1.png

好啦,原图是这样子的
4MfQNykY.jpg

怎么样,好玩吧,好那么要怎么写,才能实现这个效果呢,我就不卖关子了,来吧,上代码:

class character():
    def __init__(self):
    self.IMG = args.file
    self.WIDTH = args.width
    self.HEIGHT = args.height
    self.OUTPUT = args.output
    # 不同字符代表不同色块,字符最好不要重复
    self.ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
    self.txt = ''

    # 将256灰度映射到70个字符上
    # 图片格式为RGB的*im.getpixel((j,i)后会得到三个参数r(red),g(green),b(blue);RGBA得到四个参数r,g,b,alpha(透明度,0表示完全透明)
    # im.getpixel((j,i))得到一个由r, g, b, alpha(如果有的话)构成的元祖,加上*号即表示拆分元祖分别赋值引用
    def get_char(self, r, g, b, alpha = 256):
        # 如果是透明的,则输出空格
        if alpha == 0:
                return ' '
        length = len(self.ascii_char)
        # r,g,b转换为灰度值,白色是255,黑色是0
        gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
        # 单元字符的灰度值大小
        unit = (256.0 + 1)/length
        # 字符从小到大表示灰度值,已知灰度值大小,一个字符表示的灰度值大小,求该灰度值由第几个字符表示,ascii_char[i]
        return self.ascii_char[int(gray/unit)]

    def convert(self):
    im = Image.open(self.IMG)
    # im.resize(size,filter)
        # 变量filter为NEAREST、BILINEAR、BICUBIC或者ANTIALIAS之一
        # 如果忽略,或者图像模式为“1”或者“P”,该变量设置为NEAREST,速度快
        # ANTIALIAS 抗锯齿,质量最高;BICUBIC 三次样条插;BILINEAR 线性插值法
        im = im.resize((self.WIDTH,self.HEIGHT), Image.NEAREST)
        for i in range(self.HEIGHT):
            for j in range(self.WIDTH):
                self.txt += self.get_char(*im.getpixel((j,i)))
            self.txt += '\n'
    def save(self):
        if self.OUTPUT:
            with open(self.OUTPUT,'w') as f:
                f.write(self.txt)
        else:
            with open("output.txt",'w') as f:
                f.write(self.txt)
    def start(self):
    self.convert();
    self.save();

if __name__ == '__main__':
    c = character()
    c.start()

python picTostr.py –output picTostr_output.txt -height 50 test.jpg -width 100(打乱顺序)

对了,由于要用到PIL,所以你还需要安装这个模块,pip install pillow.

最后修改:2018 年 06 月 12 日
如果觉得我的文章对你有用,请随意赞赏