视频关键字、关键帧过滤系统

视频关键字、关键帧过滤系统

    • 综述
    • 工程实现
      • 流媒体服务模块
      • Flask框架
      • 过滤器(Vdfilter)
      • 看门狗
      • 视频切片CutVideo.py
      • 视频抓流FetchStream.py
      • 语音识别+人脸检测+过滤主函数AutoFilter
      • 推流模块Stream.py
    • 算法篇
    • 心得体会
    • 写在最后

综述

本系统可以根据用户提供的关键字和人脸图像,实时过滤选定文件中的内容,并提取出包含关键字和人脸图像的视频片段。源码可从此处获得

工程实现

流媒体服务模块

  • 使用multiprocessing.Process创建一个进程,让该进程管理流媒体服务,和主进程并行。

    vdsource = multiprocessing.Process(target=node_start)

  • 使用subprocess创建子进程,后台模式启动流媒体服务。使用阻塞模式,将该进程的输出重定向到当前进程,实时打印流媒体服务的状态。

    subprocess.check_output(command, stdin=open(os.devnull), shell=use_shell)

  • 流媒体服务基于Nodejs实现,可以通过Rtmp、Http的方式向该服务推流,客户端通过指定的播放地址来向该服务拉取视频流,实现流媒体播放。

Flask框架

  • 使用Flask框架来进行前后端通信,前端界面通过Get和Post方式向后台发送请求,以获得相应数据
  • Get方式获得后台视频库中的本地视频信息,包括视频文件名,路径和缩略图。
  • Post方式主要用于过滤器启动后返回检测到的片段机器信息,以及前台对后台过滤器的操作命令(包括初始化、开始、停止和状态检查)

过滤器(Vdfilter)

  • 类初始化主要完成基础变量设置,包括过滤模式(本地和在线)、视频地址、推流地址
  • 初始化中会创建一个流对象,该对象自底向上继承了推流、语音识别、视频切边以及文件处理所有类,方便各个类之间共享状态信息
  • 用多线程方式初始化流对象中三个主要过程为三个线程,即视频切片(在线模式为视频抓流)、语音识别和过滤、视频推流三个线程并设置为守护模式,主进程退出后,这些线程自动退出
  • 强制停止:这里涉及到强制kill一个python线程,使用_async_raise()函数实现
    def _async_raise(tid, exctype):
        """raises the exception, performs cleanup if needed"""
        tid = ctypes.c_long(tid)
        if not inspect.isclass(exctype):
            exctype = type(exctype)
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
        if res == 0:
            raise ValueError("invalid thread id")
        elif res != 1:
            # """if it returns a number greater than one, you're in trouble,
            # and you should call it again with exc=NULL to revert the effect"""
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError("PyThreadState_SetAsyncExc failed")
# 调用方式:

publish = threading.Thread(target=newfilter.push) # 创建一个线程
publish.start()

if publish.is_alive():
    _async_raise(publish.ident, SystemExit)
    publish.join()
  • clean() 函数在过滤器自然退出后看门狗清理进程极临时文件
  • get_fildthumbpic() 函数用于返回当前已经过滤出来的视频片段缩略图,返回给客户端
  • get_chipsdata() 返回过滤缓存队列中的数据,即已过滤好的片段,返回后从队列中删除

看门狗

  • 使用多线程的方式在主进程中创建一个线程,执行看门狗函数
  • 看门狗每隔5秒检测一次主进程中的过滤任务是否已经结束,如果结束,销毁Vdfilter对象,以便开始新的视频过滤。

视频切片CutVideo.py

  • 这个模块功能相对简单并独立,主要使用ffmpeg来将视频每10s为一个片段切片,存入指定文件夹,用subprocess方式调用shell命令启动ffmpeg,以备过滤

视频抓流FetchStream.py

  • 该模块和视频切片属于同级模块,当过滤模式为在线模式时,该模块主要完成抓取流媒体,并存入指定文件夹,以备过滤
  • 抓流采用多线程方式抓取

语音识别+人脸检测+过滤主函数AutoFilter

  • 该模块实现了两个功能:1,对上一级切好(或者抓好)的视频进行语音识别+人脸检测;2,根据识别和检测结果和要检测的内容进行比对实现过滤
  • 关于语音识别和人脸检测的算法方案详见算法部分,本部分只讨论工程实现
  • filter_start():过滤器控制函数,实时监测过滤状态和外界指令,如过滤完成或者接收到停止信号,退出循环,并等待主进程终结
  • filter_save():过滤实现,对传入的文件调用语音识别和人脸识别检测器进行检测,若检测到切割检测到的片段,并保存到指定文件夹

推流模块Stream.py

  • 该模块功能也相对简单,当过滤模式为本地模式,则将原视频推流到流媒体服务,客户端直接拉取流媒体播放
  • 当过滤模式为直播模式,客户端从直播源直接拉取,此处不做任何任务。

算法篇

  • 语音识别
    • 语音识别模块是在此工程Autosub基础上包装完成,替换了识别引擎,最后方案为百度的语音识别API
    • 主要过程为:对传入的语音进行切片,并通过音频来检测有语音的部分,然后百度语音转录API进行语音识别并回传
    • 该部分的独立代码可在这里获取
  • 人脸识别
    • 人脸识别主要采用dlib库中的人脸检测和特征提取详见代码
    • 为了提高检测速度以达到实时监测,主要采取了这几个策略:
      • 若源视频分辨率太高则相应降低分辨率,若分辨率太低相应增大图片尺寸
      • 使用dib的GPU版本,使用GPU加速检测
      • 通过用矩阵运算实现人脸特征匹配的加速

心得体会

  • 本项目前期遇到的最大问题就是关于多进程和多线程的处理问题,本项目有三个模块需要并行执行,而其中的抓流和语言识别模块又需要多线程处理实现高并发。做此项目之际,初次使用多进程和多线程,使用方式甚是简陋,而且很不规范(进程套线程,线程套进程)。若有大神能实现一个更好的版本,可否给小弟瞻仰学习一番,以发扬当代码农之同甘共苦精神!
  • 项目中后期遇到的主要问题就是检测精度不高并且速度问题,语音识别由于包装了原有的工程,没有调整一些参数,使得检测不太精准。人脸识别即使开了GPU,当图像分辨率变大时候计算效率依然捉襟见肘,GPU使用效率却不高,由此可见计算密集型代码使用C++实现的重要性!
  • 其它,想起来再补充吧,暂时就这了

写在最后

  • 本系统为笔者研究生练手项目,代码设计思路笨拙,实现方式蹩脚。功能虽然实现了,但是却有无数bug正在潜伏,伺机而动。
  • 前期致力于功能实现,后面又有论文追赶(主要是菜),此项目就搁置,没有做过多的优化!

你可能感兴趣的:(人脸识别,语音识别,视频检索,人脸识别,语音识别,视频处理)