歡迎訪問集智主站:集智,通向智能時代的引擎瀏覽器
本文全部代碼都可在集智原貼中運行調試,有須要的同窗能夠點擊這裏前往原貼
bash
ASCII的全稱是American Standard Code for Information Interchange,即美國信息交換標準碼。是由軍用電報編碼發展而來,併成爲最通用的現代計算機編碼系統。網絡
在顯卡還不能摧毀航母戰鬥羣的年代,計算機還主要用來計算導彈彈道和衛星軌道,其圖形處理能力是很是弱的,甚至還不現在天高級一點的示波器。但這並不能阻止人類對美的追求,正如四萬年前的莽荒也沒有耽誤拉斯科洞窟壁畫的誕生。編輯器
在我剛上網那陣,有個流傳很廣的帖子,是教你觀看命令行裏的《星球大戰》,而這部星戰正是由ASCII編碼中的字符構成的,這被稱做ASCII art函數
在鬥圖代替打字、點播變成直播甚至VR/AR的今天,圖形的處理已經再也不是瓶頸,反而成爲了新的增加點。道高一尺魔高一丈,技術的進步也帶來了有害信息,好比廣你們長朋友們特別關注的色情信息。剛開始色情的鑑定是由人工完成的,李迪同志就是在《暴走大事件》中扮演鑑黃師唐馬儒而一炮走紅。post
可是,基於人工智能的圖像識別也在飛速進步,自動鑑黃已經投入實用,鑑黃師的職業前景就面臨着嚴重的威脅!ui
把一張照片轉換爲字符畫,大體須要三步:編碼
早年間以上步驟還須要專門作一個小軟件來完成,而如今只須要簡單的代碼就能夠直接在瀏覽器中實現。人工智能
由於字符畫的本質是「字符」,能夠用文本編輯器打開,對於計算機來講,他們和其餘的字符沒有任何區別,「畫」的性質只是由人類的想象力後天賦予的。因此,若是你用字符畫的形式傳播春宮圖,仍是須要唐馬儒。url
針對字符畫生成的基礎功能,Python已經內置了不少優秀的擴展庫,能夠在此基礎上直接調用,而無需重複製造輪子。
圖庫PIL(Python Imaging Library)
基本的圖像處理功能。
網庫urllib
獲取網絡資源,以下載網上的圖片。
from PIL import Image # 圖像處理模塊
from urllib import request #網絡請求模塊
複製代碼
沒有必要把0-255的灰度值一一對應爲不一樣的字符,通常十幾個也就足夠了。這裏作以下定義:
ASCII_CHARS = [' ', '#', '?', '%', '.', '+', '.', '*', ':', ',', '@']
複製代碼
這裏將最低的灰度段映射爲' '
(空格),也就是原圖中空白或接近空白的部分,在字符畫中也會會變成空白;而原圖的黑點則變成@
。
讀者朋友能夠在後文的開放代碼環境中想要定義本身的字符,並能夠傳入任意網絡圖片作實驗。
4K屏已經逐漸普及,如今差很少的電腦顯示器也能支持2K分辨率,若是把每一個像素點都變成一個字符,那出來的圖片實在是太大了。
因此首先要對源圖片進行壓縮,再轉換爲灰度模式,即拋出色彩信息。
# 壓縮圖片
def scale_image(image, new_width=60):
(original_width, original_height) = image.size # 獲取原圖尺寸
aspect_ratio = original_height/float(original_width) * 0.5 # 計算高寬比,由於輸出文本有2倍行距,因此乘0.5維持高寬比
new_height = int(aspect_ratio * new_width)
new_image = image.resize((new_width, new_height))
return new_image
# 灰度模式
def convert_to_grayscale(image):
return image.convert('L') # 調用image對象本身的.convert()方法
複製代碼
而後是創建圖片(壓縮後)像素點到字符集的映射關係。
def map_pixels_to_ascii_chars(image, range_width=25):
# 將每一個像素根據其灰度值映射爲一個字符,每一個字符對應25個灰度值
pixels_in_image = list(image.getdata()) # 獲取原圖灰度值列表
pixels_to_chars = [ASCII_CHARS[int(pixel_value/range_width)] for pixel_value in pixels_in_image]
# 對於每一個像素點,將其灰度值轉換爲列表ASCII_CHARS的索引
return "".join(pixels_to_chars)[/amalthea_sample_code]
複製代碼
最後綜合前面幾個函數,以文本形式輸出字符畫。
def convert_image_to_ascii(image, new_width=60):
image = scale_image(image, new_width) # 調用scale_image()函數,壓縮圖片
image = convert_to_grayscale(image) # convert_to_grayscale()函數,轉換爲灰度圖
pixels_to_chars = map_pixels_to_ascii_chars(image) # 映射至字符集
len_pixels_to_chars = len(pixels_to_chars) # 獲取字符集長度
image_ascii = [pixels_to_chars[index: index + new_width] for index in range(0, len_pixels_to_chars, new_width)]
return "\n".join(image_ascii)
def handle_image_conversion(image_filepath, new_width=60):
image = Image.open(image_filepath) # Image.open()打開源圖片
image_ascii = convert_image_to_ascii(image, new_width) # 調用上面的convert_image_to_ascii()函數
print(image_ascii) # 輸出字符畫
複製代碼
接下來咱們能夠將任意圖片轉換爲字符畫看看效果,爲了充分發揚互聯網精神,目前僅支持具備網絡地址的圖片(實際上是圖片上傳系統還沒作好)。
下面來看一個實例,將一張QQ企鵝的圖標轉換爲字符畫,點擊運行便可獲得字符畫。
from PIL import Image
ASCII_CHARS = [' ', '#', '?', '%', '.', '+', '.', '*', ':', ',', '@']
def scale_image(image, new_width=60):
"""Resizes an image preserving the aspect ratio. """
(original_width, original_height) = image.size
aspect_ratio = original_height/float(original_width) * 0.5
new_height = int(aspect_ratio * new_width)
new_image = image.resize((new_width, new_height))
return new_image
def convert_to_grayscale(image):
return image.convert('L')
def map_pixels_to_ascii_chars(image, range_width=25):
pixels_in_image = list(image.getdata())
pixels_to_chars = [ASCII_CHARS[int(pixel_value/range_width)] for pixel_value in
pixels_in_image]
return "".join(pixels_to_chars)
def convert_image_to_ascii(image, new_width=60):
image = scale_image(image, new_width)
image = convert_to_grayscale(image)
pixels_to_chars = map_pixels_to_ascii_chars(image)
len_pixels_to_chars = len(pixels_to_chars)
image_ascii = [pixels_to_chars[index: index + new_width] for index in
range(0, len_pixels_to_chars, new_width)]
return "\n".join(image_ascii)
def handle_image_conversion(image_filepath, new_width=60):
image = Image.open(image_filepath)
image_ascii = convert_image_to_ascii(image, new_width)
print(image_ascii)
from urllib import request
image_file_path = 'image2ascii.jpg' # 圖片的本地名稱
image_url = "http://upload.wikimedia.org/wikipedia/en/thumb/9/9c/Tencent_QQ.png/64px-Tencent_QQ.png" # 圖片的網絡地址
request.urlretrieve(image_url, image_file_path) # 將網絡圖片下載到本地,並重命名
handle_image_conversion(image_file_path) # 啓動handle_image_conversion()這個總函數
複製代碼
上節的例子仍然保留了默認的字符集和默認圖像寬度60
,接下來的部分留給讀者自由發揮,能夠經過修改以下參數得到本身的字符畫:
new_width
:字符畫的尺寸(寬的字符數)ASCII_CHARS
:字符集image_url
:網絡圖片地址,就是你想要轉換的圖片當你在網上看到一張圖片,右鍵-複製圖片地址。
將圖片地址賦值予變量image_url
,點擊運行便可。
from PIL import Image
from urllib import request
def scale_image(image, new_width=60):
(original_width, original_height) = image.size
aspect_ratio = original_height/float(original_width) * 0.5
new_height = int(aspect_ratio * new_width)
new_image = image.resize((new_width, new_height))
return new_image
def convert_to_grayscale(image):
return image.convert('L')
def map_pixels_to_ascii_chars(image, range_width=25):
pixels_in_image = list(image.getdata())
pixels_to_chars = [ASCII_CHARS[int(pixel_value/range_width)] for pixel_value in
pixels_in_image]
return "".join(pixels_to_chars)
def convert_image_to_ascii(image, new_width=60):
image = scale_image(image, new_width)
image = convert_to_grayscale(image)
pixels_to_chars = map_pixels_to_ascii_chars(image)
len_pixels_to_chars = len(pixels_to_chars)
image_ascii = [pixels_to_chars[index: index + new_width] for index in
range(0, len_pixels_to_chars, new_width)]
return "\n".join(image_ascii)
def handle_image_conversion(image_filepath, new_width=60):
image = Image.open(image_filepath)
image_ascii = convert_image_to_ascii(image, new_width)
print(image_ascii)
image_file_path = 'image2ascii.jpg' # 圖片的本地名稱
new_width = 60 # 字符畫寬幾個字符
ASCII_CHARS = [' ', '#', '?', '%', '.', '+', '.', '*', ':', ',', '@'] # 字符集
image_url = "http://upload.wikimedia.org/wikipedia/en/thumb/9/9c/Tencent_QQ.png/64px-Tencent_QQ.png" # 圖片的網絡地址
request.urlretrieve(image_url, image_file_path)
handle_image_conversion(image_file_path, new_width)
複製代碼
摘掉眼鏡看效果更佳。