Python 让蔡徐坤在我的命令行里打篮球!| 技术头条

640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | 雇个城管打天下

责编 | 伍杏玲

本文经授权转载自01二进制(ID:gh_d1999add1857)

【CSDN 编者按】作者自称是一个经常逛 B 站的肥宅。最近 B 站上流行的视频素材除了“换脸”,其次就要属“蔡xx打球”视频了。有模仿的、对比的、手绘的,还有人在命令行输出了他的打球视频。不过,视频中的动画好像是用某个软件生成的 TXT 文件,作者就在想既然都可以用  TXT 输出了,能不能用 Python 在命令行中显示呢?

说到这作者便开始搜索资料,做后制作了下面一段视频“:

 

代码是自己在网上查询资料后自己修改的,本着学习和分享的精神,今天就来分享下上面这段视频的制作过程。

 

640?wx_fmt=png

原理

 

既然要开始做东西,首要的问题就是想好要怎么做,大家都知道视频是由一系列图片一帧一帧组成的,因此视频转字符动画最基本的便是图片转字符画。

在这里简单的说一下图片转字符画的原理:首先将图片转为灰度图,每个像素都只有亮度信息(用 0~255 表示)。然后我们构建一个有限字符集合,其中的每一个字符都与一段亮度范围对应,我们便可以根据此对应关系以及像素的亮度信息把每一个像素用对应的字符表示,这样字符画就形成了。

Tips:如果对"灰度图像"这个概念不太理解的可以查阅百度百科

计算一张图片的灰度图像的方法如下(来自百度百科):

640?wx_fmt=jpeg

所以我们要做的就只是让字符画在命令行里面动起来就可以了。

Tips:图片转字符画可以参考:https://www.shiyanlou.com/courses/37

环境和工具:vscode、Mac OS、Python 3.7

这次实验使用到的核心的库是OpenCV-Python

Tips:这里分享一个我觉得还不错的OpenCV-Python的中文文档: https://www.kancloud.cn/aollo/aolloopencv/269602

 

 

640?wx_fmt=png

实验

 

实验开始前我们需要安装 OpenCV-Python 的包:

 

pip install opencv-python

读取视频:

 

def genCharVideo(self, filepath):
self.charVideo =[]
# 用opencv读取视频
cap = cv2.VideoCapture(filepath)
self.timeInterval = round(1/ cap.get(5),3)
nf = int(cap.get(7))
print('Generate char video, please wait...')
for i in pyprind.prog_bar(range(nf)):
# 转换颜色空间,第二个参数是转换类型,cv2.COLOR_BGR2GRAY表示从BGR↔Gray
rawFrame = cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY)
frame = self.convert(rawFrame, os.get_terminal_size(), fill=True)
self.charVideo.append(frame)
cap.release()

这里的VideoCapture是用来读取视频的, cv2.cvtColor(input_imageflag)用于转换颜色空间,其中flag就是转换类型。对于 BGR↔Gray 的转换,我们使用的 flag 就是 cv2.COLORBGR2GRAY。对于 BGR↔HSV 的转换我们用的 flag 就是 cv2.COLORBGR2HSV。

将帧转换成字符画

 

ascii_frame
ascii_char ="$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
# 像素映射到字符
def pixelToChar(self, luminance):
return self.ascii_char[int(luminance /256* len(self.ascii_char))]
# 将普通帧转为 ASCII 字符帧
def convert(self, img, limitSize=-1, fill=False, wrap=False):
if limitSize !=-1and(img.shape[0]> limitSize[1]or img.shape[1]> 
    limitSize[0]):
    img = cv2.resize(img, limitSize, 
    interpolation=cv2.INTER_AREA)
    ascii_frame =''
    blank =''
if fill:
   blank +=' '*(limitSize[0]- img.shape[1])
if wrap:
   blank +='\n'
for i in range(img.shape[0]):
   for j in range(img.shape[1]):
      ascii_frame += self.pixelToChar(img[i, j])
      ascii_frame += blank
      return ascii_frame

 

这段代码其实就是将已经转变的灰度图的像素值映射到 ascii_char上,然后输出到控制台。

控制输出

 

