人工智能/吃炸鸡油油手切换视频的正确姿势

去社区提问

简介:人工智能听起来很高深莫测?今天带你利用Python实现手势识别,制作一个智能视频播放器,实用又方便,解锁更多Python新鲜体验。

吃炸鸡油油手切换视频的正确姿势

懒人播放器的准备工作

夏日周末的午后,我正悠闲在家吹着空调,一边吃炸鸡,一边准备刷最近被朋友们疯狂安利的新剧。

还有什么事情比什么都不用干,光在家躺着就能离退休更近一步还开心的呢~

然而打开视频才突然发现这集上次好像看过了…再看看自己吃炸鸡时沾幸福油渍的手,唉我这强迫症只好去洗个手再来切下一集了。

突然,一个天才般的想法从我脑海中迸发出来,如果计算机能看懂手势,根据手势命令自动切换视频就好了,这样就能安心吃炸鸡,不用去擦手了嘻嘻。

懒人让世界变得更美好。

做为一个行动派,洗完手干脆来敲代码吧,先来整理一下想要实现的功能。

  1. 切换下个视频
  2. 切换上个视频
  3. 通过识别手势数字播放对应集数视频
  4. 退出

为了搞定这个懒人播放器的终极目标,我们来拆解一下中间需要完成的小步骤:

  • 要有一个播放器,实现基本的视频播放和切换功能
  • 创建一个手势识别工具
  • 将手势识别结果和播放器结合起来,完成视频控制

理想很丰满,下面就要开始动手了~

特别提示:如果暂时不理解代码的含义也没有关系~只通过这些案例了解Python用途就达到了目标。12课时开始将进入详细的Python语法学习,要继续加油呀。

构建简单视频播放器,使用系统默认播放工具

第一步先来用代码实现一个简单视频播放器。

创建一个video目录,把正在追剧的mp4文件放到目录下,文件取名1.mp42.mp43.mp44.mp45.mp4

导入os模块,用于处理文件和目录。

在这里首先为你介绍Python中类和对象的概念。我们经常说Python是面向对象的语言,究竟是什么含义呢?

有些同学可能回答了:‘母胎solo,对象这个东西我不太懂。’

这位同学虽然我很同情你,但是此‘对象‘,非彼’对象‘,让我们严肃起来。

类是一个模板,它用来描述一类对象的行为和状态。

对象是类的实例。

类和对象,在生活中可以很容易找到例子。比如动物是一个类,那么大熊猫,长颈鹿就可以看作动物类中的对象。

每个对象拥有自己的状态和行为,例如熊猫是一个对象,它有自己的‘名字’,‘体重’,‘性别’等等。

Python中一切皆为‘对象’。

举一个小栗子带你了解两种编程思维的区别:

假如现在你想要吃午餐

选择1:制作一份蛋炒饭,按照步骤放入油,鸡蛋,米饭,配菜。万一中间步骤里加入了不喜欢吃的青椒,就只能重做一份。

选择2:点一份盖浇饭,米饭和菜都准备好了,想要吃回锅肉还是宫保鸡丁,直接选择就可以,万一选错再换一份菜就好了。

像蛋炒饭这样按照流程一步步进行操作就是面向过程的编程,盖浇饭这种‘组合式’则类似面向对象的编程方法。

面向过程是一件事“该怎么做“,面向对象是一件事“该让谁来做”,然后那个“谁”就是对象,他要怎么做是他自己的事,反正最后一群对象合力能把事做好就行了。

好了,了解过Python中的类和对象,下面我们创建一个Player对象,用于控制视频播放。在初始化时,读取video目录中视频文件列表,获取视频总数,用于切换视频时做边界定位。设置当前播放编号为0。

嗯?边界定位?是不是有点儿没明白是什么意思,其实非常简单,让我来为你解释一下。

进行视频切换时有这样一个问题,当前正在播放视频2,那么切换下一个就是计算2+1,即播放编号为3的视频,切换上一个自然就是2-1得到编号为1的视频。

可是当处理到边界情况,比如当前播放视频5,那么切换下一视频时就应该到视频6,然而视频总数只有5,所以按照逻辑,当前播放视频5时若切换下一个就应该从头播放视频1。同理,当前视频编号为1时切换上一个就应该自动播放视频5。

怎么把这个逻辑告诉计算机呢?

