用Python让蔡徐坤在我的命令行里打篮球!|附完整代码

「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑
来源 | 01二进制(ID:gh_d1999add1857)
编辑 | Jane
【导语】作者自称是一个经常逛 B 站的肥宅。最近 B 站上流行的视频素材除了“换脸”,其次就要属“蔡xx打球”视频了。有模仿的、对比的、手绘的... ...更过分的是,竟然有人在命令行输出了他的打球视频。不过,视频中的动画好像是用某个软件生成的 txt 文件,作者就在想既然都可以用 txt 输出了,能不能用 python 在命令行中显示呢?
说到这作者便开始搜索资料,做后制作了下面一段视频“
代码是自己在网上查询资料后自己修改的,本着学习和分享的精神,今天就来分享下上面这段视频的制作过程。
原理
既然要开始做东西,首要的问题就是想好要怎么做,大家都知道视频是由一系列图片一帧一帧组成的,因此视频转字符动画最基本的便是图片转字符画。
在这里简单的说一下图片转字符画的原理:首先将图片转为灰度图,每个像素都只有亮度信息(用 0~255 表示)。然后我们构建一个有限字符集合,其中的每一个字符都与一段亮度范围对应,我们便可以根据此对应关系以及像素的亮度信息把每一个像素用对应的字符表示,这样字符画就形成了。
Tips:如果对"灰度图像"这个概念不太理解的可以查阅百度百科
计算一张图片的灰度图像的方法如下(来自百度百科):
所以我们要做的就只是让字符画在命令行里面动起来就可以了。
Tips:图片转字符画可以参考:https://www.shiyanlou.com/courses/370
准备
环境和工具:vscode、Mac OS、python 3.7
这次实验使用到的核心的库是opencv-python
Tips:这里分享一个我觉得还不错的opencv-python的中文文档:https://www.kancloud.cn/aollo/aolloopencv/269602
实验
实验开始前我们需要安装 opencv-python 的包:
1pip install opencv
读取视频:
1def genCharVideo(self, filepath):
2
3self.charVideo =[]
4
5# 用opencv读取视频
6
7cap = cv2.VideoCapture(filepath)
8
9self.timeInterval = round(1/ cap.get(5),3)
10
11nf = int(cap.get(7))
12
13print('Generate char video, please wait...')
14
15for i in pyprind.prog_bar(range(nf)):
16
17# 转换颜色空间,第二个参数是转换类型,cv2.COLOR_BGR2GRAY表示从BGR↔Gray
18
19rawFrame = cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY)
20
21frame = self.convert(rawFrame, os.get_terminal_size(), fill=True)
22
23self.charVideo.append(frame)
24
25cap.release()
这里的VideoCapture是用来读取视频的, cv2.cvtColor(input_imageflag)用于转换颜色空间,其中flag就是转换类型。对于 BGR↔Gray 的转换,我们使用的 flag 就是 cv2.COLORBGR2GRAY。对于 BGR↔HSV 的转换我们用的 flag 就是 cv2.COLORBGR2HSV。
将帧转换成字符画
1ascii_frame
2
3ascii_char ="$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
4
5
6
7# 像素映射到字符
8
9def pixelToChar(self, luminance):
10
11return self.ascii_char[int(luminance /256* len(self.ascii_char))]
12
13
14
15# 将普通帧转为 ASCII 字符帧
16
17def convert(self, img, limitSize=-1, fill=False, wrap=False):
18
19if limitSize !=-1and(img.shape[0]> limitSize[1]or img.shape[1]> limitSize[0]):
20
21img = cv2.resize(img, limitSize, interpolation=cv2.INTER_AREA)
22
23ascii_frame =''
24
25blank =''
26
27if fill:
28
29blank +=' '*(limitSize[0]- img.shape[1])
30
31if wrap:
32
33blank +='\n'
34
35for i in range(img.shape[0]):
36
37for j in range(img.shape[1]):
38
39ascii_frame += self.pixelToChar(img[i, j])
40
41ascii_frame += blank
42
43return ascii_frame
这段代码其实就是将已经转变的灰度图的像素值映射到 ascii_char上,然后输出到控制台。
控制输出
1# 创建线程
2
3getchar = threading.Thread(target=getChar)
4
5# 设置为守护线程
6
7getchar.daemon =True
8
9# 启动守护线程
10
11getchar.start()
12
13# 输出的字符画行数
14
15rows = len(self.charVideo[0])// os.get_terminal_size()[0]
16
17for frame in self.charVideo:
18
19# 接收到输入则退出循环
20
21if breakflag:
22
23break
24
25self.streamOut(frame)
26
27self.streamFlush()
28
29time.sleep(self.timeInterval)
30
31# 共 rows 行,光标上移 rows-1 行回到开始处
32
33self.streamOut('\033[{}A\r'.format(rows -1))
34
35# 光标下移 rows-1 行到最后一行,清空最后一行
36
37self.streamOut('\033[{}B\033[K'.format(rows -1))
38
39# 清空最后一帧的所有行(从倒数第二行起)
40
41for i in range(rows -1):
42
43# 光标上移一行
44
45self.streamOut('\033[1A')
46
47# 清空光标所在行
48
49self.streamOut('\r\033[K')
50
51if breakflag:
52
53self.streamOut('User interrupt!\n')
54
55else:
56
57self.streamOut('Finished!\n')
执行
最后在main函数中设置下要读取的文件名,再play一下就可以了
1if
2__name__ =='__main__':
3
4v2char = V2Char('vedio.mp4')
5
6v2char.play()
完整代码链接:
https://pan.baidu.com/s/1ZTc2a7DU-NIneI-CCbPu8Q
提取码: jc3n
作者简介:雇个城管打天下,理工男一枚。南京大学软件工程系硕士,一个还在做着拥有十万读者梦的互联网新人,或许一篇文章无法获得你的关注,但突然梦想觉醒的我还在努力着!
(本文为AI科技大本营转载文章,转载请微信联系原作者)
◆
倒计时两天
◆
「2019 Python开发者日」演讲议题全揭晓!这一次我们依然“只讲技术,拒绝空谈”10余位一线Python技术专家共同打造一场硬核技术大会。更有深度培训实操环节,为开发者们带来更多深度实战机会。目前大会倒计时 2 天,更多详细信息请咨询13581782348(微信同号)。
推荐阅读:
39个国外SCI抢发6万篇中国英文论文?然而,真正的问题是……
专访博世王红星:大数据和AI将是中国制造业升级新动力
抵制996!Python之父发声背后,这个社区一呼百应!
什么是网络爬虫?有什么用?怎么爬?终于有人讲明白了
京东或将裁员 12000 人!雷军年薪百亿;马云:阿里没人敢跟我打赌 | 极客头条
偷电、挖矿、赚快钱,这些大学生到底怎么了?
终于有人把5G和边缘计算的关系说清楚了 | 技术头条
频繁跳槽涨工资?会影响征信的!| 畅言
刺激!我31岁敲代码10年,明天退休!
❤点击“阅读原文”,了解「2019 Python开发者日」
相关文章:

