一、概述
通常我们可以使用opencv获取视频流进而对usb camera或者本地的视频进行可视化。那么我们能否获取远程电脑的视频流,通过某些算法进行处理之后可视化出来?比如说我们想调用房间里的摄像头,查看🐈有没有捣乱;或者调用无人小车🚙的前置摄像头,和其共享视野,这些场景就需要通过某种途径获取到远程电脑(即使没有X服务)的视频流,然后在自己的笔记本上显示出来了。
这篇文章将记录一个简单的pipeline,实现视频的读取、处理,并将视频流定向到HTML中。本文将涉及以下知识点:
复习基本的视频流获取
安装并调用dlib库中的人脸检测(基于hog)和特征点检测API对视频进行处理
通过Flask将视频流定向到HTML
通过threading确保并发线程安全(进而支持多clients同时使用该视频流)
通过Python生成器将获取的视频帧重新输出为“视频流”的形式
Fig. 1 效果展示:网页获取脚本中处理过的视频流
二、基本组件
本章复习/学习一下本文涉及到的一些问题,有了这些基本组件,后面只需要做一些衔接的工作就可以了。
2.1 获取本地视频/webcam的视频流
通常可以用OpenCV写个循环来获取、处理视频流。可以设置VideoCapture的参数为0或者视频文件路径来切换视频流的来源。
import cv2
cap = cv2.VideoCapture(0)
while(True):
# capture frame-by-frame
ret , frame = cap.read()
#转换为灰度图
gray = cv2.cvtColor(frame , cv2.COLOR_BGR2GRAY)
# rgb = frame[...,::-1] # 转换为RGB
# display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) &0xFF ==ord('q'): #按q键退出
break
# when everything done, release the capture
cap.release()
cv2.destroyAllWindows()
再看下Adrian封装的imutils.video.VideoStream,如果用web camera的话其实和上面的代码没有明显区别。比较不同的可能是将视频流用一个Thread类对象封装起来,将逐帧获取的过程作为一个守护进程来看待。最后结束时直接用Thread.stop()方法结束这个进程。然后省去了cap.release和destroyAllWindow这两个操作。
其实我并不理解这种通过Thread的做法有什么其他的考虑。这个回头如果遇到有类似的再深入了解吧。
Adrian的封装代码见下图:
Fig. 2 imutils中对cv2.VidewCapture的封装
不过VideoStream主要的功能是提供了一个使用树莓派设备获取视频流的选项。看了下源码,这部分主要是调用了另一个比较大的开源库picamera。这个库里面的代码动不动三四千行...果然写驱动的都是真的大佬..随手看了下,这个docs相当人性化,还给了一些树莓派相关的Setup和贴心小提示,比如不要热插拔相机之类的,后面等我的Pi回来以后详细了解下~
Fig. 3 picamera模块给出了树莓派相机相关的setup
言归正传,虽然imutils中的VideoStream和OpenCV的差别不大,这里还是试一试:
from imutils.vid