Python 实现图片转字符画的示例(静态图片,gif皆可)


Posted in Python onNovember 05, 2020

字符画是一种由字母、标点或其他字符组成的图画,它产生于互联网时代,在聊天软件中使用较多,本文我们看一下如何将自己喜欢的图片转成字符画。

静态图片

首先,我们来演示将静态图片转为字符画,功能实现主要用到的 Python 库为 OpenCV,安装使用 pip install opencv-python 命令即可。

功能实现的基本思路为:利用聚类将像素信息聚为 3 或 5 类,颜色最深的一类用数字密集度表示,阴影的一类用横杠(-)表示,明亮部分用空白表示。

主要代码实现如下:

def img2strimg(frame, K=5):  
  if type(frame) != np.ndarray:
    frame = np.array(frame)
  height, width, *_ = frame.shape 
  frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  frame_array = np.float32(frame_gray.reshape(-1))
  criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
  flags = cv2.KMEANS_RANDOM_CENTERS
  # 得到 labels(类别)、centroids(矩心)
  compactness, labels, centroids = cv2.kmeans(frame_array, K, None, criteria, 10, flags)
  centroids = np.uint8(centroids)
  # labels 的数个矩心以随机顺序排列,所以需要简单处理矩心
  centroids = centroids.flatten()
  centroids_sorted = sorted(centroids)
  # 获得不同 centroids 的明暗程度,0 为最暗
  centroids_index = np.array([centroids_sorted.index(value) for value in centroids])
  bright = [abs((3 * i - 2 * K) / (3 * K)) for i in range(1, 1 + K)]
  bright_bound = bright.index(np.min(bright))
  shadow = [abs((3 * i - K) / (3 * K)) for i in range(1, 1 + K)]
  shadow_bound = shadow.index(np.min(shadow))
  labels = labels.flatten()
  # 将 labels 转变为实际的明暗程度列表
  labels = centroids_index[labels]
  # 解析列表
  labels_picked = [labels[rows * width:(rows + 1) * width:2] for rows in range(0, height, 2)]
  canvas = np.zeros((3 * height, 3 * width, 3), np.uint8)
	# 创建长宽为原图三倍的白色画布
  canvas.fill(255)
  y = 8
  for rows in labels_picked:
    x = 0
    for cols in rows:
      if cols <= shadow_bound:
        cv2.putText(canvas, str(random.randint(2, 9)),
              (x, y), cv2.FONT_HERSHEY_PLAIN, 0.45, 1)
      elif cols <= bright_bound:
        cv2.putText(canvas, "-", (x, y),
              cv2.FONT_HERSHEY_PLAIN, 0.4, 0, 1)
      x += 6
    y += 6
  return canvas

原图如下:

Python 实现图片转字符画的示例(静态图片,gif皆可)

效果图如下:

Python 实现图片转字符画的示例(静态图片,gif皆可)

GIF 动图

接下来我们演示将 GIF 转为字符画,功能实现主要用到的 Python 库为 imageio、Pillow,安装使用 pip install imageio/Pillow 命令即可。

功能实现的基本思路如下:

将 gif 图片的每一帧拆分为静态图片
将所有静态图片变为字符画
将所有字符画重新合成 gif
主要代码实现如下:

# 拆分 gif 将每一帧处理成字符画
def gif2pic(file, ascii_chars, isgray, font, scale):
  '''
  file: gif 文件
  ascii_chars: 灰度值对应的字符串
  isgray: 是否黑白
  font: ImageFont 对象
  scale: 缩放比例
  '''
  im = Image.open(file)
  path = os.getcwd()
  if(not os.path.exists(path+"/tmp")):
    os.mkdir(path+"/tmp")
  os.chdir(path+"/tmp")
  # 清空 tmp 目录下内容
  for f in os.listdir(path+"/tmp"):
    os.remove(f)
  try:
    while 1:
      current = im.tell()
      name = file.split('.')[0]+'_tmp_'+str(current)+'.png'
      # 保存每一帧图片
      im.save(name)
      # 将每一帧处理为字符画
      img2ascii(name, ascii_chars, isgray, font, scale)
      # 继续处理下一帧
      im.seek(current+1)
  except:
    os.chdir(path)

# 将不同的灰度值映射为 ASCII 字符
def get_char(ascii_chars, r, g, b):
  length = len(ascii_chars)
  gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
  return ascii_chars[int(gray/(256/length))]


# 将图片处理成字符画
def img2ascii(img, ascii_chars, isgray, font, scale):
  scale = scale
  # 将图片转换为 RGB 模式
  im = Image.open(img).convert('RGB')
  # 设定处理后的字符画大小
  raw_width = int(im.width * scale)
  raw_height = int(im.height * scale)
  # 获取设定的字体的尺寸
  font_x, font_y = font.getsize(' ')
  # 确定单元的大小
  block_x = int(font_x * scale)
  block_y = int(font_y * scale)
  # 确定长宽各有几个单元
  w = int(raw_width/block_x)
  h = int(raw_height/block_y)
  # 将每个单元缩小为一个像素
  im = im.resize((w, h), Image.NEAREST)
  # txts 和 colors 分别存储对应块的 ASCII 字符和 RGB 值
  txts = []
  colors = []
  for i in range(h):
    line = ''
    lineColor = []
    for j in range(w):
      pixel = im.getpixel((j, i))
      lineColor.append((pixel[0], pixel[1], pixel[2]))
      line += get_char(ascii_chars, pixel[0], pixel[1], pixel[2])
    txts.append(line)
    colors.append(lineColor)
  # 创建新画布
  img_txt = Image.new('RGB', (raw_width, raw_height), (255, 255, 255))
  # 创建 ImageDraw 对象以写入 ASCII
  draw = ImageDraw.Draw(img_txt)
  for j in range(len(txts)):
    for i in range(len(txts[0])):
      if isgray:
        draw.text((i * block_x, j * block_y), txts[j][i], (119,136,153))
      else:
        draw.text((i * block_x, j * block_y), txts[j][i], colors[j][i])
  img_txt.save(img)

