1. cv2.dnn.readNetFromCaffe(prototxt, model)  用于进行SSD网络的caffe框架的加载

参数说明:prototxt表示caffe网络的结构文本,model表示已经训练好的参数结果

2.t=delib.correlation_tracker() 使用delib生成单目标的追踪器

3.delib.rectangle(int(box[0]), int(box[1]), int(box[2]), int(box[3])) 用于生成追踪器所需要的矩形框[(startX, startY), (endX, endY)]

4.t.start_track(rgb, rect) # 初始化生成器的开始状态

5.cv2.Writer(name, fourcc, (frame.shape[1], frame.shape[0]), True)进行图片写入到视频里面

参数说明: name表示视频的名字,fourcc表示视频格式,frame.shape[1] 表示视频的长和宽,

6.cv2.dnn.blobFromImage(frame, 0.007843, (w, h), 127.5)  对图像进行归一化操作(-1, 1),

参数说明:frame表示输入图片,0.007843表示需要乘的数,即1/127.5,(w, h)表示图像大小,127.5表示需要减去的数

7. net.SetInput(rgb) 表示将图片输入到caffe网络中

参数说明: rgb表示已经经过归一化的图片

8. net.forward() 输出前向传播的预测结果

9. oq = multiprocessing.Queue() 生成用于多进行传输过程中的线程

10.p = multiprocessing.Process(target=start_track, args=(bb, label, rgb, iq, oq))  # 用于对函数创建进程

参数说明:target表示需要转换为进程的函数,args表示传入到进程里函数的参数

SSD是一种目标检测的算法,其使用多个卷积层进行预测,原理在后续的博客中进行补充

对于目标追踪的视频,我们先使用SSD找出图片中人物的位置,然后使用dlib中的跟踪器对物体进行跟踪

由于每一个人物框对应一个跟踪器,因此我们可以对每一个跟踪器起一个进程,使用输入和输出线程,用于构造多进程

使用的数据,需要一个训练好的SSD权重参数,还需要caffe关于SSD的prototxt文件
代码说明:

下面的代码可以近似认为是由两部分构成

第一部分:使用SSD网络进行预测,获得box的位置

第二部分:使用dlib构造tracker跟踪器,带入box构造带有矩形框的追踪器,然后使用dlib的追踪器对图像每一帧的位置进行追踪

代码:

第一步:构造进程函数,使用iq.get 和oq.put进行追踪器的位置更新

第二步:构造输入的参数, 使用cv2.dnn.readNetFromCaffe()构造SSD网络模型

第三步:使用cv2.Videocapture视频读入,fps=FPS().start() 用于计算FPS

第四步:进入循环,使用.read()读取图片

第五步:使用cv2.resize()对图片大小进行放缩变化,使用cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #将读入的BGR转换为RGB,用于模型的预测

第六步:如果需要进行输出,使用cv2.VideoWriter实例化视频存储器

第七步:如果还没有使用SSD获得矩形框,使用cv2.dnn.blobFromImage对图像进行归一化操作

第八步:使用net.setInput将图片传入,使用net.forward获得前向传播输出的结果

第九步:如果置信度大于给定的置信度,获得SSD的标签,以及前向传播的位置信息

第十步:使用multiprocessing.Queue构造线程iq和oq,将线程添加到列表中,使用multiprocessing.process构造多进程,用于分别建立单个跟踪器

第十一步:如果已经生成了通道,使用iq.put(rgb)传入图像,使用oq.get()获得追踪器更新的位置

第十二步:进行画图操作,如果存在writer就进行写入

第十三步:更新fps.update

