天天寫測試指令碼寫煩了麼,可以嘗試下用程式設計來做點不一樣的事情。與好(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的光輝照耀著你