1.原理
字符畫
是一系列字符的組合蒂阱,我們可以把字符看作是比較大塊的像素锥咸,一個(gè)字符能表現(xiàn)一種顏色(為了簡(jiǎn)化可以這么理解)扁位,字符的種類越多,可以表現(xiàn)的顏色也越多者铜,圖片也會(huì)更有層次感腔丧。
問(wèn)題來(lái)了放椰,我們是要轉(zhuǎn)換一張彩色的圖片,這么多的顏色愉粤,要怎么對(duì)應(yīng)到單色的字符畫上去砾医?這里就要介紹灰度值的概念了。
灰度值
:指黑白圖像中點(diǎn)的顏色深度衣厘,范圍一般從0到255如蚜,白色為255,黑色為0影暴,故黑白圖片也稱灰度圖像错邦。
另外一個(gè)概念是RGB
色彩:
RGB
色彩模式是工業(yè)界的一種顏色標(biāo)準(zhǔn),是通過(guò)對(duì)紅(R)型宙、綠(G)撬呢、藍(lán)(B)三個(gè)顏色通道的變化以及它們相互之間的疊加來(lái)得到各式各樣的顏色的,RGB即是代表紅妆兑、綠魂拦、藍(lán)三個(gè)通道的顏色,這個(gè)標(biāo)準(zhǔn)幾乎包括了人類視力所能感知的所有顏色搁嗓,是目前運(yùn)用最廣的顏色系統(tǒng)之一芯勘。- 來(lái)自百度百科介紹
我們可以使用灰度值公式將像素的 RGB 值映射到灰度值(注意這個(gè)公式并不是一個(gè)真實(shí)的算法,而是簡(jiǎn)化的 sRGB IEC61966-2.1 公式腺逛,真實(shí)的公式更復(fù)雜一些荷愕,不過(guò)在我們的這個(gè)應(yīng)用場(chǎng)景下并沒(méi)有必要):
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
這樣就好辦了,我們可以創(chuàng)建一個(gè)不重復(fù)的字符列表棍矛,灰度值邪擦啤(暗)的用列表開(kāi)頭的符號(hào),灰度值大(亮)的用列表末尾的符號(hào)茄靠。
2.上代碼
# -*- coding=utf-8 -*-
from PIL import Image
import argparse
#命令行輸入?yún)?shù)處理
parser = argparse.ArgumentParser()
parser.add_argument('picture_name') #輸入文件
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.picture_name
WIDTH = args.width
HEIGHT = args.height
OUTPUT = args.output
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.convert('RGB')
im = im.resize((WIDTH,HEIGHT), Image.LANCZOS)
#使用resize()方法重新設(shè)置圖片大小茂契,其中第一個(gè)參數(shù)應(yīng)是一個(gè)尺寸元組
#而第二個(gè)參數(shù)resample有四個(gè)選項(xiàng),分別是Image.NEAREST慨绳、Image.BILINEAR掉冶、
#Image.BICUBIC、Image.LANCZOS脐雪,默認(rèn)是第一個(gè)厌小,第四個(gè)質(zhì)量最高
txt = ""
for i in range(HEIGHT):
for j in range(WIDTH):
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)
3.上效果
#涉及的相關(guān)知識(shí)點(diǎn),后續(xù)補(bǔ)上战秋。
執(zhí)行命令 #python ascii.py kanshan.png --width 50 --heigh 30