作者:辉小宝同学

微信公众号:R语言和Python学堂

知乎:

https://www.zhihu.com/people/zoro-3-92/posts

简书:

https://www.jianshu.com/u/981ba7d6b4a6

想获取本文完整代码和数据的下载链接,公众号后台回复“字符画”。

注意:点击放大图片,可查看图片细节

所谓字符画,就是将图片中的像素用相应字符来代替,这样就是字符画了。

现在网上有很多小工具可实现这个功能,主要是基于Java和Python的。目前好像还没人用R来实现,因此在这篇博客,我将带领大家学习如何用R来生成字符画。

再来看个字符动画:

原动画

字符动画

1. 基本原理

  • 将彩色图片转化为灰度图(像素值从0到255,其中0为黑色,255为白色)

  • 设计一套字符集来对应各像素值,一般原则是:黑色对应最复杂字符(比如 &或 @);白色对应最简单字符(比如 .或空格)

  • 根据彩色图片的RGB各通道的像素值来给字符上色

RGB色彩模式是通过对红(R)、绿(G)、蓝(B)三个颜色通道的叠加来得到各式各样的颜色的,常用的是8位图(各通道均为256等级,数值从0, 1, 2, ...直到255)。灰度图只含一个通道,不含色彩信息,就是我们平时看到的黑白照片,通常也划分为0到255共256个级别,其中0最暗(全黑),255最亮(全白)。在ImageMagick中,从彩色图片中的RGB值到灰度值Gray转换公式默认为: Gray=0.212*R+0.715*G+0.072*B

比如我们用 {'&', '#', 'w', 's', 'k', 'd', 't', 'j', 'i', '.', ' '} 这11字符来作为我们的字符集,你也可以根据自己的喜好来选择。我们的字符集容量为11,一个字符对应的像素区间宽度为 256/11≈23。

灰度值与字符集的对应关系为:

  1. [0, 23) → '&'

  2. [23, 46) → '#'

  3. [46, 69) → 'w'

  4. ......

  5. ......

  6. [209, 232) → '.'

  7. [232, 255] → ' '

2. R实现

对于图片处理,我们用R的 Magick包来处理,其功能非常强大,它实际上是ImageMagick的功能接口。ImageMagick可能是当今最全面的开源图像处理库,支持许多常见格式( png、JPEG、tiff、pdf等)和操作(旋转、缩放、裁剪、修剪、翻转、模糊等)。