javascript 操作Word和Excel的实现代码
1.保存html页面到word 复制代码 代码如下:<HTML> <HEAD> <title> </title> </HEAD> <body> <form id"form"> <table id "PrintA" width"100%" border"1" cellspacing"0" cel…

【C++】C++11新增关键字详解
目录一、auto1、auto 用来声明自动变量,表明变量存储在栈(C11之前)2、auto用于推断变量类型示例(C11)3、声明或定义函数时作为函数返回值的占位符,此时需要与关键字 decltype 一起使用。(C11&am…

linux批量创建用户和密码
老男孩教育第五关实战考试题:批量创建10个用户stu01-stu10,并且设置随机8位密码,要求不能用shell的循环(例如:for,while等),只能用linux命令及管道实现。 方法1:[rootoldboy /]# ech…

“重构”黑洞:26岁MIT研究生的新算法 | 人物志
点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑整理 | 若名出品 | AI科技大本营(ID:rgznai100)这是一个重要时刻。除了发布跟丈夫的两张合照外,Katie Bouman 在 Facebook 上鲜有内容更新&#…

【Ubuntu】VirtualBox显卡驱动VBoxVGA、VBoxSVGA、VMSVGA +3D对播放视频的影响
一、VBOXVGA、VMSVGA、VBOXSVGA简述 VBOXVGA和VBOXSVGA是vbox自己的,SVGA比VGA先进一点, VBoxSVGA: 使用Linux或者 Windows 7或者更高版本的新vm的默认图形控制器。 与传统的VBoxVGA选项相比,此图形控制器可提高性能和3D支持。 VBoxVGA: 将这…

MFC中利用CFileDialog选择文件并读取文件所遇到的问题和解决方法
在用MFC编写一个上位机时,需要实现选择和读取一个二进制文件,本来以为很简单的但是在实现过程中遇到很多问题,所幸都一一解决,这里做一下记录。 首先在实现文件选择,在界面上设置一个按钮,并在点击事件函数…

百度智能云一口气发布 14 个新产品,三大视频解决方案,产品最高降价 50%
产业智能化的浪潮正在加速传统互联网行业的升级,视频行业将成为最大的受益者。4 月 11 日,在 2019ABC INSPIRE 百度云智峰会上,百度副总裁、百度智能云总经理尹世明宣布,“百度云” 品牌全面升级为 “百度智能云”,以 …

开源代码hosting openfoundryfrom tw
http://www.openfoundry.org

倒计时1天!「2019 Python开发者日」报名即将关闭(附参会提醒)
「2019 Python开发者日」倒计时最后1天,仅剩少量余票,请扫码咨询 ↑↑↑相信很多人听过之前的 Python 进入小学课本、Python 进入浙江省高考等新闻,那么,有这么多头衔加持的 Python 究竟魅力在哪?与人工智能、大数据捆…

【Gstreamer】在虚拟机中无法使用硬件加速:gstreamer1.0-vaapi
1、问题描述 在虚拟机中,使用gstreamer播放视频,在没有安装gstreamer1.0-vaapi库时,还是正常的;在安装gstreamer1.0-vaapi后,不能播放视频。 错误信息如下: libva info: VA-API version 0.39.0 libva info: va_getDriverName() returns -1 libva error: va_getDriverNa…

如何在阿里云上安全的存放您的配置 - 续
在《如何在阿里云上安全的存放您的配置》一文中,我们介绍了如何通过ACM存放您的敏感配置,并进行加密。这样做的目的有两个: 在应用程序或对应生产环境容器或系统中,无需持久化任何敏感数据信息(如数据库连接串,等)&…

VLAN-VTP-Trunk
VLAN(Virtual LAN) VLAN可以隔离2层的广播域。A VLAN =(一个) 广播域 = (一个)逻辑子网路由器是隔离广播域的单个端口只能承载单个VLAN的流量。使用VLAN好处:1.有效的带宽利用2.提高了安全性3…

科大讯飞刷新纪录,机器阅读理解如何超越人类平均水平? | 技术头条
点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」明日开启,扫码咨询 ↑↑↑记者 | 琥珀出品 | AI科技大本营(公众号ID:rgznai100)对于日常从事模型训练的研究人员来讲,无论是图像处理还是语音识别,都离…

【经验】Lenovo/ThinkPad 进入BIOS的方法汇总
1、快捷汇总 联想电脑进入BIOS的快捷键有“F2、F1、Del/Delete、NOVO开机”,部分机型按F2、F1时需要FN键配合 2、常用键 Lenovo笔记本:F2 Fn Lenovo台式机:F2 ThinkPad:F1 联系官网说明: http://tsonline.lenovo.…

NO.7 今天我们是实用派,看看业务选择和部署以及常用故障解决方案是怎么做的...
Hello,大家好,这是第七期 上云用户必看期刊,本期我们主打实用派的相关业务选择和部署以及一些常用故障解决方案做分享。 今天我们不平凡,成为实用派 运维工程师需要掌握的技能https://yq.aliyun.com/articles/591171?spma2c4e.11…

php基础知识
一:php变量#一、PHP的变量定义:变量用于存储值,比如数字、文本字符串或数组、五中:string /integer /double /array /object 命名规则:1、PHP的变量名是区分大小写的。 2、变量名必须以$开头 3、变量名开头可以是下划线 4、变量名…

【Qt】QPixmap加载图片报错:Corrupt JPEG data: premature end of data segment Didn‘t expect more than one scan
1、问题描述 在使用QPixmap加载图片时失败,错误信息如下 Corrupt JPEG data: premature end of data segment Didnt expect more than one scan使用QPicture加载时错误信息如下: QPicturePaintEngine::checkFormat: Incorrect header QPicturePaintEng…

Python超越Java,Rust持续称王!Stack Overflow 2019开发者报告
点击上方↑↑↑蓝字关注我们~「2019 Python开发者日」明日开启,扫码咨询 ↑↑↑作者 | 郭芮出品 | CSDN(ID:CSDNnews)导语:2019 年 Stack Overflow 开发者调查报告最新出炉了!今年,近 90,000 名…
electron打包可选择安装位置,可自动更新
Electron打包调参软件(windows版) ----------------------------------可选安装位置,可自动更新,手动更新 一:引包:electron,electron-builder,electron-updater** npm i electron --save-dev n…

osi 模型 tcpip网络模型
OSI网络分层参考模型 网络协议设计者不应当设计一个单一、巨大的协议来为所有形式的通信规定完整的细节,而应把通信问题划分成多个 小问题,然后为每一个小问题设计一个单独的协议。这样做使得每个协议的设计、分析、时限和测试比较容易。协议划分的一…

我在旷视研究院做检测 | 技术头条
作者 | 俞刚,旷视研究院Detection组负责人。2014年博士毕业于新加坡南洋理工大学,加入旷视。主要负责检测,分割,跟踪,骨架,动作行为等方面的研究以及算法落地工作。俞刚博士带队参加 2017 COCOPlaces 挑战赛…

【Ubuntu】ubuntu设置GUI程序自启动
1、在启动脚本中添加 在脚本中添加,如“/etc/rc/”“etc/rc.d”“/etc/rc?.d”“/ect/profile”“.bash_profile”等等。 百度下有很多讲解,这里不再赘述。 2、利用ubuntu界面系统启动 终端中执行:gnome-session-properties,出…

(转)关于数据库主键和外键(终于弄懂啦)
一、什么是主键、外键: 关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键 比如 学生表(学号,姓名,性别,班级) 其中每个学生的学号是唯…

浏览器兼容:IE6,IE7,IE8,FIREFOX,Chrome
javascript部分1. document.form.item 问题问题:代码中存在 document.formName.item("itemName") 这样的语句,不能在FF下运行解决方法:改用 document.formName.elements["elementName"]2. 集合类对象问题问题:…

如何将DynamoDB的数据增量迁移到表格存储
为什么80%的码农都做不了架构师?>>> 摘要: AWS 的 Amazon DynamoDB 和阿里云的表格存储 TableStore 都是完全托管的NoSQL数据库服务,提供快速的、可预期的性能,并且可以实现无缝扩展。本篇文章介绍了如何使用 Lambda …

【Ubuntu】ping: unknown host www.baidu.com
1、问题描述 每次重新设置网络后,ping百度总是报错: $ ping www.baidu.com ping: unknown host www.baidu.com2、原因分析 原因是:查看/etc/resolv.conf,发现没有设置DNS服务。 $ cat /etc/resolv.conf # Dynamic resolv.con…

马云:“996 是一种巨大的福气”
作者 | 伍杏玲出品 | CSDN(ID:CSDNnews)【导语】自3月27日996.ICU话题诞生以来,目前GitHub已获得21万的Star,引发国内外的广泛关注和热议。很多人质疑996工作制,Python之父Guido Van Rossum更直言“996反人…

Firebug Console 与命令行全集
Console API 当打开 firebug (也包括 Chrome 等浏览器的自带调试工具),window 下面会注册一个叫做 console 的对象,它提供多种方法向控制台输出信息,供开发人员调试使用。下面是这些方法的一个简单介绍,适时地运用它们,…

100%的程序员都想挑战的算法趣题!| 码书
计算机的世界每天都在发生着深刻的变化。新操作系统的发布、CPU性能的提升、智能手机和平板电脑的流行、存储介质的变化、云的普及……这样的变化数不胜数。在这样日新月异的时代中,“算法”是不变的重要基石。要编写高效率的程序,就需要优化算法。无论开…
【Qt】qss样式表之:QCalendarWidget,日历窗口样式表设置
1、效果图: 2、qss样式表 其中表头的背景颜色等设置不起作用,只好在下面的代码中实现。 /*日历*/ QCalendarWidget QHeaderView {qproperty-minimumSectionSize:0; } QCalendarWidget QMenu{background-color: rgb