用 R 生成字符动画
楚新元 / 2021-08-18
获取动画
library(magick)
if (dir.exists("./data") == FALSE) dir.create("./data")
img_path = "https://picb.zhimg.com/v2-f77c2758553b63f51f2061fc711101e8_b.webp"
if (file.exists("./data/ball.webp") == FALSE) {
download.file(img_path, "./data/ball.webp", mode = "wb")
}
img = image_read("./data/ball.webp")
img
动画简单处理
倒放动画
img_rev = rev(img)
img_rev
局部放慢
img_slow = img[c(1:30, rep(31:44, each = 3))]
img_slow
从局部放慢动画里提取每帧图片
if (dir.exists("./result") == FALSE) dir.create("./result")
for (i in 1:length(img_slow)) {
image_write(img_slow[i], format = "png", paste0("./result/", i, ".png"))
}
每帧图片转为字符画
自定义函数
注:这个函数参考辉小宝同学知乎文章,详见:https://zhuanlan.zhihu.com/p/51153590
library(magick)
image2chars = function(
pathIn = '',
pathOutTxt = NULL,
pathOutImg = NULL,
jpg_quality = 80,
width = 100,
chars = c('&', '#', 'w', 's', 'k', 'd', 't', 'j', 'i', '.', ' '),
isColor = FALSE
){
# pathIn: 原始图片的路径,支持各种格式。
# pathOutTxt: 字符文本的输出路径,默认与原始图片在同一文件夹下。
# pathOutImg: 字符图片的输出路径,默认与原始图片在同一文件夹下。
# jpg_quality: 字符图片的质量,范围0-100。
# width: 字符文本的宽度,默认为100,即一行100个字符。
# chars: 字符集,可自定义;
# isColor: 字符图片是否为彩色,默认为黑白字符图片
img = image_read(pathIn) # 读入图片
gray = image_convert(img, colorspace = 'gray') # 转为灰度图
rgb = image_convert(img, colorspace = 'rgb') # 转为rgb图
# 修改图片尺寸
gray = image_resize(gray, paste0(width, 'x'))
rgb = image_resize(rgb, paste0(width, 'x'))
# 获取图片灰度值矩阵,并将各像素值对应于相应字符
gray = as.integer(image_data(gray))[, , 1]
w = ncol(gray) # 图片宽度
h = nrow(gray) # 图片高度
index = findInterval(
c(gray),
seq(0, 255, length.out = length(chars) + 1),
rightmost.closed = T
)
labels = chars[index]
labels_mat = matrix(labels, ncol = w)
# 输出字符文本,并保存成文件
if(is.null(pathOutTxt))
pathOutTxt <- paste0(gsub(".png", "", pathIn), ".txt")
write.table(labels_mat, pathOutTxt, quote = F, row.names = F, col.names = F)
# 绘制字符图片,给相应字符着色,并保存成文件
if(isColor){
rgb = as.integer(image_data(rgb))
r = rgb[, , 1] # red通道像素矩阵
g = rgb[, , 2] # green通道像素矩阵
b = rgb[, , 3] # blue通道像素矩阵
cols = rgb(c(r), c(g), c(b), maxColorValue = 255) # 转化为颜色表示
}
if(is.null(pathOutImg))
pathOutImg = paste0(gsub(".png", "", pathIn), ".jpg")
jpeg(pathOutImg, width = 16 * w, height = 16 * h, quality = jpg_quality)
op = par(mar = c(0, 0, 0, 0))
plot(
0, xlab = '', ylab = '', asp = 1,
xlim = c(0, w), ylim = c(0, h),
xaxs = "i", yaxs = "i",
type = 'n', axes = FALSE
)
grid = expand.grid(y = h:1 - 0.5, x = 1:w - 0.5) # 各字符位置
if (isColor) {
text(grid$x, grid$y, labels, cex = 1.5, col = cols) # 绘制彩色字符
} else {
text(grid$x, grid$y, labels, cex = 1.5) # 绘制黑白字符
}
par(op)
dev.off()
}
利用自定义函数实现图片转字符
for (i in 1:length(img_slow)) {
pathIn = paste0("./result/", i, ".png")
image2chars(
pathIn,
width = 72,
isColor = TRUE,
chars = c("0", "1")
)
}
将字符图片转化为动画
library(gganimate)
library(magick)
p = 1:length(img_slow)
animate_p = image_animate(
image = image_read(path = paste0("./result/", p, ".jpg"))
)
anim_save(
filename = "ball_chars.gif",
animation = animate_p
)
ball_chars = image_read("ball_chars.gif")
ball_chars