50行Python代碼實(shí)現(xiàn)圖片轉(zhuǎn)字符畫

本篇博客改編自實(shí)驗(yàn)樓

通過本篇博客,你可以將你喜歡的任意圖片轉(zhuǎn)換成對(duì)應(yīng)的字符畫

最終效果

teaGod.jpg

原理介紹

字符畫是一系列字符組合成的文本,看起來就像一幅畫一樣,我們可以把字符看作是比較大塊的像素,一個(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)前目錄下

在源代碼同級(jí)目錄下放置我們要轉(zhuǎn)換的圖片
teaGod.jpg

將命令行切換到當(dāng)前目錄,然后輸入
python .\ascii.py .\teaGod.jpg -o teaGod.txt --width 80 --height 40

之后會(huì)在命令行打印出字符畫

命令行輸出

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

在當(dāng)前目錄下生成的 teaGod.txt

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

祝大家用雙手 code 出自己的夢(mèng)想世界

再見
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容