作者:輝小寶同學微信公眾號:R語言和Python學堂
知乎:
https://www.zhihu.com/people/zoro-3-92/posts
簡書:
https://www.jianshu.com/u/981ba7d6b4a6
想獲取本文完整代碼和數據的下載連結,公眾號後臺回復「字符畫」。
注意:點擊放大圖片,可查看圖片細節
所謂字符畫,就是將圖片中的像素用相應字符來代替,這樣就是字符畫了。
現在網上有很多小工具可實現這個功能,主要是基於Java和Python的。目前好像還沒人用R來實現,因此在這篇博客,我將帶領大家學習如何用R來生成字符畫。
再來看個字符動畫:
原動畫
字符動畫
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。
灰度值與字符集的對應關係為:
[0, 23) → '&'
[23, 46) → '#'
[46, 69) → 'w'
......
......
[209, 232) → '.'
[232, 255] → ' '
2. R實現對於圖片處理,我們用R的 Magick包來處理,其功能非常強大,它實際上是ImageMagick的功能接口。ImageMagick可能是當今最全面的開源圖像處理庫,支持許多常見格式( png、JPEG、tiff、pdf等)和操作(旋轉、縮放、裁剪、修剪、翻轉、模糊等)。
對於圖片轉字符畫的R實現,我將其封裝成一個叫 image2chars的函數,其使用說明可參考函數內部的注釋,函數代碼如下:
library(magick) # 加載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: 字符文本的輸出路徑,默認與原始圖片在同一文件夾下,只是後綴為.txt;你也可指定其他路徑
# pathOutImg: 字符圖片的輸出路徑,默認與原始圖片在同一文件夾下,只是後綴為.jpg;你也可指定其他路徑
# jpg_quality: 字符圖片的質量,範圍0-100,越大圖片越清晰,默認為80
# width: 字符文本的寬度,默認為100,即一行100個字符;字符圖片的尺寸也與其成正比
# chars: 字符集,可自定義;默認為'&','#','w','s','k','d','t','j','i','.', ' '共11個字符
# 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(pathIn,'.txt') # 文本文件名,與輸入圖片文件名一致,只是後綴為.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(pathIn,'.jpg') # 圖片文件名,與輸入圖片文件名一致,只是後綴為.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()
}
來測試一下:
pathIn <- 'messi.jpg'
image2chars(pathIn, width=80)
代碼運行後,將生成兩個文件 messi.jpg.txt和 messi.jpg.jpg(見下圖),分別為字符文本和字符圖片。
其中字符圖片為:
pathIn <- 'tiger.jpg'
image2chars(pathIn, width=80, isColor=TRUE)
其原圖為:
custom_chars <- c('@','%','M','G','a','l','-') ##自定義字符集
pathIn <- 'cartoon.jpg'
image2chars(pathIn, width=80, chars=custom_chars)
其原圖為:
最後結合《用R製作gif動態圖以及從gif中提取圖片》博客中的方法就可以製作字符動畫了,再來看個例子:
以上就是本文的全部內容,希望對大家的學習有所幫助。如果覺得文章不錯,動手轉發支持一下哦!
公眾號後臺回復關鍵字即可學習
回復 爬蟲 爬蟲三大案例實戰
回復 Python 1小時破冰入門
回復 數據挖掘 R語言入門及數據挖掘
回復 人工智慧 三個月入門人工智慧
回復 數據分析師 數據分析師成長之路
回復 機器學習 機器學習的商業應用
回復 數據科學 數據科學實戰
回復 常用算法 常用數據挖掘算法