<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python 實(shí)現(xiàn)圖片轉(zhuǎn)字符畫,靜態(tài)圖、動(dòng)態(tài)圖都能轉(zhuǎn)!

          共 1732字,需瀏覽 4分鐘

           ·

          2020-11-08 12:44

          文 |?野客

          來源:Python 技術(shù)「ID: pythonall」

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

          靜態(tài)圖片

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

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

          主要代碼實(shí)現(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?的數(shù)個(gè)矩心以隨機(jī)順序排列,所以需要簡單處理矩心
          ????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?轉(zhuǎn)變?yōu)閷?shí)際的明暗程度列表
          ????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 動(dòng)圖

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

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

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

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

          #?拆分 gif 將每一幀處理成字符畫
          def?gif2pic(file,?ascii_chars,?isgray,?font,?scale):
          ????'''
          ????file:?gif?文件
          ????ascii_chars:?灰度值對(duì)應(yīng)的字符串
          ????isgray:?是否黑白
          ????font:?ImageFont?對(duì)象
          ????scale:?縮放比例
          ????'
          ''
          ????im?=?Image.open(file)
          ????path?=?os.getcwd()
          ????if(not?os.path.exists(path+"/tmp")):
          ????????os.mkdir(path+"/tmp")
          ????os.chdir(path+"/tmp")
          ????#?清空?tmp?目錄下內(nèi)容
          ????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
          ????#?將圖片轉(zhuǎn)換為?RGB?模式
          ????im?=?Image.open(img).convert('RGB')
          ????#?設(shè)定處理后的字符畫大小
          ????raw_width?=?int(im.width?*?scale)
          ????raw_height?=?int(im.height?*?scale)
          ????#?獲取設(shè)定的字體的尺寸
          ????font_x,?font_y?=?font.getsize('?')
          ????#?確定單元的大小
          ????block_x?=?int(font_x?*?scale)
          ????block_y?=?int(font_y?*?scale)
          ????#?確定長寬各有幾個(gè)單元
          ????w?=?int(raw_width/block_x)
          ????h?=?int(raw_height/block_y)
          ????#?將每個(gè)單元縮小為一個(gè)像素
          ????im?=?im.resize((w,?h),?Image.NEAREST)
          ????#?txts?和?colors?分別存儲(chǔ)對(duì)應(yīng)塊的?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?對(duì)象以寫入?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)

          原圖如下:

          黑白效果圖如下:

          彩色效果圖如下:

          總結(jié)

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

          -END-


          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品久久久无码 | 超碰在线中文1159 | 人妻巨大乳HD免费看 | 九九操| 亚洲AV无码一区 |