对于图片转字符画的R实现,我将其封装成一个叫 image2chars的函数,其使用说明可参考函数内部的注释,函数代码如下:

  1. library(magick)  # 加载magick包

  2. image2chars <- function(pathIn='',

  3.                        pathOutTxt=NULL,

  4.                        pathOutImg=NULL,

  5.                        jpg_quality=80,

  6.                        width=100,

  7.                        chars=c('&','#','w','s','k','d','t','j','i','.', ' '),

  8.                        isColor=FALSE){

  9.  ##### 参数

  10.  # pathIn: 原始图片的路径,支持各种格式

  11.  # pathOutTxt: 字符文本的输出路径,默认与原始图片在同一文件夹下,只是后缀为.txt;你也可指定其他路径

  12.  # pathOutImg: 字符图片的输出路径,默认与原始图片在同一文件夹下,只是后缀为.jpg;你也可指定其他路径

  13.  # jpg_quality: 字符图片的质量,范围0-100,越大图片越清晰,默认为80

  14.  # width: 字符文本的宽度,默认为100,即一行100个字符;字符图片的尺寸也与其成正比

  15.  # chars: 字符集,可自定义;默认为'&','#','w','s','k','d','t','j','i','.', ' '共11个字符

  16.  # isColor: 字符图片是否为彩色,默认为黑白字符图片

  17.  ##### 返回值

  18.  # 无

  19.  img <- image_read(pathIn)  # 读入图片

  20.  gray <- image_convert(img, colorspace='gray')  # 转为灰度图

  21.  rgb <- image_convert(img, colorspace='rgb')  # 转为rgb图

  22.  ## 修改图片尺寸

  23.  gray <- image_resize(gray, paste0(width,'x'))

  24.  rgb <- image_resize(rgb, paste0(width,'x'))

  25.  ## 获取图片灰度值矩阵,并将各像素值对应于相应字符

  26.  gray <- as.integer(image_data(gray))[, , 1]

  27.  w <- ncol(gray)   # 图片宽度

  28.  h <- nrow(gray)  # 图片高度

  29.  index <- findInterval(c(gray), seq(0, 255, length.out=length(chars)+1), rightmost.closed=T)

  30.  labels <- chars[index]

  31.  labels_mat <- matrix(labels, ncol=w)
     

  32.  ## 输出字符文本,并保存成文件

  33.  if(is.null(pathOutTxt))

  34.    pathOutTxt <- paste0(pathIn,'.txt') # 文本文件名,与输入图片文件名一致,只是后缀为.txt

  35.  write.table(labels_mat, pathOutTxt,

  36.              quote=F, row.names=F,col.names=F)
                 

  37.  ## 绘制字符图片,给相应字符着色,并保存成文件

  38.  if(isColor){

  39.    rgb <- as.integer(image_data(rgb))

  40.    r <- rgb[, , 1]  # red通道像素矩阵

  41.    g <- rgb[, , 2]  # green通道像素矩阵

  42.    b <- rgb[, , 3]  # blue通道像素矩阵

  43.    cols <- rgb(c(r), c(g), c(b), maxColorValue=255) # 转化为颜色表示

  44.  }

  45.  if(is.null(pathOutImg))

  46.    pathOutImg <- paste0(pathIn,'.jpg')  # 图片文件名,与输入图片文件名一致,只是后缀为.jpg

  47.  jpeg(pathOutImg, width=16*w, height=16*h, quality=jpg_quality)

  48.  op <- par(mar=c(0, 0, 0, 0))

  49.  plot(0,

  50.       xlab='',

  51.       ylab='',

  52.       asp=1,

  53.       xlim=c(0,w),

  54.       ylim=c(0,h),

  55.       xaxs="i",

  56.       yaxs="i",

  57.       type='n',

  58.       axes=FALSE)

  59.  grid <- expand.grid(y=h:1-0.5, x=1:w-0.5)  # 各字符位置

  60.  if(isColor){

  61.    text(grid$x, grid$y, labels, cex=1.5, col=cols)  # 绘制彩色字符

  62.    } else {

  63.    text(grid$x, grid$y, labels, cex=1.5) # 绘制黑白字符

  64.    }

  65.  par(op)

  66.  dev.off()

  67. }

来测试一下:

  • 黑白字符图片

  1. pathIn <- 'messi.jpg'

  2. image2chars(pathIn, width=80)

代码运行后,将生成两个文件 messi.jpg.txt和 messi.jpg.jpg(见下图),分别为字符文本和字符图片。

其中字符图片为:

  • 彩色字符图片

  1. pathIn <- 'tiger.jpg'

  2. image2chars(pathIn, width=80, isColor=TRUE)

其原图为:

  • 自定义字符

  1. custom_chars <- c('@','%','M','G','a','l','-')  ##自定义字符集

  2. pathIn <- 'cartoon.jpg'

  3. image2chars(pathIn, width=80, chars=custom_chars)

其原图为:

最后结合《用R制作gif动态图以及从gif中提取图片》博客中的方法就可以制作字符动画了,再来看个例子:

以上就是本文的全部内容,希望对大家的学习有所帮助。如果觉得文章不错,动手转发支持一下哦!

公众号后台回复关键字即可学习

回复 爬虫             爬虫三大案例实战  
回复 Python        1小时破冰入门

回复 数据挖掘      R语言入门及数据挖掘
回复 人工智能      三个月入门人工智能
回复 数据分析师   数据分析师成长之路 
回复 机器学习      机器学习的商业应用
回复 数据科学      数据科学实战
回复 常用算法      常用数据挖掘算法

爱我请给我好看!

