ASCII Art之tone-based生成方法实现

来源:互联网 发布:幼儿教师美工作品图片 编辑:程序博客网 时间:2024/06/10 20:17

ASCII Art之tone-based生成方法实现

  • ASCII Art之tone-based生成方法实现
    • 前言
    • tone-based方法原理
    • 灰度等级的选取
    • 代码实现
    • 使用ascii字符表示动图

前言

大家好我又回来了……其实开这个系列完全是为了熟悉Markdown语法。但是想了想还是有必要有始有终,于是准备按计划填坑。这篇文章讲解tone-based方法生成ascii图像的实现。

1.tone-based方法原理

我们知道图像的像素点是由RGB三种颜色构成的,而在上古时代还没有发明彩色显示屏的时候。图像都是以灰度图的方式进行呈现,每个像素点只包含亮度一个信息。

我们谈论像素的时候,谈论的是一个抽象的概念,它是对图像基本单位的一种抽象。事实上,不同的设备,像素点的大小,排布方式,亮度来源都不同。而由于真正决定人眼感受到的清晰度的指标是视野的张角,同样的像素分辨率在不同的距离,给人的感受可能不同。当离得足够远时,即使很大尺寸的像素点也可以很“清晰”;距离越近,看到的图像就越模糊。介于人对于低分辨率图像的识别能力还是比较强的。这就构成了tone-based方法生成ascii art的理论基础。即使用单个字符代替像素点,来表示降采样后的图像(低分辨率版本的图像)。

评价一张图像,我们除了要看其分辨率大小,还要看它的颜色鲜艳程度。对于灰度图来说,我们需要关心的是像素点能够表达多少种不同的亮度,也即灰度等级。那么随之而来的一个问题是,ascii字符能够表示多少灰度等级?或者说,同种颜色打印的ascii字符为什么能够表示不同的灰度?首先我们来看一张图。

pic

如图,眯着眼睛看是玛丽莲·梦露,仔细看是爱因斯坦。之所以会出现这种状况,是因为眯着眼睛时,我们的眼睛自动过滤了图像中的高频部分,而只关注了图像的轮廓,此时人物的形象就会发生变化。

类似的,我们在看低分辨率图像时,人眼也相当于一个低通滤波器。对于高频信息会不自觉的丢弃,从而在较大的尺度上获得不同的视觉体验。上世纪喷墨式打印机还没出现时,针式打印机为获得较好的视觉效果,也使用过类似的trick,以较细尺度的点的密度来表现较高尺度“点”的灰度。以相同大小的字符作为像素。因此,要使用字符表达不同亮度的像素点,只需要改变字符点阵所占的比例即可,即,利用不同的ascii字符的大小不同来表示不同的像素。经过人脑的低通滤波,它们就变成不同亮度的像素点了以字符的点阵面积代表不同的灰度等级,这就是tone-based方法的基本思路。

2.灰度等级的选取

我们日常见到的灰度图的像素点都是8bit存储的,即使用了256个灰度等级。受限于字符本身的数量与字体,ascii字符所能表达的灰度等级要远远低于这个值。在此,我们选取八种字符(当然,理论上效果较好的方法是统计字符点阵数量并进行排序和分级,然而实验发现并非如此。)代表8种不同的灰度等级。即:

graylevels = [' ', '.', '-', '+', '*', '%', '#', '&']

对应的,将0~255的灰度均分为8个灰度等级。

3.代码实现

代码使用python3进行实现,用到了PIL库进行图像的灰度化和缩放。具体如下:

#!/usr/bin/pythonimport osimport sysfrom PIL import Imagedef tone_based_ascii(img):    'convert img to ascii art using tonebased method'    graylevels = [' ', '.', '-', '+', '*', '%', '#', '&']    img.convert('L')    (height, width) = os.popen('stty size', 'r').read().split()    height, width = int(height), int(width)    img = img.resize((width, height), 1)    data = img.tobytes()    ascii_pic_list = [levels[7-i//32] for i in data]    return "".join(ascii_pic_list)def main():    'main module'    img = Image.open(sys.argv[1])    print("\033[1;1H\033\n")    print(tone_based_convert(img,tone_table))if __name__ == '__main__':    main()

调用方法为python3 tonbased.py lena.jpg
得到图像如下
pic

4.使用ascii字符表示动图

将动图中每一帧的图像分解出来输入tone_based_ascii函数就可以将gif图转换成ascii art。具体代码可以参考这里

以上。
(下一篇要讲机器学习了么想想还有点小激动呢)

0 0
原创粉丝点击