深度学习和OpenCV对象检测(MobileNet SSD多进程视频流实时识别)

python多进程背景

Unix

Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。

python Multiprocessing

由于Windows没有fork调用,Windows上无法使用,因此python提供了一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。多进程 Multiprocessing 和多线程 threading 类似, 都是在 python 中用来并行运算的. 由于python存在GIL全局锁的功能,影响了python的多线程并行计算能力,为了解决此类问题,python提供了多进程的概念。

python Queue

queue的功能是将每个核或线程的运算结果放在队里中, 等到每个线程或核运行完毕后再从队列中取出结果, 继续加载运算。因为多线程或者多进程调用的函数不能有返回值, 所以使用Queue存储多个线程或者进程运算的结果

  1. 使用queue.put()来记录每个进程或者线程的值
  2. 使用queue.get()来获取每个进程或者线程的值

MobileNet SSD多进程视频流实时识别

有了python多进程的基础知识,我们来优化上期代码,来进行视频流的实时对象检测

1 导入需要的第三方库

import 第三方库

2 初始化训练模型

#14 # 15 输入prototxt与caffe 的模型文件地址

#17 class列表是SSD caffe检测模型中的20个label标签,还包括一个background

#21 针对每个label,随机建一个颜色,以便后期检测图片时 ,使用不同的颜色框,以便区分

# 22 使用cv的dnn加载模型数据

初始化模型

3 新建多进程处理任务函数

由于net.forward 函数是阻塞式函数,顾名思义本次检测未完成前,不允许程序执行下一条指令,所以导致了图片检测的速度较慢,我们多进程函数主要来处理此函数,以便快速检测

# 28 判断输入队列中是否有数据

# 29 使用get方法获取输入队列中的图片

#30 31 设置图片尺寸,并计算blob值

# 32 blob值传递神经网络

#33 正向传递预测

#34 把预测结果通过put方法加入队列

4 新建video 类函数提取视频中的图片

#37 初始化预测值,默认none

#38 40 创建VideoStream、创建FPS

#43 读取视频中的帧图片

#44 调整图片宽度

#45 获取图片宽度与高度

#46 47 若输入队列中无image数据,向输入队列中保存image数据

#48 49 若输出队列中有检测结果数据, 获取检测结果数据

5 获取检测结果,并把检测结果加入图片中

本段代码跟前几期的文章只在第一条上有差别,因为我们前期初始化了detections,我们判断一下detections是否是none,来加速无效代码的运行

6 显示最终图片

当for循环结束后,我们把当前帧获取的图片检测结果实时显示出来,由于多进程的设计,当进程执行时,video_start函数可以继续执行,并不是阻塞式程序,便加快了图片检测的速度,

当输入q退出时,便可以看到多进程处理的速度大概是每秒60帧

电脑配置不是太高: i5+4G

7、主函数入口

由于多进程的特殊性,新建进程与启动进程,需要在if __name__ == ‘__main__’:函数中

#81 初始化输入队列,设置最大值1

#82 初始化输出队列,设置最大值1

设置输入输出队列都是1,避免进程中数据混淆

# 初始化多进程,进程初始化,使用如下函数,特别注意:target 是多进程的函数名称,无小括号

p = Process(target=multiProcess, args=(inputQueue, outputQueue,))

”’

p.daemon = True: 主进程运行完不会检查子进程的状态(是否执行完),直接结束进程;

p.daemon = False: 主进程运行完先检查子进程的状态(是否执行完),子进程执行完后,直接结束进程;

daemon默认值为False

”’

#86 开始进程

#87 开始实时视频检测

以上便是完整的代码结构,opencv没有GPU加速,采用多进程的方式,也可以加快代码运行,使用多进程,大大提高了代码运行速度,也加速了图片检测的速度,我们观看实时生成的视频时,看着也比较流畅,没有了先前的卡顿感