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 相关文章推荐
web.py在模板中输出美元符号的方法
Aug 26 Python
Python利用flask sqlalchemy实现分页效果
Aug 02 Python
python paramiko模块学习分享
Aug 23 Python
python+POP3实现批量下载邮件附件
Jun 19 Python
python3.6的venv模块使用详解
Aug 01 Python
selenium + python 获取table数据的示例讲解
Oct 13 Python
简单了解django索引的相关知识
Jul 17 Python
Django CBV与FBV原理及实例详解
Aug 12 Python
np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴
Nov 30 Python
如何基于python操作excel并获取内容
Dec 24 Python
Python warning警告出现的原因及忽略方法
Jan 31 Python
pip安装提示Twisted错误问题(Python3.6.4安装Twisted错误)
May 09 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将session信息存储到数据库的类实例
2015/03/04 PHP
帝国cms常用标签汇总
2015/07/06 PHP
8个必备的PHP功能开发
2015/10/02 PHP
实例讲解php数据访问
2016/05/09 PHP
Yii框架中jquery表单验证插件用法示例
2016/10/18 PHP
onpropertypchange
2006/07/01 Javascript
javascript Zifa FormValid 0.1表单验证 代码打包下载
2007/06/08 Javascript
JavaScript.The.Good.Parts阅读笔记(一)假值与===运算符
2010/11/16 Javascript
通过Javascript创建一个选择文件的对话框代码
2012/06/16 Javascript
简洁Ajax函数处理(示例代码)
2013/11/15 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
2015/09/01 Javascript
JavaScript的Backbone.js框架的一些使用建议整理
2016/02/14 Javascript
Angularjs的ng-repeat中去除重复数据的方法
2016/08/05 Javascript
微信小程序开发入门基础教程
2017/04/19 Javascript
vue.js框架实现表单排序和分页效果
2017/08/09 Javascript
Vue0.1的过滤代码如何添加到Vue2.0直接使用
2017/08/23 Javascript
p5.js入门教程之键盘交互
2018/03/19 Javascript
Node.js进阶之核心模块https入门
2018/05/23 Javascript
vue2单元测试环境搭建
2018/05/24 Javascript
JavaScript引用类型RegExp基本用法详解
2018/08/09 Javascript
小程序实现选择题选择效果
2018/11/04 Javascript
vue created钩子函数与mounted钩子函数的用法区别
2020/11/05 Javascript
python实现html转ubb代码(html2ubb)
2014/07/03 Python
利用python和百度地图API实现数据地图标注的方法
2019/05/13 Python
opencv python图像梯度实例详解
2020/02/04 Python
纯css3无js实现的Android Logo(有简单动画)
2013/01/21 HTML / CSS
自定义html标记替换html5新增元素
2008/10/17 HTML / CSS
魅力惠奢品线上平台:MEI.COM
2016/11/29 全球购物
美国在线眼镜店:GlassesShop
2018/11/15 全球购物
学校党员个人问题整改措施思想汇报
2014/10/08 职场文书
简单的离婚协议书范本
2014/11/16 职场文书
会计主管竞聘书
2015/09/15 职场文书
队名及霸气口号大全
2015/12/25 职场文书
PostgreSQL将数据加载到buffer cache中操作方法
2021/04/16 PostgreSQL
Nginx实现负载均衡的项目实践
2022/03/18 Servers
Netflix《海贼王》真人版剧集多张片场照曝光
2022/04/04 日漫