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 相关文章推荐
Django imgareaselect手动剪切头像实现方法
May 26 Python
Python字符编码判断方法分析
Jul 01 Python
Python使用functools模块中的partial函数生成偏函数
Jul 02 Python
你应该知道的python列表去重方法
Jan 17 Python
python中seaborn包常用图形使用详解
Nov 25 Python
python实现根据给定坐标点生成多边形mask的例子
Feb 18 Python
pycharm如何实现跨目录调用文件
Feb 28 Python
Python3 利用face_recognition实现人脸识别的方法
Mar 13 Python
django 取消csrf限制的实例
Mar 13 Python
python实现经典排序算法的示例代码
Feb 07 Python
Python利用机器学习算法实现垃圾邮件的识别
Jun 28 Python
Python实现仓库管理系统
May 30 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实现的网络相册图片防盗链完美破解方法
2015/07/01 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
2015/12/10 PHP
CentOS 7.2 下编译安装PHP7.0.10+MySQL5.7.14+Nginx1.10.1的方法详解(mini版本)
2016/09/01 PHP
PHP+ajax实现获取新闻数据简单示例
2018/05/08 PHP
jQuery语法总结和注意事项小结
2012/11/11 Javascript
关于jQuery新的事件绑定机制on()的使用技巧
2013/04/26 Javascript
js计算字符串长度包含的中文是utf8格式
2013/10/15 Javascript
原生js做的手风琴效果的导航菜单
2013/11/08 Javascript
Jquery在指定DIV加载HTML示例代码
2014/02/17 Javascript
Javascript学习笔记之函数篇(四):arguments 对象
2014/11/23 Javascript
jQuery预加载图片常用方法
2015/06/15 Javascript
js实现新浪微博首页效果
2015/10/16 Javascript
举例讲解jQuery中可见性过滤选择器的使用
2016/04/18 Javascript
JSONP和批量操作功能的实现方法
2016/08/21 Javascript
利用Javascript实现简单的转盘抽奖
2017/02/13 Javascript
layer弹出层框架alert与msg详解
2017/03/14 Javascript
jquery Ajax实现Select动态添加数据
2017/06/08 jQuery
react系列从零开始_简单谈谈react
2017/07/06 Javascript
Vue2.0 axios前后端登陆拦截器(实例讲解)
2017/10/27 Javascript
微信小程序事件对象中e.target和e.currentTarget的区别详解
2019/05/08 Javascript
Vue.js 中制作自定义选择组件的代码附演示demo
2020/02/28 Javascript
简单了解JavaScript作用域
2020/07/31 Javascript
在webstorm中配置less的方法详解
2020/09/25 Javascript
简单理解Python中基于生成器的状态机
2015/04/13 Python
Python验证码识别处理实例
2015/12/28 Python
Python中常用操作字符串的函数与方法总结
2016/02/04 Python
使用Python的Flask框架构建大型Web应用程序的结构示例
2016/06/04 Python
Python 访问限制 private public的详细介绍
2018/10/16 Python
Python识别html主要文本框过程解析
2020/02/18 Python
浅谈pytorch中的BN层的注意事项
2020/06/23 Python
利用scikitlearn画ROC曲线实例
2020/07/02 Python
css3动画效果小结(推荐)
2016/07/25 HTML / CSS
美国背景检查、公共记录和人物搜索网站:BeenVerified
2018/02/25 全球购物
电气自动化专业职业规划范文
2014/02/16 职场文书
政法干警核心价值观心得体会
2014/09/11 职场文书
​(迎国庆)作文之我爱我的祖国
2019/09/19 职场文书