巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!

Anybaby發表於2018-05-07
天天寫測試指令碼寫煩了麼,可以嘗試下用程式設計來做點不一樣的事情。與好(ji)友聊天的時候肯定見到過好多很搞笑的gif動態圖,其中甚至還有一些是字元組成的動畫.雖然畫面上是各種字元,但整體上看卻可以表達出各種很意思的場景,加上"腦補"的畫面,分外有趣。
今天小編講的就是字元動畫,前幾年比較流行,現在玩的人少了,但創意永不過時。先來一波圖感受一下,有圖有真相!
巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!

製作工具

想製作字元動畫,我們需要圖形影像利器opencv

製作思路

根據文件的說明,牛刀小試
[程式碼]
import numpy as np
import cv2

image = cv2.imread("opencv.jpg", 1)
image2 = cv2.resize(image, (400, 500))

cv2.imshow("image", image2)
cv2.waitKey(0)
cv2.destroyAllWindows()

透過使用opencv開啟圖片彩色序列,並顯示到內嵌的圖形介面上,這裡我們顯示了opencv的logo
巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
掌握了基本用法,我們來試試播放動畫幀,為了從簡單的做起,我們選擇曾經最流行的黑白動畫badapple!進行嘗試
巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
使用opencv讀取動畫的每一幀,輸出到終端,看看是什麼
[程式碼]
from curses import wrapper
import numpy as np
import cv2

cap = cv2.VideoCapture("test.avi")

while cap.isOpened():
    
    ret, frame = cap.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    print(gray)

    cv2.imshow("frame", gray)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
我們看到,將opencv的圖片幀輸出到螢幕,發現是灰度值的矩陣,最小0最大255
我們可以嘗試用終端的黑色代表0,用“#”號來代表白色,試試同步輸出
[程式碼]
from curses import wrapper
import numpy as np
import cv2

def main(stdscr):

    height, width = stdscr.getmaxyx()

    cap = cv2.VideoCapture("test.avi")

    while cap.isOpened():

        ret, frame = cap.read()

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray_2 = cv2.resize(gray, (width, height))

        y = 0
        for i in gray_2:
            y += 1
            x = 0
            for j in i:
                x += 1
                if x < width-1 and y < height-1:
                    if j == 0:
                        stdscr.addstr(y, x, " ")
                    else:
                        stdscr.addstr(y, x, "#")

        stdscr.refresh()                

        cv2.imshow("frame", gray)

        if cv2.waitKey(1) & 0xFF == ord("q"):
            break

    cap.release()
    cv2.destroyAllWindows()

wrapper(main)
巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
成功了!但是….速度好慢,而且畫面好粗糙!腫麼破?
有了
因為這裡有很多並行操作:讀取幀、修改解析度、終端輸出重新整理,所以執行效率比較低,而且因為命令列字型太大,造成動畫不夠清晰我們換個思路,先讀取動畫進行編碼,再讀取輸出,並且減小字型以提高解析度!
[程式碼]
import time
import sys
import curses
import cv2
import numpy as np

stdscr = curses.initscr()
height,width = stdscr.getmaxyx()
curses.endwin()

def std_print(text):
    sys.stdout.write("\r" + " "*80 + "\r")
    sys.stdout.write(text)
    sys.stdout.flush()

with open("./anime", "w") as f:

    cap = cv2.VideoCapture("test.avi")

    '''
    while cap.isOpened():
        ret, frame = cap.read()
        img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow("frame", img)
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    cv2.destroyAllWindows()
    '''


    frames = 0
    while(cap.isOpened()):

        ret,frame = cap.read()

        img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        img2 = cv2.resize(img, (width, height))

        x = 0
        for i in img2:
            x += 1
            y = 0
            for j in i:
                y += 1 
                if j != 0:
                    f.write("#")
                else:
                    f.write(" ")

        frames += 1
        std_print("frames: %s"%frames)

    cap.release()

播放程式碼
import time
from curses import wrapper

def main(stdscr):

    text = ""

    height,width = stdscr.getmaxyx()

    with open("./anime", "r") as f:
        text = f.read()     

    def anime(text):
        for c in text:
            yield c

    ani = anime(text)

    while True:
        for y in range(height):
            for x in range(width):
                char = next(ani)
                if 0 < x < width-1 and 0 < y < height-1:
                    stdscr.addstr(y, x, char)

        stdscr.refresh()

wrapper(main)

巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
速度完美,清晰度完美,太棒了!而且畫素化後味道更佳
巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
想要效果更好的話,果斷再提高解析度就行了
思考:如果不是黑白分明的效果,而是有灰度變化的圖片,應該如何處理呢?
巧用程式設計製作搞笑表情包,你和女神只有一組字元的距離!
開源之神stallman的光輝照耀著你

相關文章