用R将图片转为字符画相关推荐

  1. python将图片转为字符画_Python将图片转换为字符画的方法

    最近在学习python,看到网上用python将图片转换成字符画便来学习一下 题目意思是,程序读入一个图片,以txt格式输出图片对应的字符画,如图所示: 以下是python代码: # coding:u ...

  2. python把图片转为字符画_Python 实现图片转换为字符画

    主要使用 pillow 如果没有安装 使用 pillow install pillow 安装一下 看代码: from PIL import Image import argparse #字符画所用的字 ...

  3. golang实现图片颜色反转、图片灰度、缩放、转为字符画

    看到网上很多通过字符形成的画,觉得很好玩,于是网上搜索了下原来叫字符画. 见百度百科:https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6%E7%94%BB/ ...

  4. python动态图片转字符画_GIF动态图,视频?都能用Python转换成字符画图像

    字符画是一种由字母.标点或其他字符组成的图画,它产生于互联网时代,在聊天软件中使用较多,本文我们看一下如何将自己喜欢的图片转成字符画. 静态图片 首先,我们来演示将静态图片转为字符画,功能实现主要用到 ...

  5. Python 实现 图片转 字符画,静态图、GIF 都能转

    源码在python学习交流q群:733089476 获取 字符画是一种由字母.标点或其他字符组成的图画,它产生于互联网时代,在聊天软件中使用较多,本文我们看一下如何将自己喜欢的图片转成字符画. 静态图 ...

  6. 网页版 Python 图片转字符画

    原文:https://lwebapp.com/zh/post/python-image-to-ascii 需求 最近发现一个好玩的 Python 玩法,用 Python 将图片转为字符画,大多数都是本 ...

  7. Python图片转字符画,太好玩啦(46)

    小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生. 和猫妹学Python,一起趣味学编程. 今日主题 什么是字符画呢? 如何用Python将图片转为字符画? 我们先找一幅原画,比如 ...

  8. python图像转字符画_Python实现图片转字符画的代码实例

    如何利用Python实现图片转字符画详解 如何用python将图片转为字符画给小编你的心作纪念,小编的梦有你的祝福才能够完全,风浪再大,小编也会勇往直前,小编们的爱,镶在青春的纪念册. # codin ...

  9. 图片,文字在线转为字符画

    图片转换字符画 http://www.makepic.net/Tool/Image2ascii.html 文字转换字符画 http://patorjk.com/software/taag http:/ ...

  10. char添加一个字符_给你五十行代码把图片变成字符画!程序:太多了,一半都用不完...

    今天和大家分享一个简单又好玩的Python项目–"图片转字符画".废话不多说,先上一个效果图迷惑一下众生. 没错的,图片转字符画就是将我们平常所看到的的图片根据像素RGB值和灰度值 ...

最新文章

  1. amd同步多线程_使用方法及感受_AMD Ryzen Threadripper 1950X_CPUCPU评测-中关村在线
  2. 集合框架源码学习之HashMap(JDK1.8)
  3. 全局内存BSS,DATA,RODATA的区别以及其他内存区间相关
  4. FPGA学习之路—接口(3)—SPI详解及Verilog源码分析
  5. Centos7安装apt-get 在centos下用yum install xxx        不是使用apt-get
  6. [转载](热议)“我不伟大”,但可以让善良“春暖花开”
  7. 《人件(原书第3版)》—— 01 此时此刻,一个项目正在走向失败
  8. 《OpenGL编程指南》学习笔记
  9. 我的世界java版forge放在哪_我的世界forge怎么装mod(mod安装方法介绍)
  10. 【2021】重装ubuntu16.04系统
  11. java append concat_最佳实践/性能:将StringBuilder.append与String.concat混合使用
  12. 玩游戏计算机虚拟内存怎么设置,【新手指导】电脑虚拟内存设置
  13. opencv-3.0.0-beta和opencv2版本的区别
  14. css cubic-bezier,使用cubic-bezier()创建带有反弹特效的CSS动画
  15. [keil5]从AC5到AC6的转变
  16. 安卓手机拨号键盘隐藏工程代码大全
  17. JavaScript 遍历数组 翻转数组与冒泡排序法
  18. 企业上软件,选择ERP还是ERC
  19. 微信公众号流量主的实际收益(本人亲测)
  20. SAP License:术语歪解

热门文章

  1. 卧槽!迅雷的代码竟然被扒了精光!
  2. 新同事不讲“码”德,这SQL写得太野了,请耗子尾汁~
  3. 百度开源超级链技术方案!
  4. 五轮面试,阿里offer到手!!
  5. 竟然才发现,Github上还有开源的面试项目
  6. 写了一百万行代码是什么体验?
  7. 一分钟了解微服务的好处和陷阱
  8. 一场重新定义的发布会
  9. Android 下拉刷新库,这一个就够了!
  10. shell基础之后台运行脚本