第十四步:统计运行的时间和FPS,并对vs进行释放内存

  1. import cv2
  2. import numpy as np
  3. import argparse
  4. import dlib
  5. import multiprocessing
  6. from utils import FPS
  7.  
  8. # 第一步:构造追踪器并进行结果的更新
  9. def start_tracker(box, label, rgb, inputQueue, outputQueue):
  10.  
  11. # 构造追踪器
  12. t = dlib.correlation_tracker()
  13. # rect为SSD获得的矩形框的位置
  14. rect = dlib.rectangle(int(box[0]), int(box[1]), int(box[2]), int(box[3]))
  15. # 设置追踪器的初始位置
  16. t.start_track(rgb, rect)
  17. # 获得下一帧图片
  18. while True:
  19. # 传入的图片
  20. rgb = inputQueue.get()
  21. if rgb is not None:
  22. # 更新追踪器
  23. t.update(rgb)
  24. # 获得追踪器的当前位置
  25. pos = t.get_position()
  26.  
  27. startX = int(pos.left())
  28. startY = int(pos.top())
  29. endX = int(pos.right())
  30. endY = int(pos.bottom())
  31.  
  32. # 把结果输出放入到output里面, 返回标签和位置
  33. outputQueue.put((label, (startX, startY, endX, endY)))
  34.  
  35. # 第二步:设置参数,并使用cv2.dnn.readFrameCaffe构造SSD的网络模型
  36. ap = argparse.ArgumentParser()
  37. ap.add_argument('-p', '--prototxt', default='mobilenet_ssd/MobileNetSSD_deploy.prototxt',
  38. help='path to caffe "deploy" prototxt file')
  39. ap.add_argument('-m', '--model', default='mobilenet_ssd/MobileNetSSD_deploy.caffemodel',
  40. help='path to Caffe pre-trained model')
  41. ap.add_argument('-v', '--video', default='race.mp4',
  42. help='path to input video file')
  43. ap.add_argument('-o', '--output', type=str,
  44. help='path to optional output video file')
  45. ap.add_argument('-c', '--confidence', type=float, default=0.2,
  46. help='minimu probability to filter weak detections')
  47.  
  48. args = vars(ap.parse_args())
  49.  
  50. # 用于存放输入线程和输出线程
  51. inputQueues = []
  52. outputQueues = []
  53. # 21种分类的结果
  54. CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
  55. "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
  56. "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
  57. "sofa", "train", "tvmonitor"]
  58.  
  59. print('[INFO] loading model...')
  60. # 构造SSD网络模型
  61. net =cv2.dnn.readNetFromCaffe(args['prototxt'], args['model'])
  62.  
  63. print('[INFO] starting video stream...')
  64. # 第三步:使用cv2.VideoCapture读取视频
  65. vs = cv2.VideoCapture(args['video'])
  66. writer = None
  67.  
  68. fps = FPS().start()
  69.  
  70. if __name__ == '__main__':
  71. # 第四步:进入循环,使用.read() 读取图片
  72. while True:
  73. ret, frame = vs.read()
  74.  
  75. if frame is None:
  76. break
  77.  
  78. # 第五步:进行图像的维度变化, 并且将BGR转换为RGB格式
  79. h, w = frame.shape[:2]
  80. width = 600
  81. r = width / float(w)
  82. dim = (width, int(r*h))
  83. frame = cv2.resize(frame, dim, cv2.INTER_AREA)
  84. rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  85.  
  86. # 第六步:进行视频的保存
  87. if args['output'] is not None and writer is None:
  88. fourcc = cv2.VideoWriter_fourcc(*'MJPG')
  89. writer = cv2.VideoWriter(args['output'], fourcc,
  90. (frame.shape[1], frame.shape[0]), True)
  91.  
  92. # 如果输入进程的维度为0,进入循环首先检测位置
  93. if len(inputQueues) == 0:
  94. # 第七步:使用cv2.dnn.blobFromImage()对图片进行归一化操作
  95. (h, w) = frame.shape[:2]
  96. blob = cv2.dnn.blobFromImage(frame, 0.007843, (w, h), 127.5)
  97. # 第八步:使用net.setInput输入图片,net.forward()获得前向传播的结果
  98. net.setInput(blob)
  99. detections = net.forward()
  100. # 第九步:对结果进行循环,如果置信度大于阈值,则获得其标签和box位置信息
  101. for i in np.arange(0, detections.shape[2]):
  102. confidence = detections[0, 0, i, 2]
  103. if confidence > args['confidence']:
  104. idx = int(detections[0, 0, i, 1])
  105. label = CLASSES[idx]
  106.  
  107. if label != 'person':
  108. continue
  109.  
  110. box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
  111. (startX, startY, endX, endY) = box.astype('int')
  112. bb = (startX, startY, endX, endY)
  113.  
  114. # 第十步:创建输入q和输出q,创建process线程,使用process.start()启动线程
  115. iq = multiprocessing.Queue()
  116. oq = multiprocessing.Queue()
  117. inputQueues.append(iq)
  118. outputQueues.append(oq)
  119.  
  120. # 在多个核上运行, 创建多核
  121. p = multiprocessing.Process(
  122. target=start_tracker,
  123. args=(bb, label, rgb, iq, oq)
  124. )
  125. p.daemon = True
  126. p.start()
  127.  
  128. cv2.rectangle(frame, (startX, startY), (endX, endY),
  129. (0, 255, 0), 2)
  130. cv2.putText(frame, label, (startX, startY-15),
  131. cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 2)
  132.  
  133. else:
  134. # 第十一步:如果生成了进程,循环输入线程,传入rgb图片,获得输出线程的label和更新位置的输出
  135. for iq in inputQueues:
  136. iq.put(rgb)
  137.  
  138. for oq in outputQueues:
  139. (label, (startX, startY, endX, endY)) = oq.get()
  140. # 在frame图像上绘制矩形框和text
  141. cv2.rectangle(frame, (startX, startY), (endX, endY),
  142. (0, 255, 0), 2)
  143. cv2.putText(frame, label, (startX, startY - 15),
  144. cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 2)
  145. # 第十二步:进行绘图,并进行视频的写入操作
  146. if writer is not None:
  147. writer.write(frame)
  148.  
  149. cv2.imshow('Frame', frame)
  150. key = cv2.waitKey(1) & 0xFF
  151. if key == 27:
  152. break
  153. # 第十三步 fps更新
  154. fps.update()
  155. # 第十四步:统计运行时间和FPS,释放内存
  156. fps.stop()
  157. print('[INFO] elapsed time {:.2f}'.format(fps.elapsed()))
  158. print('[INFO] approx. FPS:{:.2f}'.format(fps.fps()))
  159.  
  160. if writer is not None:
  161. writer.release()
  162.  
  163. cv2.destroyAllWindows()
  164. vs.release()

