[关闭]
@gongsheng 2018-01-13T13:37:11.000000Z 字数 2352 阅读 1234

python 图片转字符画

python


本篇的重点是实验过程中牵扯的很多知识。最终效果只是个附属品,原因之一:字符数(选取了70个字符)和它的排列情况还没达到使字符画精致的程度。
先看效果:
原图:

此处输入图片的描述

下载地址

效果图(少部分未能截取):

此处输入图片的描述

你将在本文接触到这些词:


1. 准备

在命令 pip install pillow 安装 pillow(python 的图像处理库)。

pillow官方文档 中规定,导入包的方式为:

from PIL import Image

而不是平常的 import pillow
官方文档截图(注意标记):

此处输入图片的描述

注 1:PIL 图像处理库很遗憾地只支持 Python2,但是它的分支 pillow 弥补了位置。安装之后你会发现 site-packages 文件夹里除了 pillow 还有 PIL 库,但你绝对不能按照惯性的导包思路操作,因为那是官方规定。

此处输入图片的描述

注 2:因为 pillow 的依赖包 olefile 存在无关紧要的一个编码 bug (olefile 的作者在 GitHub 提到),但是它会让你安装 pillow 不是那么顺利,在
pip install pillow 时,工具自动下载并安装它的依赖包,虽然报了编码错误,olefile 还是完成安装,在这基础上,pillow 需要再次 pip install

报错:
此处输入图片的描述

pillow的安装停止(pip show 没有显示 pillow 的信息):

此处输入图片的描述

2. 贴代码逐行分析

此处输入图片的描述

到这里,如果你的目的只是字符画,这个教程就结束了,只要你懂得如何运行一个 Python 代码文件,就可以得到最终效果。


符号解释:-1 为代码第1行,代码解释从起始行开始,无结束行

此处输入图片的描述
此处输入图片的描述
此处输入图片的描述

没有判断 alpha 为 0 的效果如下:

此处输入图片的描述

gray = 0.2126*r+0.7152*g+0.0722*b

这是代码中的第一个重要式子,是科学公式,gray 就是我们要算的灰度值,它对 rgb 取不同比例得出,三个系数和为 1, 所以 gray 的上限值为 255 。下限0 。

['$', '@', 'B', '%', '8', '&', 'W', 'M', '#', '*', 'o', 'a', 'h', 'k',
'b', 'd', 'p', 'q', 'w', 'm', 'Z', 'O', '0', 'Q', 'L', 'C', 'J', 'U',
'Y', 'X', 'z', 'c', 'v', 'u', 'n', 'x', 'r', 'j', 'f', 't', '/', '\',
'|', '(', ')', '1', '{', '}', '[', ']', '?', '-', '_', '+', '~', '<',
'>', 'i', '!', 'l', 'I', ';', ':', ',', '"', '^', '`', "'", '.', ' ']

x = int(gray/256*len(ascii_char))

这是第二个重要式子。它将灰度值映射到列表里的字符上。你可以把分母的 256 换成其他值,但是它要在一个范围内,最终目的是把 0~255 映射为 0~69,所以你取的值不能使x越界(为说明方便,分母为 a,那么a要满足:
255 < a <258.695652,由以下两个式子推导)
使

恒成立
这能保证x的取值不会是70及以上。
并且当 gray=255 时,

这能保证x最大值能取到69


源码:

  1. from PIL import Image
  2. def get_char(r, g, b, alpha):
  3. # if alpha == 0:
  4. # return ' '
  5. gray = 0.2126*r+0.7152*g+0.0722*b
  6. ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
  7. x = int(gray/256*len(ascii_char))
  8. return ascii_char[x]
  9. def main(file_name, width=80,height=30):
  10. text=''
  11. im = Image.open(file_name)
  12. im = im.resize((width, height), Image.NEAREST)
  13. for i in range(height):
  14. for j in range(width):
  15. content = im.getpixel((j, i))
  16. text +=get_char(*content)
  17. text +='\n'
  18. print(text)
  19. if __name__ == '__main__':
  20. main(file_name='ascii_dora.png')

注:图片和 python 文件同目录。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注