[关闭]
@agpwhy 2022-07-09T08:13:19.000000Z 字数 2286 阅读 262

王胖的生信笔记第四十八篇:转字符动画

最近看到一个好玩的教程和大家分享。

https://cxy.rbind.io/post/2021/08/18/r-image-chars-gif/

讲的是如何用一张图片换成那种字符动画。类似这样:

char

【gif不知为何出问题了】

使用的包如下主要是magickgganimate

这两个包之前在介绍新冠疫情可视化的时候也搞过,这个里面还是有很多能搞的。

读取动图并拆成逐帧图

  1. library(magick)
  2. img = image_read("./gif.gif")
  3. dir.create("./逐帧")

其实用webp格式也可以的

然后转逐帧的图片。

  1. for (i in 1:length(img)) {
  2. image_write(img[i], format = "png", paste0("./逐帧/", i, ".png"))
  3. }

教程中的重要function image2chars

  1. image2chars = function(
  2. 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: 字符文本的输出路径,默认与原始图片在同一文件夹下。
  12. # pathOutImg: 字符图片的输出路径,默认与原始图片在同一文件夹下。
  13. # jpg_quality: 字符图片的质量,范围0-100。
  14. # width: 字符文本的宽度,默认为100,即一行100个字符。
  15. # chars: 字符集,可自定义;
  16. # isColor: 字符图片是否为彩色,默认为黑白字符图片
  17. img = image_read(pathIn) # 读入图片
  18. gray = image_convert(img, colorspace = 'gray') # 转为灰度图
  19. rgb = image_convert(img, colorspace = 'rgb') # 转为rgb图
  20. # 修改图片尺寸
  21. gray = image_resize(gray, paste0(width, 'x'))
  22. rgb = image_resize(rgb, paste0(width, 'x'))
  23. # 获取图片灰度值矩阵,并将各像素值对应于相应字符
  24. gray = as.integer(image_data(gray))[, , 1]
  25. w = ncol(gray) # 图片宽度
  26. h = nrow(gray) # 图片高度
  27. index = findInterval(
  28. c(gray),
  29. seq(0, 255, length.out = length(chars) + 1),
  30. rightmost.closed = T
  31. )
  32. labels = chars[index]
  33. labels_mat = matrix(labels, ncol = w)
  34. # 输出字符文本,并保存成文件
  35. if(is.null(pathOutTxt))
  36. pathOutTxt <- paste0(gsub(".png", "", pathIn), ".txt")
  37. write.table(labels_mat, pathOutTxt, quote = F, row.names = F, col.names = F)
  38. # 绘制字符图片,给相应字符着色,并保存成文件
  39. if(isColor){
  40. rgb = as.integer(image_data(rgb))
  41. r = rgb[, , 1] # red通道像素矩阵
  42. g = rgb[, , 2] # green通道像素矩阵
  43. b = rgb[, , 3] # blue通道像素矩阵
  44. cols = rgb(c(r), c(g), c(b), maxColorValue = 255) # 转化为颜色表示
  45. }
  46. if(is.null(pathOutImg))
  47. pathOutImg = paste0(gsub(".png", "", pathIn), ".jpg")
  48. jpeg(pathOutImg, width = 16 * w, height = 16 * h, quality = jpg_quality)
  49. op = par(mar = c(0, 0, 0, 0))
  50. plot(
  51. 0, xlab = '', ylab = '', asp = 1,
  52. xlim = c(0, w), ylim = c(0, h),
  53. xaxs = "i", yaxs = "i",
  54. type = 'n', axes = FALSE
  55. )
  56. grid = expand.grid(y = h:1 - 0.5, x = 1:w - 0.5) # 各字符位置
  57. if (isColor) {
  58. text(grid$x, grid$y, labels, cex = 1.5, col = cols) # 绘制彩色字符
  59. } else {
  60. text(grid$x, grid$y, labels, cex = 1.5) # 绘制黑白字符
  61. }
  62. par(op)
  63. dev.off()
  64. }

运用函数转换

每帧图片都转成字符图

  1. for (i in 1:length(img)) {
  2. pathIn = paste0("./逐帧/", i, ".png")
  3. image2chars(
  4. pathIn,
  5. width = 72,
  6. isColor = TRUE,
  7. chars = c('&', '#', 'w', 's', 'k', 'd', 't', 'j', 'i', '.', ' ')
  8. )
  9. }

每帧都是这样

1

然后在使用gganimate把各帧结合成动图

  1. library(gganimate)
  2. p = 1:length(img)
  3. animate_p = image_animate(
  4. image = image_read(path = paste0("./逐帧/", p, ".jpg"))
  5. )
  6. anim_save(
  7. filename = "charnew.gif",
  8. animation = animate_p
  9. )

charnew

【gif不知为何出问题了】

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注