用R将图片转为字符画

作者: 天善智能 | 来源:发表于2019-01-22 15:32 被阅读50次

    欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

    对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。

    作者:辉小宝同学

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

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

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

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

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

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

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

    再来看个字符动画:

    原动画

    字符动画

    1. 基本原理

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

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

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

  4. 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. }

    来测试一下:

  5. 黑白字符图片

    1. pathIn <- 'messi.jpg'

    2. image2chars(pathIn, width=80)

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

    其中字符图片为:

  6. 彩色字符图片

    1. pathIn <- 'tiger.jpg'

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

    其原图为:

  7. 自定义字符

    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将图片转为字符画

        本文链接:https://www.haomeiwen.com/subject/hqaljqtx.html