获取目录中视频总数就能轻松解决这个问题啦。计算下一个播放视频编号时对视频总数取余,就能得到正确的答案。

%在Python中代表取余数。

例如:当前播放是5,那么下一个播放(5+1)%5,6➗5,得到余数1,即下一个播放编号1。

当前播放2,得到下一个视频(2+1)%5,3➗5,得到余数3,播放编号3。

切换上一个视频也是同样的方法,你可以自己尝试计算一下~

下面就把切换视频和播放的功能写进Player中。

键盘上霹雳啪嗒一顿猛如虎的操作后,就飞速完成了这个任务,来看下面这段代码:

  1. import os
  2. from os import startfile
  3. class Player(object):
  4. def __init__(self):
  5. # 视频文件总数
  6. self.fileNum = len(os.listdir('./video'))
  7. # 当前播放的视频编号
  8. self.index = 0
  9. def play(self):
  10. fileName = './video/' + str(self.index + 1) + '.mp4'
  11. print('开始播放:', fileName)
  12. startfile(fileName)
  13. def next(self):
  14. self.index = (self.index + 1) % self.fileNum
  15. self.play()
  16. def prev(self):
  17. self.index = (self.index - 1) % self.fileNum
  18. self.play()
  19. def start_one(self, index):
  20. self.index = index
  21. self.play()

我们为它写入一个Play()方法,实现基础播放功能,start_one(),next(),prev()方法,为使用者分别实现播放指定编号的视频,切换下一视频,切换上一视频的功能。

一个简易播放器登场,这样一来我们就完成了懒人播放器的第一步。下面进入至关重要的手势识别环节。

至关重要的手势识别

创建手势识别器

如何让计算机看懂我比划的手势呢,这看起来貌似是一个高深而复杂的问题。

来在心里默念出我们的口号:困难就像纸老虎,我们绝对不发怵~!

先来看看手势识别过程需要用到的模块。

open cv是一个开源的计算机视觉库,它提供了很多函数,这些函数非常高效地实现了计算机视觉算法。

这里还需要调用百度手势识别的API接口。

新奇的知识点又增加了,看到这里你一定想知道,API(接口)是什么?

API是预先定义一些方法,使开发人员无需访问源码或理解内部工作机制,就可以访问一组例程。

举个常见的例子:在淘宝上下单付款之后,商家选用顺丰发货,然后你就可以在淘宝上实时查看当前的物流信息。淘宝和顺丰作为两家独立的公司,为什么会在淘宝上实时看到顺丰的快递信息?

这就要用到API,当查看自己的快递信息时,淘宝利用顺丰提供的API接口,可以实时调取信息呈现在自己的网站上。

除此,你也可以在微信端公众号或者小程序上输入订单号查取到快递信息。只要有合作,或是有允许,别的公司都可以通过顺丰提供的API接口调取到快递信息。既然有多方调用,那提供一个统一的调用规范会方便很多啦。

来看看百度的手势识别API给我们提供了哪些功能,感兴趣的同学也可以课下深入研究,说不定你也能产生新的灵感,用它实现更多懒人工具呢。

用这段代码实现初始化,下面我们导入必要包,初始化API调用类、初始化摄像头:

  1. import cv2
  2. from aip import AipBodyAnalysis
  3. from threading import Thread
  4. import time
  5. APP_ID = '20804321'
  6. API_KEY = 'ye****************dGZ'
  7. SECRET_KEY = 'jQ****************kPXFm'
  8. # 初始化API调用客户端
  9. gesture_client = AipBodyAnalysis(APP_ID, API_KEY, SECRET_KEY)
  10. # 初始化摄像头
  11. capture = cv2.VideoCapture(0)

程序需要实现通过摄像机捕捉图像的功能,并在屏幕上显示出来。运行下面这段代码可以在电脑上显示摄像头内容。

  1. # 显示摄像头拍摄效果
  2. def camera():
  3. global running
  4. while running:
  5. # 获得图片
  6. ret, frame = capture.read()
  7. # 在电脑上显示摄像头内容
  8. cv2.imshow('frame', frame)
  9. if cv2.waitKey(1) == ord('q'):
  10. break

这样以来,我们就能准确地把手势放到摄像头前,让计算机更好地对手势进行识别判断。

我们在摄像头前比划手势是一个连续动态的过程,要想对它分析,就需要从动态的过程中截取一帧图片,作为手势识别的内容。

