1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Python 實現(xiàn)圖片轉字符畫,靜態(tài)圖、動態(tài)圖都能轉!

        共 1732字,需瀏覽 4分鐘

         ·

        2020-11-08 12:44

        文 |?野客

        來源:Python 技術「ID: pythonall」

        字符畫是一種由字母、標點或其他字符組成的圖畫,它產生于互聯(lián)網時代,在聊天軟件中使用較多,本文我們看一下如何將自己喜歡的圖片轉成字符畫。

        靜態(tài)圖片

        首先,我們來演示將靜態(tài)圖片轉為字符畫,功能實現(xiàn)主要用到的 Python 庫為 OpenCV,安裝使用?pip install opencv-python?命令即可。

        功能實現(xiàn)的基本思路為:利用聚類將像素信息聚為 3 或 5 類,顏色最深的一類用數字密集度表示,陰影的一類用橫杠(-)表示,明亮部分用空白表示。

        主要代碼實現(xiàn)如下:

        def?img2strimg(frame,?K=5):???
        ????if?type(frame)?!=?np.ndarray:
        ????????frame?=?np.array(frame)
        ????height,?width,?*_?=?frame.shape??
        ????frame_gray?=?cv2.cvtColor(frame,?cv2.COLOR_BGR2GRAY)
        ????frame_array?=?np.float32(frame_gray.reshape(-1))
        ????criteria?=?(cv2.TERM_CRITERIA_EPS?+?cv2.TERM_CRITERIA_MAX_ITER,?10,?1.0)
        ????flags?=?cv2.KMEANS_RANDOM_CENTERS
        ????#?得到?labels(類別)、centroids(矩心)
        ????compactness,?labels,?centroids?=?cv2.kmeans(frame_array,?K,?None,?criteria,?10,?flags)
        ????centroids?=?np.uint8(centroids)
        ????#?labels?的數個矩心以隨機順序排列,所以需要簡單處理矩心
        ????centroids?=?centroids.flatten()
        ????centroids_sorted?=?sorted(centroids)
        ????#?獲得不同?centroids?的明暗程度,0?為最暗
        ????centroids_index?=?np.array([centroids_sorted.index(value)?for?value?in?centroids])
        ????bright?=?[abs((3?*?i?-?2?*?K)?/?(3?*?K))?for?i?in?range(1,?1?+?K)]
        ????bright_bound?=?bright.index(np.min(bright))
        ????shadow?=?[abs((3?*?i?-?K)?/?(3?*?K))?for?i?in?range(1,?1?+?K)]
        ????shadow_bound?=?shadow.index(np.min(shadow))
        ????labels?=?labels.flatten()
        ????#?將?labels?轉變?yōu)閷嶋H的明暗程度列表
        ????labels?=?centroids_index[labels]
        ????#?解析列表
        ????labels_picked?=?[labels[rows?*?width:(rows?+?1)?*?width:2]?for?rows?in?range(0,?height,?2)]
        ????canvas?=?np.zeros((3?*?height,?3?*?width,?3),?np.uint8)
        ?#?創(chuàng)建長寬為原圖三倍的白色畫布
        ????canvas.fill(255)
        ????y?=?8
        ????for?rows?in?labels_picked:
        ????????x?=?0
        ????????for?cols?in?rows:
        ????????????if?cols?<=?shadow_bound:
        ????????????????cv2.putText(canvas,?str(random.randint(2,?9)),
        ????????????????????????????(x,?y),?cv2.FONT_HERSHEY_PLAIN,?0.45,?1)
        ????????????elif?cols?<=?bright_bound:
        ????????????????cv2.putText(canvas,?"-",?(x,?y),
        ????????????????????????????cv2.FONT_HERSHEY_PLAIN,?0.4,?0,?1)
        ????????????x?+=?6
        ????????y?+=?6
        ????return?canvas

        原圖如下:

        效果圖如下:

        GIF 動圖

        接下來我們演示將 GIF 轉為字符畫,功能實現(xiàn)主要用到的 Python 庫為 imageio、Pillow,安裝使用?pip install imageio/Pillow?命令即可。

        功能實現(xiàn)的基本思路如下:

        • 將 gif 圖片的每一幀拆分為靜態(tài)圖片
        • 將所有靜態(tài)圖片變?yōu)樽址?/section>
        • 將所有字符畫重新合成 gif

        主要代碼實現(xiàn)如下:

        #?拆分 gif 將每一幀處理成字符畫
        def?gif2pic(file,?ascii_chars,?isgray,?font,?scale):
        ????'''
        ????file:?gif?文件
        ????ascii_chars:?灰度值對應的字符串
        ????isgray:?是否黑白
        ????font:?ImageFont?對象
        ????scale:?縮放比例
        ????'
        ''
        ????im?=?Image.open(file)
        ????path?=?os.getcwd()
        ????if(not?os.path.exists(path+"/tmp")):
        ????????os.mkdir(path+"/tmp")
        ????os.chdir(path+"/tmp")
        ????#?清空?tmp?目錄下內容
        ????for?f?in?os.listdir(path+"/tmp"):
        ????????os.remove(f)
        ????try:
        ????????while?1:
        ????????????current?=?im.tell()
        ????????????name?=?file.split('.')[0]+'_tmp_'+str(current)+'.png'
        ????????????#?保存每一幀圖片
        ????????????im.save(name)
        ????????????#?將每一幀處理為字符畫
        ????????????img2ascii(name,?ascii_chars,?isgray,?font,?scale)
        ????????????#?繼續(xù)處理下一幀
        ????????????im.seek(current+1)
        ????except:
        ????????os.chdir(path)

        #?將不同的灰度值映射為?ASCII?字符
        def?get_char(ascii_chars,?r,?g,?b):
        ????length?=?len(ascii_chars)
        ????gray?=?int(0.2126?*?r?+?0.7152?*?g?+?0.0722?*?b)
        ????return?ascii_chars[int(gray/(256/length))]


        #?將圖片處理成字符畫
        def?img2ascii(img,?ascii_chars,?isgray,?font,?scale):
        ????scale?=?scale
        ????#?將圖片轉換為?RGB?模式
        ????im?=?Image.open(img).convert('RGB')
        ????#?設定處理后的字符畫大小
        ????raw_width?=?int(im.width?*?scale)
        ????raw_height?=?int(im.height?*?scale)
        ????#?獲取設定的字體的尺寸
        ????font_x,?font_y?=?font.getsize('?')
        ????#?確定單元的大小
        ????block_x?=?int(font_x?*?scale)
        ????block_y?=?int(font_y?*?scale)
        ????#?確定長寬各有幾個單元
        ????w?=?int(raw_width/block_x)
        ????h?=?int(raw_height/block_y)
        ????#?將每個單元縮小為一個像素
        ????im?=?im.resize((w,?h),?Image.NEAREST)
        ????#?txts?和?colors?分別存儲對應塊的?ASCII?字符和?RGB?值
        ????txts?=?[]
        ????colors?=?[]
        ????for?i?in?range(h):
        ????????line?=?''
        ????????lineColor?=?[]
        ????????for?j?in?range(w):
        ????????????pixel?=?im.getpixel((j,?i))
        ????????????lineColor.append((pixel[0],?pixel[1],?pixel[2]))
        ????????????line?+=?get_char(ascii_chars,?pixel[0],?pixel[1],?pixel[2])
        ????????txts.append(line)
        ????????colors.append(lineColor)
        ????#?創(chuàng)建新畫布
        ????img_txt?=?Image.new('RGB',?(raw_width,?raw_height),?(255,?255,?255))
        ????#?創(chuàng)建?ImageDraw?對象以寫入?ASCII
        ????draw?=?ImageDraw.Draw(img_txt)
        ????for?j?in?range(len(txts)):
        ????????for?i?in?range(len(txts[0])):
        ????????????if?isgray:
        ????????????????draw.text((i?*?block_x,?j?*?block_y),?txts[j][i],?(119,136,153))
        ????????????else:
        ????????????????draw.text((i?*?block_x,?j?*?block_y),?txts[j][i],?colors[j][i])
        ????img_txt.save(img)

        #?讀取?tmp?目錄下文件合成?gif
        def?pic2gif(dir_name,?out_name,?duration):
        ????path?=?os.getcwd()
        ????os.chdir(dir_name)
        ????dirs?=?os.listdir()
        ????images?=?[]
        ????num?=?0
        ????for?d?in?dirs:
        ????????images.append(imageio.imread(d))
        ????????num?+=?1
        ????os.chdir(path)
        ????imageio.mimsave(out_name?+?'_ascii.gif',images,duration?=?duration)

        原圖如下:

        黑白效果圖如下:

        彩色效果圖如下:

        總結

        本文我們利用 Python 演示了將靜態(tài)圖和 GIF 轉為字符畫的方法,大家如果有興趣的話,可以將自己喜歡的圖轉一下,如果對轉換效果不滿意,還可以修改代碼,改成自己滿意的效果。

        -END-


        瀏覽 40
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            2攻一受做哭调教高h | 欧美在线视频播放 | 黄色一级裸体片 | 天天日天天操天天插 | 国产精品菊爆在线播放 | 国产又白又嫩又紧又爽18p | 男人天堂黄片 | 国产欧美日韩免费看aⅴ视频 | 超碰色色色 | 被艹到爽|