# 创建线程
getchar = threading.Thread(target=getChar)
# 设置为守护线程
getchar.daemon =True
# 启动守护线程
getchar.start()
# 输出的字符画行数
rows = len(self.charVideo[0])// os.get_terminal_size()[0]
for frame in self.charVideo:
    # 接收到输入则退出循环
    if breakflag:
        break
    self.streamOut(frame)
    self.streamFlush()
    time.sleep(self.timeInterval)
    # 共 rows 行,光标上移 rows-1 行回到开始处
    self.streamOut('\033[{}A\r'.format(rows -1))
    # 光标下移 rows-1 行到最后一行,清空最后一行
    self.streamOut('\033[{}B\033[K'.format(rows -1))
    # 清空最后一帧的所有行(从倒数第二行起)
    for i in range(rows -1):
       # 光标上移一行
       self.streamOut('\033[1A')
       # 清空光标所在行
       self.streamOut('\r\033[K')
       if breakflag:
          self.streamOut('User interrupt!\n')
       else:
          self.streamOut('Finished!\n')

执行

最后在main函数中设置下要读取的文件名,再Play一下就可以了。

作者简介:雇个城管打天下,理工男一枚。南京大学软件工程系硕士,一个还在做着拥有十万读者梦的互联网新人,或许一篇文章无法获得你的关注,但突然梦想觉醒的我还在努力着!

源码:

https://pan.baidu.com/s/1ZTc2a7DU-NIneI-CCbPu8Q 

提取码: jc3n 

Python 为何能成最强编程语言?

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

 

【End】

640?wx_fmt=jpeg

作为码一代,想教码二代却无从下手:

听说少儿编程很火,可它有哪些好处呢?

孩子多大开始学习比较好呢?又该如何学习呢?

最新的编程教育政策又有哪些呢?

下面给大家介绍CSDN新成员:极客宝宝(ID:geek_baby)

戳他了解更多↓↓↓

640?wx_fmt=jpeg

 热 文 推 荐 

☞但见高通笑,哪闻英特尔哭?

☞为什么说 5G 绝对不是伪命题?| 人物志

☞IoT、3D 扫描抢救巴黎圣母院!

☞零编程基础、大龄全职妈妈是如何写出两个商业网站的?

☞下过富士康工厂、做过华为外包,这位程序员是如何花 6 年逆袭成为技术大佬的?

☞《权力的游戏》最终季上线!谁是你最喜爱的演员?这里有一份Python教程 | 附源码

☞微服务落地,我们在考虑什么?| 技术头条

☞爆料! 18张图、55个链接, 证据都在这了, 你还说自己是中本聪?

程序员被骗"黑砖窑":监禁、恐吓、996无休编程!

 

System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"

 

640?wx_fmt=png你点的每个“在看”,我都认真当成了喜欢640?wx_fmt=png

Python虽然不是专门用于绘画的工具,但它可以借助一些图形库如PIL(Python Imaging Library)或者更现代的如matplotlib、pygame等来绘制简单的图像,包括人物像。如果你想画出徐坤打篮球的画面,通常需要结合图片处理技术,将徐坤的照片或者卡通形象和篮球场景结合起来。 例如,你可以先在网上找到徐坤和篮球的相关素材,然后利用Python的图像处理库进行裁剪、合并或者添加动画效果。下面是一个简化的步骤描述: 1. 导入所需的库: ```python from PIL import Image, ImageDraw, ImageFont ``` 2. 加载背景图片(篮球场)和人物图片(徐坤): ```python background = Image.open('basketballCourt.jpg') bkg_draw = ImageDraw.Draw(background) avatar = Image.open('kaikai_basketball.png') ``` 3. 将人物图片调整大小并放置到适当位置: ```python position = ... # 根据需求计算人物在球场上的位置 avatar_resized = avatar.resize((..., ...)) # 调整大小 background.paste(avatar_resized, position) ``` 4. 可能还需要添加文字或者其他元素,例如球框、篮球等: ```python font = ImageFont.truetype('arial.ttf', size=50) text = '徐坤打篮球' text_position = (..., ...) text_image = font.getsize(text) background.paste(Image.new('RGBA', text_image, color=(0, 0, 0, 0)), text_position, mask=text_image) background.paste(Image.open('basketball.png'), (..., ...), text_image) # 添加篮球 ``` 这只是一个基本框架,实际操作可能会更复杂,取决于你想要的具体效果。记得处理好版权问题,确保使用的图片允许商业使用。
评论 49
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值