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使用PyV8执行javascript代码示例分享
Dec 04 Python
python django集成cas验证系统
Jul 14 Python
Python基于PycURL自动处理cookie的方法
Jul 25 Python
遍历python字典几种方法总结(推荐)
Sep 11 Python
老生常谈python之鸭子类和多态
Jun 13 Python
python基础之包的导入和__init__.py的介绍
Jan 08 Python
Python进程间通信Queue消息队列用法分析
May 22 Python
详解利用Python scipy.signal.filtfilt() 实现信号滤波
Jun 05 Python
Python整数与Numpy数据溢出问题解决
Sep 11 Python
使用TensorFlow对图像进行随机旋转的实现示例
Jan 20 Python
获取python运行输出的数据并解析存为dataFrame实例
Jul 07 Python
Python学习之异常中的finally使用详解
Mar 16 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 内存缓存加速功能memcached安装与用法
2009/09/03 PHP
php结合正则批量抓取网页中邮箱地址
2015/05/19 PHP
php如何控制用户对图片的访问 PHP禁止图片盗链
2016/03/25 PHP
总结PHP中DateTime的常用方法
2016/08/11 PHP
JQuery.ajax传递中文参数的解决方法 推荐
2011/03/28 Javascript
Javascript遍历table中的元素示例代码
2014/07/08 Javascript
javascript页面倒计时实例
2015/07/25 Javascript
使用impress.js制作幻灯片
2015/09/09 Javascript
JavaScript中定义类的方式详解
2016/01/07 Javascript
jQuery插件ImageDrawer.js实现动态绘制图片动画(附源码下载)
2016/02/25 Javascript
基于jQuery实现一个marquee无缝滚动的插件
2017/03/09 Javascript
Vue 多层组件嵌套二种实现方式(测试实例)
2017/09/08 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
2018/08/10 Javascript
关于layui 实现点击按钮添加一行(方法渲染创建的table)
2019/09/29 Javascript
用JS实现一个简单的打砖块游戏
2019/12/11 Javascript
Vue中的nextTick作用和几个简单的使用场景
2021/01/25 Vue.js
使用webpack和rollup打包组件库的方法
2021/02/25 Javascript
Python统计文件中去重后uuid个数的方法
2015/07/30 Python
好用的Python编辑器WingIDE的使用经验总结
2016/08/31 Python
Python3下错误AttributeError: ‘dict’ object has no attribute’iteritems‘的分析与解决
2017/07/06 Python
django多文件上传,form提交,多对多外键保存的实例
2019/08/06 Python
Python使用itchat模块实现简单的微信控制电脑功能示例
2019/08/26 Python
python实现井字棋小游戏
2020/03/04 Python
html5中JavaScript removeChild 删除所有节点
2014/05/16 HTML / CSS
前端水印的简单实现代码示例
2020/12/02 HTML / CSS
Abe’s of Maine:自1979以来销售相机和电子产品
2016/11/21 全球购物
Moda Italia荷兰:意大利男士服装
2019/08/31 全球购物
英国在线药房和在线医生:LloydsPharmacy
2019/10/21 全球购物
eHarmony英国:全球领先的认真恋爱约会平台之一
2020/11/16 全球购物
过程装备与控制工程专业个人的求职信
2013/12/01 职场文书
装修致歉信
2014/01/15 职场文书
机关财务管理制度
2014/01/17 职场文书
四风问题对照检查整改措施思想报告
2014/10/05 职场文书
开幕式邀请函
2015/01/31 职场文书
Django实现在线无水印抖音视频下载(附源码及地址)
2021/05/06 Python