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 相关文章推荐
利用QT写一个极简单的图形化Python闹钟程序
Apr 07 Python
Python中关于字符串对象的一些基础知识
Apr 08 Python
python实现装饰器、描述符
Feb 28 Python
python入门前的第一课 python怎样入门
Mar 06 Python
python中的turtle库函数简单使用教程
Jul 23 Python
Django项目中使用JWT的实现代码
Nov 04 Python
python自动分箱,计算woe,iv的实例代码
Nov 22 Python
Python面向对象封装操作案例详解
Dec 31 Python
Jupyter Notebook 实现正常显示中文和负号
Apr 24 Python
Python读取JSON数据操作实例解析
May 18 Python
Python 保存加载mat格式文件的示例代码
Aug 04 Python
区分python中的进程与线程
Aug 13 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&amp;mysql(三)
2006/10/09 PHP
DISCUZ 论坛管理员密码忘记的解决方法
2009/05/14 PHP
php 文章采集正则代码
2009/12/28 PHP
有关php运算符的知识大全
2011/11/03 PHP
PHP+Ajax+JS实现多图上传
2016/05/07 PHP
php+js实现点赞功能的示例详解
2020/08/07 PHP
javascript 计算两个整数的百分比值
2009/12/26 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(下:动画篇)
2010/03/24 Javascript
jquery动态改变onclick属性导致失效的问题解决方法
2013/12/04 Javascript
封装好的js判断操作系统与浏览器代码分享
2015/01/09 Javascript
JavaScript 模块化编程(笔记)
2015/04/08 Javascript
JS实现很实用的对联广告代码(可自适应高度)
2015/09/18 Javascript
Jquery easyui 实现动态树
2015/11/17 Javascript
JS使用正则截取两个字符串之间的字符串实现方法详解
2017/01/06 Javascript
jQuery快速实现商品数量加减的方法
2017/02/06 Javascript
解决vue里碰到 $refs 的问题的方法
2017/07/13 Javascript
JS中利用FileReader实现上传图片前本地预览功能
2018/03/02 Javascript
React Form组件的实现封装杂谈
2018/05/07 Javascript
uni-app之APP和小程序微信授权方法
2019/05/09 Javascript
JavaScript实现多文件下载方法解析
2020/08/07 Javascript
[11:01]2014DOTA2西雅图邀请赛 冷冷带你探秘威斯汀
2014/07/08 DOTA
Python中字典和JSON互转操作实例
2015/01/19 Python
python处理csv数据动态显示曲线实例代码
2018/01/23 Python
python 按照固定长度分割字符串的方法小结
2018/04/30 Python
浅谈python中np.array的shape( ,)与( ,1)的区别
2018/06/04 Python
python多进程提取处理大量文本的关键词方法
2018/06/05 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
简单了解django缓存方式及配置
2019/07/19 Python
你还在@微信官方?聊聊Python生成你想要的微信头像
2019/09/25 Python
HTML5使用ApplicationCache接口实现离线缓存技术解决离线难题
2012/12/13 HTML / CSS
Helly Hansen工作服美国官方网上商店:为最恶劣的环境
2019/09/04 全球购物
Seavenger官网:潜水服、浮潜、靴子和袜子
2020/03/05 全球购物
英国最大的天然和有机产品在线零售商之一:Big Green Smile
2020/05/06 全球购物
绿化工程实施方案
2014/03/17 职场文书
医学生毕业自我鉴定
2014/03/26 职场文书
五年级数学教学反思
2016/02/16 职场文书