freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

巧用编程制作搞笑表情包,你和女神只有一组字符的距离!
2018-05-10 10:04:49

天天写测试脚本写烦了么,可以尝试下用编程来做点不一样的事情。与好(ji)友聊天的时候肯定见到过好多很搞笑的gif动态图,其中甚至还有一些是字符组成的动画.虽然画面上是各种字符,但整体上看却可以表达出各种很意思的场景,加上"脑补"的画面,分外有趣。

今天小编讲的就是字符动画,前几年比较流行,现在玩的人少了,但创意永不过时。先来一波图感受一下,有图有真相!

0.gif1.gif

制作工具

想制作字符动画,我们需要图形图像利器opencv

logo.png

制作思路

根据文档的说明,牛刀小试

[代码]

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

2.gif

掌握了基本用法,我们来试试播放动画帧,为了从简单的做起,我们选择曾经最流行的黑白动画badapple!进行尝试

3.gif

使用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()

4.gif

我们看到,将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)

5.gif

成功了!但是….速度好慢,而且画面好粗糙!肿么破?

有了

因为这里有很多并行操作:读取帧、修改分辨率、终端输出刷新,所以运行效率比较低,而且因为命令行字体太大,造成动画不够清晰我们换个思路,先读取动画进行编码,再读取输出,并且减小字体以提高分辨率!

[代码]

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)

6.gif

速度完美,清晰度完美,太棒了!而且像素化后味道更佳

0 (1).gif

想要效果更好的话,果断再提高分辨率就行了

思考:如果不是黑白分明的效果,而是有灰度变化的图片,应该如何处理呢?

stallman.png

开源之神stallman的光辉照耀着你

# 编程语言 # 字符动画
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者