准备完毕,先来怀着忐忑的心情测试一下识别效果。我们设定‘单手比心’时退出程序,手势1-5、拳头、OK都会在屏幕打印出识别的结果:

啊哈!真是一个平平无奇的程序小天才,我们已经实现了简易播放器功能,手势识别的难题也攻克完成,下面把二者的功能结合在一起就能实现懒人播放器了,想想还有点小激动呢。

播放器最终实现

下面创建手势处理函数handle(),使它能够通过参数获取手势内容,并根据不同内容调用Player的方法完成视频控制。把播放器功能和手势识别功能串连在一起。

我们可以利用handle函数实现如下功能:

  • 手势1-5:播放对应集数的视频
  • 拳头:播放上一个视频
  • OK:播放下一个视频

一起来看下面这段代码:

  1. hand = {'One': '第一集', 'Two': '第二集', 'Three': '第三集', 'Four': '第四集',
  2. 'Five': '第五集', 'Fist':'上一集','Ok':'下一集'}
  3. def handle(words):
  4. # 根据手势做操作
  5. print('收到', words)
  6. if words == 'Face':
  7. print('我不看脸,只看手势!')
  8. print(hand)
  9. elif words in hand:
  10. print(hand[words])
  11. if words == 'One':
  12. player.start_one(0)
  13. elif words == 'Two':
  14. player.start_one(1)
  15. elif words == 'Three':
  16. player.start_one(2)
  17. elif words == 'Four':
  18. player.start_one(3)
  19. elif words == 'Five':
  20. player.start_one(4)
  21. elif words == 'Fist':
  22. player.prev()
  23. elif words == 'Ok':
  24. player.next()
  25. else:
  26. print('无效手势!')

我们可以看到handle()方法括号内有一个words参数,每次调用方法时,为它传入的words参数都是不同值。

这里传入的参数也就是每次手势识别出的结果。根据参数的不同,再进行不同的切换和播放操作等。

现在看来,合并功能的小目标也成功实现啦~

最后一步我们会在前面实现的基础上创建手势识别核心函数,在循环中从摄像头获取照片,调用云端API,根据图片得到手势识别结果。然后将结果作为参数传入前面定义的handle()函数中进行处理。

  1. def gesture_recognition():
  2. global running
  3. while running:
  4. try:
  5. # 第一个结果ret为True或者False,代表有没有读取到图片
  6. # 第二个结果frame表示截取的一帧图片
  7. ret, frame = capture.read()
  8. # 获取图片数据
  9. image = cv2.imencode('.jpg', frame)[1]
  10. # 调用API识别手势
  11. gesture = gesture_client.gesture(image)
  12. words = gesture['result'][0]['classname']
  13. if words == 'Heart_single':
  14. # 退出
  15. print('程序结束')
  16. running = False
  17. else:
  18. # 处理手势
  19. handle(words)
  20. except:
  21. print('识别失败')
  22. if cv2.waitKey(1) == ord('q'):
  23. break
  24. time.sleep(1)

现在终于可以开始试验功能了,我们利用下面的代码创建player对象,并调用gesture_recognition()方法启动识别过程。

激动地搓搓手~

  1. # 运行状态
  2. running = True
  3. # 启动摄像头显示手势,引入线程防止在识别的时候卡死
  4. thread = Thread(target=camera)
  5. thread.start()
  6. player = Player()
  7. gesture_recognition()
  8. # 等待视频获取线程退出
  9. thread.join()

今天我们用Python实现了一个懒人播放器,妈妈再也不用担心我的油手弄脏电脑了~

回忆一下身边的场景,你是不是也曾出现过和我类似的困扰状况,下次说不定也可以写个代码来解决,看来我们懒人也是促进技术发展的重要因素之一呢。

懒惰使人进步,所有的发明创造都是为了可以更加省事或省力。比如说在地上拖动东西过于费劲和低效,于是发明了轮子和车;清洗过于费时费力又洗不干净,所以发明了洗衣机、洗碗机。

说不定…还能因此找到发家致富的新路。

今天的内容就到这里,是不是还想了解更多Python相关知识?欢迎添加班主任微信,和更多的朋友一起交流进步,我们下次再见啦~

扫描下方二维码添加班主任微信

人工智能 1/3

吃炸鸡油油手切换视频的正确姿势

1.0x

恭喜完成本课时的学习!
坚持学习

行动力超过

累计学习

学习下一课时