Python下字符画(ascii art)生成
之前在b站上看到有人用C写了个脚本把妹抖龙op转换成字符画的形式输出了,感觉比较好玩在下就用python也写了一遍(主要是因为python比较简单好用)。这里就这里就不介绍字符画了,因为能搜到这个的肯定知道自己在干什么 = =。
首先梳理转换思路:转换图片也就是转换视频,因为视频就是有连续的图片组成的。而为了简单起见,我们这里先把彩色图片先转换成黑白图片(将RGB三通道转换成一个),然后读取图片的每个像素点,根据像素点的灰度(grayscale)选择相应的字符(比如@#对应高灰度点,而.,对应低灰度点),将所有当前图片或帧的像素转换成字符后输出就是我们看到的字符画了。
这里我们可以看到这其实是一个很简单的事,最重要无非就是要根据灰度选择字符。这一点已经有好事者统计每个字符所占的像素帮大家做了(参考)。
完整版(灰度从高到低排列,注意最后的空白字符):$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,"^\'. 而在实际应用中,发现**精简版**的打印效果更好(其实可以自己随便挑一些):@%#*+=-:. `
代码实现:
为了简单起见,这里只讲如何将视屏直接打印到到终端(输出为黑白,不保留颜色),至于输出为其他文件形式具体可以参考这里
1.读取图片或视频
这里我们用Pillow或者opencv包进行图片读取和处理,后者可以用于视频操作,但是由于opencv读取视频的格式只支持avi,所以进行视频处理的时候我们需要另一个包:scikit-video;而如果是转换图片,那么写出可以用matplotlib包。
import skvideo.io
import cv2
def read_image(image_path, method="opencv"):
if self.method == "pillow":
img = PI.open(image_path)
grey_image = img.convert("L")
elif self.method == "opencv":
img = cv2.imread(image_path)
grey_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
return grey_image
def read_video(video_path):
videogen = skvideo.io.vreader(video_path)
for frame in videogen:
grey_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
yield grey_frame # 由于视频包含的图片很多,为了防止一次处理的内存过大,这里用generator逐帧返回图片
- 将读取的图片各像素点转换成相应的字符
STANDARD_CHAR_LIST = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^'\`. ")
ABBREVIATED_CHAR_LIST = list("@%#*+=-:. ")
def img2ascii(grey_image, char_list=ABBREVIATED_CHAR_LIST, scale=1.0, method='pillow'):
if method == 'pillow':
scaled_img_width = int(grey_image.size[0] * scale) # 按比例放大或缩小图片
scaled_img_height = int(grey_image.size[1] * scale)
scaled_grey_img = grey_image.resize((scaled_img_width, scaled_img_height))
elif method == 'opencv':
scaled_grey_img = cv2.resize(grey_image, None, fx=scale, fy=scale)
scaled_img_width = len(scaled_grey_img[0])
scaled_img_height = len(scaled_grey_img)
char_list_length = len(char_list)
ascii_img = [[None for i in range(scaled_img_width)] for j in range(scaled_img_height)]
ascii_color = [x[:] for x in ascii_img]
for i in range(scaled_img_height):
for j in range(scaled_img_width):
if self.method == "pillow":
# brightness: the larger, the brighter, and later position in given char list
brightness = scaled_grey_img.getpixel((j, i))
elif self.method == "opencv":
brightness = scaled_grey_img[i, j]
ascii_img[i][j] = char_list[brightness * char_list_length / 255]
return ascii_img
3.打印图片/视频
打印图片和视频稍微有些不同,因为打印视频是希望能与原视频播放同步,因此实时读取转换打印的时间是无法在0.0278s(默认24帧/1s)内完成的,需要先将转换结果保存到数组然后再依次打印。
a)图片
output_str = ""
for line in ascii_img:
output_str += "".join(line) + "\n"
os.system(self.clear_console)
sys.stdout.write(output_str)
b)视频
total_video = []
video_temp_file = video_path + ".temp"
if not os.path.exists(video_temp_file):
with open(video_temp_file, "wb") as of:
first_frame = True
for grey_frame in read_video(video_path):
ascii_img = self.img2ascii(grey_image=grey_frame, char_list=char_list, scale=scale)
output_str = ""
for line in ascii_img:
output_str += "".join(line) + "\n"
total_video.append(output_str)
if first_frame:
of.write("{}\n".format(len(ascii_img))) # 再文件开头保存打印每一帧所需的行数
first_frame = False
of.write(output_str)
of.close()
else:
row = 1
frame_str = ""
with open(video_temp_file, "rb") as fi:
frame_row = int(fi.readline().strip())
for line in fi:
frame_str += line
if row % frame_row == 0:
total_video.append(frame_str)
frame_str = ""
row += 1
fi.close()
for frame in total_video:
sys.stdout.write(frame)
sys.stdout.flush() # 清空屏幕
sys.stdout.write("\x1b[0;0H") # 重新定位打印光标于最开始的为止(0,0)
time.sleep(0.015) # 设置与下一帧的打印时间间隔
注意:这里要选择将中间字符保存到文件,然后再读取打印,这是因为在打印的过程中读取和打印都需要时间,所以如果设置sleep时间为0.0278,那么将会出现播放时间延迟不同步,因此需要调整sleep的时间。为了避免每次调试重新转化需要大量时间,这里就进行了保存。
总结:转换图片到字符画并不是什么难的事情,不过在下发现转换以后的字符画跟原图相比就跟打了码一样,那么不免想到不妨用DL技术训练一个模型用于还原万恶的马赛克,岂不美哉2333
参考
http://paulbourke.net/dataformats/asciiart/
http://pillow.readthedocs.io/en/3.0.x/handbook/tutorial.html
opencv官方文档(随便找找,这边忘了链接就不给了)
Python下字符画(ascii art)生成的更多相关文章
- python中字符与ascii码转换
ASCII码转字符用chr()函数: 字符转ASCII码用ord()函数:
- 图片处理拓展篇 : 图片转字符画(ascii)
首先要明确思路, 图片是由像素组成的, 不同的像素有不同的颜色(rgb), 那么既然我们要转化为字符画, 最直接的办法就是利用字符串来替代像素, 也就是用不同的字符串来代表不同的像素. 另外图片一般来 ...
- python学习 —— 字符画
代码: import os from PIL import Image WIDTH = int(250) HEIGHT = int(250/2) ascii_char = list('toahkbdp ...
- AsciiMorph - 新奇的 ASCII 字符画生成工具&插件
AsciiMorph 是一个新奇的 ASCII 字符画生成工具和开源插件.字符画(ASCII Art)的历史可以追溯到几十年前,起初是用在图形显示功能受限的设备上,用ASCII字符集里的可打印字符来拼 ...
- 使用Python生成ASCII字符画
使用Python生成ASCII字符画 在很多的网站主页中或者程序的注释中会有一些好看的字符注释画.显得很牛逼的样子 例如: 知乎 _____ _____ _____ _____ /\ \ /\ \ / ...
- python生成字符画
python生成字符画 这个idea来自于实验楼,非常适合练习PIL的像素处理,更重要的是非常有意思. 环境配置 依赖的第三方库就是PIL(Python Image Library),可以直接使用pi ...
- 将图片转为ASCII字符画
原文:将图片转为ASCII字符画 Copyright 2012 Conmajia 源代码下载:点击这里 什么是字符画?就是用ASCII字符来近似组成图像,就像这样: ╭╮ ╭╮ ││ ││ ╭┴┴—— ...
- Python 图片转字符画
Python 图片转字符画 一.课程介绍 1. 课程来源 原创 2. 内容简介 本课程讲述怎样使用 Python 将图片转为字符画 3. 前置课程 Python编程语言 Linux 基础入门(新版) ...
- python图片转字符画(转)
先上代码: from PIL import Image import argparse #命令行输入参数处理 parser = argparse.ArgumentParser() parser.add ...
随机推荐
- Java编程的逻辑 (63) - 实用序列化: JSON/XML/MessagePack
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- java中反向转义org.apache.commons.lang3.StringEscapeUtils.unescapeJava
工具类中包含类反向转义的方法: eorderHistory.setSubPrintTemplates(StringEscapeUtils.unescapeJava(eorderHistory.getS ...
- linux 计划任务(十)
[教程主题]: 计划任务 [1]at 在windows系统中,windows提供了计划任务这一功能,在控制面板 -< 性能与维护 -< 任务计划, 它的功能就是安排自动运行的任务. 通过' ...
- 阿里云扩容数据盘_Linux
扩容数据盘_Linux 更新时间:2018-10-11 15:18:46 · 编辑者 编辑 · ★ 我的收藏 新手学堂 学习路径 本页目录 前提条件 注意事项 步骤 1. 在控制台上扩容数据盘的磁盘空 ...
- Listener 监听Session内的对象
Listener用于监控Session内的对象,分别是HttpSessionBindingListener与HttpSessionActivationListener.它们的触发时机分别为: Http ...
- React Native常用第三方组件汇总--史上最全[转]
本文出处: http://blog.csdn.net/chichengjunma/article/details/52920137 React Native 项目常用第三方组件汇总: react-na ...
- js关于弹也遮罩层
1:什么是遮罩层 遮罩层:我是弹也一个(遮罩层)还有一个(内容层),下面上图片看一效果 我们看到一个灰蒙蒙的遮盖(其实也是一个层)还有一个层(也就是我们展示的内容). 2: 弹出层效果居中分析 在这 ...
- SpannableString属性详解
1.BackgroundColorSpan 背景色 2.ClickableSpan 文本可点击,有点击事件 3.ForegroundColorSpan 文本颜色(前景色) 4.Ma ...
- (笔记)Linux Root下的.gvfs出现异常解决办法
在linux系统下安装软件或复制文件的时候,复制不成功,出现错误如下: error: failed to stat /home/dade/.gvfs: Permission denied. 表面上看: ...
- 【总结】牛客职播第九期:您的美团点评offer已送到门口,快来与我们一起影响世界!
一.介绍 美团点评2018校园春招流程介绍&面试答疑 讲师:燕鹏.Taylor 二.收获 面试时如果太紧张或者内向,容易吃亏,所以建议把面试当做展示自己的一次舞台. 遇见一道编程题目,如果无法 ...