天天写测试脚本写烦了么,可以尝试下用编程来做点不一样的事情。与好(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的光辉照耀着你