用R將圖片轉為字符畫

2021-01-18 表哥有話講

作者:輝小寶同學微信公眾號:R語言和Python學堂

知乎:

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

簡書:

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


想獲取本文完整代碼和數據的下載連結,公眾號後臺回復「字符畫」。

注意:點擊放大圖片,可查看圖片細節

所謂字符畫,就是將圖片中的像素用相應字符來代替,這樣就是字符畫了。

現在網上有很多小工具可實現這個功能,主要是基於Java和Python的。目前好像還沒人用R來實現,因此在這篇博客,我將帶領大家學習如何用R來生成字符畫。

再來看個字符動畫:

原動畫

字符動畫

1. 基本原理

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語言入門及數據挖掘
回復 人工智慧      三個月入門人工智慧
回復 數據分析師   數據分析師成長之路 
回復 機器學習      機器學習的商業應用
回復 數據科學      數據科學實戰
回復 常用算法      常用數據挖掘算法

相關焦點

  • 用搜狗快速輸入特殊字符與表情字符
    因為它不僅涵蓋了大量的特殊符號如標點、數字、數學、希臘符號等,還預置了幾百款搜狗表情和字符畫,在寫文章做論文時能快速的輸入需要的特殊字符,在聊天泡論壇時也可隨手可愛的字符畫表達你的心情,很酷的噢。  一、搜狗輸入法都有哪些「表情&符號」?
  • 深入剖析go中字符串的編碼問題——特殊字符的string怎麼轉byte?
    我們通過go對二進位轉為整型:綜上:當用字符轉字節時輸出的是字符本身的整型值,當用字符串轉字節切片時,實際上是輸出的是utf8的字節切片序列(go中的字符串存儲的就是utf8位元組切片)。此時,我們回顧一下最開始的問題,就會發現輸出是完全符合預期的。
  • Python中去除字符串首尾空格、特殊字符和指定子字符串的方法
    第七十七節:去除字符串中的空格和特殊字符字符串在實際應用中,有很多情況是默認去除字符串首尾的空格狀態,去除幾個比較特殊的字符的。這幾個特殊的字符是:換行符「\n」、回車符「\r」、制表符「\t」。在Python中,提供了一個去除字符串首尾空格和特殊字符的方法,就是使用strip(),它的語法格式是下面這樣的:str.strip()設定一個字符串,然後用實例來看一下這個方法的應用,詳見下圖:
  • 機器視覺—字符識別之環形字符識別
    字符呈環形排列,若需識別,首先需要需要將環形排列的字符轉換至我們所熟悉的水平排列方式,後續就是OCR分割和分類的任務了。CD盤印刷的環形字符,如下圖。環形字符識別通過極坐標變換,可以加個環形排列字符轉換至水平排列,原理如下。極坐標變換原理直角坐標是我們能夠直觀想像,符合人類大腦的空間坐標,即x-y坐標系。
  • java之字符緩衝輸出流,BufferedWriter的簡單介紹
    >BufferedWriter:字符緩衝輸出流繼承自父類的共性成員方法:1.void write(int c)寫入單個字符。會根據不同的作業系統,獲取不同的行分隔符換行:換行符號Windows:\r\nLinux:/nMac:/r使用步驟:1.創建字符緩衝輸出流對象
  • stm32接收中文字符,解析中文字符的方法與調試
    測試過程:1、在keil中寫出一個字符,例如"袁",然後寫一個測試程序: 2、解析這種列印的原因: 新建一個txt文件,用ultraedit
  • 如何在線把png圖片轉為ico圖標
    有時候我們需要把png圖片或者其他格式的圖片,比如jpg、gif等轉為ico格式的。用於程序的圖標或者其他應用,如何不下載安裝軟體就可以轉換呢?在百度搜索png轉ico,或者png在線轉ico,得到搜索結果頁面,點擊在線進入:可以看到在線轉換圖標的網站:在頁面選擇「選擇文件」,會彈出窗口,讓你選擇你需要轉換的圖片:在輸入框上面選擇你想要轉換成多大的size,也可以自己輸入:點擊下面的按鈕「將以上圖片轉為ICO」:跳轉到另一個頁面,可以看到有一個下載按鈕,點擊下載按鈕
  • R語言-stringr-字符串處理
    R包stringr處理字符相對簡單,尤其是我常用Power BI,但是對M語言不熟悉,不會處理字符數據,往往我就先利用R清洗字符數據列。本文記錄工作中常用的字符處理函數,部分案例照搬R for Data Science的字符部分。
  • 手把手教你將矩陣畫成張量網絡圖
    在之前的一篇文章中,我們介紹過如何將矩陣&概率畫成圖,讀者表示妙不可言。最近,該文作者又動手實現了新的想法:將矩陣畫成張量網絡圖。今天,我想分享一種不同的方法來描繪矩陣,它不僅用於數學,也用於物理、化學和機器學習。基本想法是:一個帶有實數項的 m×n 矩陣 M 可以表示從 R^n→R^m 的線性映射。這樣的映射可以被描繪成具有兩條邊的節點。
  • php刪除字符串兩邊的空白符:trim()、ltrim()、rtrim()
    trim()函數不但能刪除空白符,還可以刪除其它任意字符,只要你在它的第二個參數中指明了你想要刪除的那些字符即可。還有兩個和trim()函數很相近的函數,ltrim()和rtrim()。ltrim第一個字母l表示left,即它只刪除字符串左邊的空白符或其它字符。rtrim的第一個字母r表示right,即它只刪除字符串右邊的空白符或其它字符。
  • 怎樣用word畫電路圖
    ),並分別放在每個黑點的上面,然後全部選中,再 「組合」在一起,,如圖3,最後將圖3放入下面的矩形中,再將整個圖形「組合」,如圖4所示,這就畫成了電流表的簡圖。例如要畫的電路如圖5所示,先單擊繪圖工具欄中的「矩形」,畫出三個矩形如圖6放置(除非特別需要不要用直線工具畫,那樣不如這樣容易調整),然後在按住「ctrl」鍵的同時,將原來畫的電燈、電流表等符號的「預製件」按住左鍵拖到適當的地方(這實際是一個複製的過程),最後「組合」在一起,再複製到你需要的地方即可,這樣非常的快捷,通常只要一分鐘。
  • 黑臉山雀白描畫圖片欣賞
    ,翅膀要用長線表現出它的特點,頭部要刻畫得生動。一、單只黑臉山雀白描圖片山雀飛行、落地、俯衝的姿態各不同,注意了解山雀的特徵,將其運動的姿態表現準確。山雀身體的毛要用短線勾勒,翅膀要用長線表現出它的特點,頭部要刻畫得生動。飛的姿態黑臉山雀白描畫圖片
  • Polarr 想用免費專業圖片處理工具,在數據的幫助下幫助專家和小白...
    在整個圖片處理應用市場中,每年又有 200 萬新人加入。但從數據中就能發現一定問題:對圖片處理工具的需求人數巨大,但對用戶而言,他們產出的照片質量和價值越高,他們要在照片修改和管理的成本就越高。另一方面,使用 Instagram 這類自動化工具過多,就不免導致最終成品趨於同質化、雷同化,相比之下原片的平均質量也會隨習慣增進而降低。
  • 如何使用VBA中正則表達式之元字符實現強大的匹配能力?
    我們在查找時通常會用通配符「*」表示任意字符,在正則表達式中也有一些固定的字符,它們可以表達某一類型的字符,以實現強大的匹配能力,這就是元字符。下面例舉一些常用的元字符:(注意大小寫之分)\d 匹配一個數字字符\D 匹配一個非數字字符\w 匹配包括下劃線的任何單詞字符。
  • 整理了一些自己可能會用到的R包~20210125更新
    更新於2021年1月25號gtable生信菜鳥團 公眾號分享的文章 R包:gtable包用於處理ggplot2圖像ggrgl畫三維圖 在 微生物生信 看到的推文 ggrgl:用ggplot做3D圖表rayshader公眾號有人留言說這個包做ppt很好用,我查了一下,大體看了一眼幫助文檔
  • 介紹「十六進位數字符串至數值轉換」函數
    有幾點需要注意:本文引用地址:http://www.eepw.com.cn/article/201701/337016.htm1:雖然該函數的輸入端子「string」的值可以是十六進位數、字符串(ASCII)或其他進位數,但是「string」的值流入該函數中時,先轉換成字符串(ASCII)。