本篇博客改編自實(shí)驗(yàn)樓
通過本篇博客,你可以將你喜歡的任意圖片轉(zhuǎn)換成對(duì)應(yīng)的字符畫
最終效果

原理介紹
字符畫是一系列字符組合成的文本,看起來就像一幅畫一樣,我們可以把字符看作是比較大塊的像素,一個(gè)字符能表現(xiàn)一種顏色(暫且這么理解吧),字符的種類越多,可以表現(xiàn)的顏色也越多,圖片也會(huì)更有層次感。
問題來了,我們是要轉(zhuǎn)換一張彩色的圖片,這么這么多的顏色,要怎么對(duì)應(yīng)到單色的字符畫上去?這里就要介紹灰度值的概念了。
灰度值:指黑白圖像中點(diǎn)的顏色深度,范圍一般從 0 到 255,白色為
255,黑色為 0,故黑白圖片也稱灰度圖像
我們可以使用灰度值公式將像素的 RGB 值映射到灰度值:
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
這樣,任何一個(gè) RGB 像素點(diǎn)都可以映射成一個(gè) 0~255 之間的整數(shù)。
我們可以定義一個(gè)字符列表,然后根據(jù)像素點(diǎn)轉(zhuǎn)換成的灰度值在 0~255 之間的相對(duì)位置,將像素點(diǎn)替換成我們定義的字符列表中相對(duì)位置上的字符。
開發(fā)準(zhǔn)備
我們要用到兩個(gè) python 庫,PIL(pillow) 庫和 argparse 庫,PIL庫 是一個(gè)第三方 Python 圖像處理庫,argparse 庫是用來管理命令行參數(shù)輸入的一個(gè) python 內(nèi)置庫。
你可以使用 pip install pillow 來安裝 PIL 庫,PIL 庫的快速學(xué)習(xí)可以參考廖雪峰的官方網(wǎng)站
Coding
下面是我們的字符畫所使用的字符集,一共有 70 個(gè)字符,字符的種類與數(shù)量可以自己根據(jù)字符畫的效果反復(fù)調(diào)試
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
下面是RGB像素轉(zhuǎn)字符的函數(shù):
def get_char(r,g,b,alpha = 256):
if alpha == 0:
return ' '
length = len(ascii_char)
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
unit = (256.0 + 1)/length
return ascii_char[int(gray/unit)]
ascii.py 完整代碼(參考自實(shí)驗(yàn)樓):
from PIL import Image
import argparse
#命令行輸入?yún)?shù)處理
parser = argparse.ArgumentParser()
parser.add_argument('file') #輸入文件
parser.add_argument('-o', '--output') #輸出文件
parser.add_argument('--width', type = int, default = 80) #輸出字符畫寬
parser.add_argument('--height', type = int, default = 80) #輸出字符畫高
#獲取參數(shù)
args = parser.parse_args()
IMG = args.file
WIDTH = args.width
HEIGHT = args.height
OUTPUT = args.output
# 我們定義的不重復(fù)的字符列表,灰度值小(暗)的用列表開頭的符號(hào),灰度值大(亮)的用列表末尾的符號(hào)
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
# 將256灰度映射到70個(gè)字符上
def get_char(r,g,b,alpha = 256):
if alpha == 0:
return ' '
length = len(ascii_char)
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
unit = (256.0 + 1)/length
return ascii_char[int(gray/unit)]
if __name__ == '__main__':
im = Image.open(IMG)
im = im.resize((WIDTH,HEIGHT), Image.NEAREST)
txt = ""
#將圖片看成由像素點(diǎn)組成的二維數(shù)組,i代表每一行,j代表每一列
for i in range(HEIGHT):
for j in range(WIDTH):
#getpixel()函數(shù)的參數(shù)是由每個(gè)像素點(diǎn)在圖片中的相對(duì)位置(w,h)組成的元組
#返回值是一個(gè)代表圖片像素值的(r,g,b,alpha)元組
txt += get_char(*im.getpixel((j,i)))
txt += '\n'
print(txt)
#字符畫輸出到文件
if OUTPUT:
with open(OUTPUT,'w') as f:
f.write(txt)
else:
with open("output.txt",'w') as f:
f.write(txt)
然后將圖片拷貝到當(dāng)前目錄下


將命令行切換到當(dāng)前目錄,然后輸入
python .\ascii.py .\teaGod.jpg -o teaGod.txt --width 80 --height 40
之后會(huì)在命令行打印出字符畫

同樣,也會(huì)在當(dāng)前目錄生成字符畫 txt 文件,現(xiàn)在可以復(fù)制或者截圖出去給小伙伴炫耀了

最后打一個(gè)廣告,實(shí)驗(yàn)樓 是一個(gè)很好的學(xué)習(xí)網(wǎng)站,配套了線上的開發(fā)環(huán)境,不需要用戶自己部署,非常方便。上面也有各種有趣的實(shí)驗(yàn),大家可以嘗試下。
祝大家用雙手 code 出自己的夢(mèng)想世界