效果展示:

FPS副代码

  1. import cv2
  2. import numpy as np
  3. import datetime
  4.  
  5. class FPS:
  6.  
  7. def __init__(self):
  8.  
  9. self._start = None
  10. self._end = None
  11. self._numFrames = 0
  12.  
  13. def start(self):
  14. # start the timer
  15. self._start = datetime.datetime.now()
  16. return self
  17.  
  18. def stop(self):
  19. # stop the timer
  20. self._end = datetime.datetime.now()
  21.  
  22. def update(self):
  23. self._numFrames += 1
  24.  
  25. def elapsed(self):
  26. return (self._end - self._start).total_seconds()
  27.  
  28. def fps(self):
  29. return self._numFrames / self.elapsed()

机器学习进阶-目标追踪-SSD多进程执行 1.cv2.dnn.readnetFromCaffe(用于读取已经训练好的caffe模型) 2.delib.correlation_tracker(生成追踪器) 5.cv2.writer(将图片写入视频中) 6.cv2.dnn.blobFromImage(图片归一化) 10.multiprocessing.process(生成进程)的更多相关文章

  1. 机器学习进阶-目标跟踪-KCF目标跟踪方法 1.cv2.multiTracker_create(构造选框集合) 2. cv2.TrackerKCF_create(获得KCF追踪器) 3. cv2.resize(变化图像大小) 4.cv2.selectROI(在图像上框出选框)

    1. tracker = cv2.multiTracker_create() 获得追踪的初始化结果 2.cv2.TrackerKCF_create() 获得KCF追踪器 3.cv2.resize(fr ...

  2. php如何截取出视频中的指定帧作为图片

    php如何截取出视频中的指定帧作为图片 一.总结 一句话总结:截取视频指定帧为图片,php ffmpeg扩展已经完美实现,并且php ffmpeg是开源的 二.php如何截取出视频中的指定帧作为图片 ...

  3. 基于OpenCV实现对图片及视频中感兴趣区域颜色识别

    基于OpenCV实现图片及视频中选定区域颜色识别 近期,需要实现检测摄像头中指定坐标区域内的主体颜色,通过查阅大量相关的内容,最终实现代码及效果如下,具体的实现步骤在代码中都详细注释,代码还可以进一步 ...

  4. MFC 对话框Picture Control(图片控件)中静态和动态显示Bmp图片

    版权声明:本文为博主原创文章,转载请注明CSDN博客源地址! 共同学习,一起进步~ https://blog.csdn.net/Eastmount/article/details/26404733   ...

  5. android 阿拉伯语下,图库中编辑运动轨迹图片,动画中会显示绿色的图片

    alps/packages/apps/Camera/src/com/android/camera/FileSaver.java 1:import java.util.Locale; 2:modify ...

  6. 将图片写入二进制文件,再从二进制文件还原图片(c++)

    #include "string" #include "iostream" #include "fstream" using namespa ...

  7. 解决PNG图片在IE6中背景不透明方法_解决IE6中PNG背

    解决PNG图片在IE6中背景不透明方法_解决IE6中PNG背   目录 解决代码 解决png图片在html中 解决png作为网页背景-css 1.解决PNG图片在IE6中背景不透明的CSS与JS代码 ...

  8. 50行Python代码实现视频中物体颜色识别和跟踪(必须以红色为例)

    目前计算机视觉(CV)与自然语言处理(NLP)及语音识别并列为人工智能三大热点方向,而计算机视觉中的对象检测(objectdetection)应用非常广泛,比如自动驾驶.视频监控.工业质检.医疗诊断等 ...

  9. Python+OpenCV4:读写输入和输出的简单实践(图片、视频、摄像头)

    典型的文件处理流程如下: 利用命令行参数 sys.argv 命令行参数是读取文件时常用的方式. 命令行参数保存在 sys.argv 的列表中,列表的第一个元素是脚本名称,后面的元素是命令行参数: 通过 ...

随机推荐

  1. Android开发之环境配置篇

    Android环境配置: 一.JDK(不用安装) 1.拷贝 D:\Java\jdk1.8.0_91 文件内容 2. 安卓ADT ADT(Android Development Tools):安装ADT ...

  2. LinkedList的自定义实现

    一.背景 LinkedList双向链表: 代码: Node.java: package com.cy.collection; public class Node { Node previous; // ...

  3. flume-拦截器、channel选择器、sink组合sink处理器

    1. Flume Interceptors Flume有能力修改/删除流程中的events.这是在拦截器(interceptor)的帮助下完成的.拦截器(Interceptors)是实现org.apa ...

  4. 学习笔记之Data Science

    Data science - Wikipedia https://en.wikipedia.org/wiki/Data_science Data science, also known as data ...

  5. 解决hash冲突的三个方法(转)

    https://www.cnblogs.com/wuchaodzxx/p/7396599.html 目录 开放定址法 线性探测再散列 二次探测再散列 伪随机探测再散列 再哈希法 链地址法 建立公共溢出 ...

  6. openVPN设置本地密码验证

    wget https://git.io/vpn -O openvpn-install.sh && bash openvpn-install.sh https://github.com/ ...

  7. http和https的区别联系

    超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂 ...

  8. 可变卷积Deforable ConvNet 迁移训练自己的数据集 MXNet框架 GPU版

    [引言] 最近在用可变卷积的rfcn 模型迁移训练自己的数据集, MSRA官方使用的MXNet框架 环境搭建及配置:http://www.cnblogs.com/andre-ma/p/8867031. ...

  9. Office365开发者计划——账户信息上显示已是订阅用户,点击其他授权信息,仍然需要激活

    一.申请过程跳过. 二.安装之后,点击账号,查看授权状态,如题所述. 解决办法: 链接地址:https://answers.microsoft.com/zh-hans/msoffice/forum/a ...

  10. 第6章 静态路由和动态路由(4)_OSPF动态路由协议

    6. OSPF动态路由协议 6.1 OSPF协议(Open Shortest Path First,OSPF开放式最短路径优先协议) (1)通过路由器之间通告链路的状态来建立链路状态数据库,网络中所有 ...