# 读取 tmp 目录下文件合成 gif
def pic2gif(dir_name, out_name, duration):
  path = os.getcwd()
  os.chdir(dir_name)
  dirs = os.listdir()
  images = []
  num = 0
  for d in dirs:
    images.append(imageio.imread(d))
    num += 1
  os.chdir(path)
  imageio.mimsave(out_name + '_ascii.gif',images,duration = duration)

原图如下:

Python 实现图片转字符画的示例(静态图片,gif皆可)

黑白效果图如下:

Python 实现图片转字符画的示例(静态图片,gif皆可)

彩色效果图如下:

Python 实现图片转字符画的示例(静态图片,gif皆可)

总结

本文我们利用 Python 演示了将静态图和 GIF 转为字符画的方法,大家如果有兴趣的话,可以将自己喜欢的图转一下,如果对转换效果不满意,还可以修改代码,改成自己满意的效果。

示例代码:py-ascii

以上就是Python 实现图片转字符画的示例(静态图片,gif皆可)的详细内容,更多关于python 图片转字符画的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
Mar 13 Python
python实现从字符串中找出字符1的位置以及个数的方法
Aug 25 Python
使用Python标准库中的wave模块绘制乐谱的简单教程
Mar 30 Python
python机器学习理论与实战(二)决策树
Jan 19 Python
Python爬取数据并写入MySQL数据库的实例
Jun 21 Python
详解python中的json和字典dict
Jun 22 Python
django foreignkey外键使用的例子 相当于left join
Aug 06 Python
python单例模式原理与创建方法实例分析
Oct 26 Python
Python实现名片管理系统
Feb 14 Python
python 实现读取csv数据,分类求和 再写进 csv
May 18 Python
Python之字典对象的几种创建方法
Sep 30 Python
Python实现学生管理系统并生成exe可执行文件详解流程
Jan 22 Python
Python中常用的os操作汇总
Nov 05 #Python
Python Web项目Cherrypy使用方法镜像
Nov 05 #Python
Python实现异步IO的示例
Nov 05 #Python
Python requests HTTP验证登录实现流程
Nov 05 #Python
Python包资源下载路径报404解决方案
Nov 05 #Python
如何一键升级Python所有包
Nov 05 #Python
python实现磁盘日志清理的示例
Nov 05 #Python
You might like
php cookie 作用范围?不要在当前页面使用你的cookie
2009/03/24 PHP
smarty模板引擎之内建函数用法
2015/03/30 PHP
codeigniter实现get分页的方法
2015/07/10 PHP
Zend Framework实现Zend_View集成Smarty模板系统的方法
2016/03/05 PHP
JS下高效拼装字符串的几种方法比较与测试代码
2010/04/15 Javascript
jQuery 定时局部刷新(setInterval)
2010/11/19 Javascript
cnblogs 代码高亮显示后的代码复制问题解决实现代码
2011/12/14 Javascript
深入理解javascript原型链和继承
2014/09/23 Javascript
自己动手写的javascript前端等待控件
2015/10/30 Javascript
基于javascript实现九宫格大转盘效果
2020/05/28 Javascript
学习AngularJs:Directive指令用法(完整版)
2016/04/26 Javascript
js轮播图的插件化封装详解
2017/07/17 Javascript
socket在egg中的使用实例代码详解
2019/05/30 Javascript
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
Python ORM框架SQLAlchemy学习笔记之关系映射实例
2014/06/10 Python
详解在Python的Django框架中创建模板库的方法
2015/07/20 Python
解决uWSGI的编码问题详解
2017/03/24 Python
python中退出多层循环的方法
2018/11/27 Python
Python实现将字符串的首字母变为大写,其余都变为小写的方法
2019/06/11 Python
详解Python 多线程 Timer定时器/延迟执行、Event事件
2019/06/27 Python
Python学习笔记之函数的参数和返回值的使用
2019/11/20 Python
python统计函数库scipy.stats的用法解析
2020/02/25 Python
Pymysql实现往表中插入数据过程解析
2020/06/02 Python
Html5 FileReader实现即时上传图片功能实例代码
2014/09/01 HTML / CSS
ALEX AND ANI:手镯,项链,耳环和更多
2017/04/20 全球购物
购买英国原创艺术:Art Gallery
2018/08/25 全球购物
Boolean b = new Boolean(“abcde”); 会编译错误码
2013/11/27 面试题
法律进机关实施方案
2014/03/12 职场文书
先进典型事迹材料
2014/12/29 职场文书
违纪检讨书范文
2015/01/27 职场文书
安全生产先进个人总结
2015/02/15 职场文书
学校工会工作总结2015
2015/05/19 职场文书
2015迎新晚会开场白
2015/05/29 职场文书
怎样写工作总结啊!
2019/06/18 职场文书
Redis集群新增、删除节点以及动态增加内存的方法
2021/09/04 Redis
Win10系统搭建ftp文件服务器详细教程
2022/08/05 Servers