当前位置:   article > 正文

【opencv】计算机视觉:实时目标追踪_opencv 目标追踪

opencv 目标追踪

目录

前言

解析

深入探究


前言

目标追踪技术对于民生、社会的发展以及国家军事能力的壮大都具有重要的意义。它不仅仅可以应用到体育赛事当中目标的捕捉,还可以应用到交通上,比如实时监测车辆是否超速等!对于国家的军事也具有一定的意义,比如说导弹识别目标等方向。所以说实时目标追踪技术对于整个社会来说都是非常重要的!目前被应用的比较多的,而且效果较好的是YOLO系列,目前已经更新到了YOLO7。原作者更新到了YOLO3之后就不再更新YOLO这个系列了,因为被一些不法人员应用到了军事上,给民众要造成了一定的伤害!但是依旧没有阻挡住YOLO的发展。但是我们提出来的这个是基于计算机视觉的,那么为什么有了YOLO这么好的东西我们还要基于计算机视觉来做呢?因为YOLO训练的模型占用的内存一般不小,这就会影响了一些东西的使用,比如说摄像头!就没有办法有这么大的内存来存储,所以还需要一些不需要那么大内存的东西来去实时跟踪目标!
 

解析

首先我们来根据代码来讲解一下如何追踪实时物体!
首先我们导入库和配置参数,对于参数的配置。我们需要在参数框架上输入--video videos/nascar.mp4 --tracker kcf。表示的意思就是我们导入的视频是nascar.mp4,然后用kcf这个框架来干活。

  1. import argparse
  2. import time
  3. import cv2
  4. import numpy as np
  5. # 配置参数
  6. ap = argparse.ArgumentParser()
  7. ap.add_argument("-v", "--video", type=str,
  8. help="path to input video file")
  9. ap.add_argument("-t", "--tracker", type=str, default="kcf",
  10. help="OpenCV object tracker type")
  11. args = vars(ap.parse_args())

然后我们写一些OpenCV已经有的算法。

  1. OPENCV_OBJECT_TRACKERS = {
  2. "csrt": cv2.legacy.TrackerCSRT_create,
  3. "kcf": cv2.legacy.TrackerKCF_create,
  4. "boosting": cv2.legacy.TrackerBoosting_create,
  5. "mil": cv2.legacy.TrackerMIL_create,
  6. "tld": cv2.legacy.TrackerTLD_create,
  7. "medianflow": cv2.legacy.TrackerMedianFlow_create,
  8. "mosse": cv2.legacy.TrackerMOSSE_create
  9. }

这里注意一定要按照这个来写。其他的由于版本问题,可能会有问题。对于新老版本是不一样的。
然后我们建立多个追踪器。并且开始读入视频数据。这里的trackers就是我们需要建立的多目标追踪器。

  1. trackers = cv2.legacy.MultiTracker_create()
  2. vs = cv2.VideoCapture(args["video"])

这里我们取出来视频中的每一帧,然后视频结束了就直接结束。对于每一帧我们都要做一个操作就是同比例处理图像。

  1. while True:
  2. # 取当前帧
  3. frame = vs.read()
  4. # (true, data)
  5. frame = frame[1]
  6. if frame is None:
  7. break
  8. # resize每一帧
  9. (h, w) = frame.shape[:2]
  10. width=600
  11. r = width / float(w)
  12. dim = (width, int(h * r))
  13. frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)

对于追踪结果来说,我们需要每一帧每一帧的进行更新框框。因为物体在运动,所以我们也要更新框框。

(success, boxes) = trackers.update(frame)
  1. for box in boxes:
  2. (x, y, w, h) = [int(v) for v in box]
  3. cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

对于每一个框框我们在更新的时候我们都要绘制出来!

  1. cv2.imshow("Frame", frame)
  2. key = cv2.waitKey(100) & 0xFF

然后将框框展示出来。cv2.waitKey(100)这个部分100可以改成其他的这里可以调节视频的快慢。

  1. if key == ord("s"):
  2. # 选择一个区域,按s
  3. box = cv2.selectROI("Frame", frame, fromCenter=False,
  4. showCrosshair=True)

如果我们按下S键,然后我们就可以手动的框出来ROI区域了。

  1. tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]()#创建一个追踪器 添加追踪器
  2. trackers.add(tracker, frame, box)

这里创建出来追踪器,然后添加上。

  1. elif key == 27:
  2. break
  3. vs.release()
  4. cv2.destroyAllWindows()

最后退出。

可以手动的任意追踪目标!!!完美!!!

追踪效果总体来说还是不错的!

深入探究

然后又继续做了一个多目标自动识别目标追踪。这里我们以运动员短跑为案例继续来讲解。

这里面我们导入库和第三方参数。

  1. from utils import FPS
  2. import numpy as np
  3. import argparse
  4. import dlib
  5. import cv2
  6. ap = argparse.ArgumentParser()
  7. ap.add_argument("-p", "--prototxt", required=True,
  8. help="path to Caffe 'deploy' prototxt file")
  9. ap.add_argument("-m", "--model", required=True,
  10. help="path to Caffe pre-trained model")
  11. ap.add_argument("-v", "--video", required=True,
  12. help="path to input video file")
  13. ap.add_argument("-o", "--output", type=str,
  14. help="path to optional output video file")
  15. ap.add_argument("-c", "--confidence", type=float, default=0.2,
  16. help="minimum probability to filter weak detections")
  17. args = vars(ap.parse_args())

其中参数导入的话是这样:

  1. --prototxt mobilenet_ssd/MobileNetSSD_deploy.prototxt --model mobilenet_ssd/MobileNetSSD_deploy.caffemodel --video race.mp4
  2. --model mobilenet_ssd/MobileNetSSD_deploy.caffemodel
  3. --video race.mp4

把这段代码直接复制粘贴到参数配置当中就好。
然后我们建立一些分类标签,看看计算机到时候框出来的很多很多框框都属于什么东西,然后我们进行过滤操作。

  1. CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
  2. "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
  3. "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
  4. "sofa", "train", "tvmonitor"]

读取网络模型。

  1. print("[INFO] loading model...")
  2. net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])

其中cv2.dnn.readNetFromCaffe(prototxt, model) 用于进行SSD网络的caffe框架的加载
参数说明:prototxt表示caffe网络的结构文本,model表示已经训练好的参数结果把视频读入进来。

  1. print("[INFO] starting video stream...")
  2. vs = cv2.VideoCapture(args["video"])
  3. writer = None
  1. trackers = []
  2. labels = []
  3. fps = FPS().start()

这里我们设置两个列表,等会来添加追踪器和标签信息。并且计算一下视频的fps数值。fps也就是一秒钟计算机可以处理多少帧图像。

  1. while True:
  2. # 读取一帧
  3. (grabbed, frame) = vs.read()
  4. # 是否是最后了
  5. if frame is None:
  6. break
  7. # 预处理操作
  8. (h, w) = frame.shape[:2]
  9. width=600
  10. r = width / float(w)
  11. dim = (width, int(h * r))
  12. frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
  13. rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

在这里面和上面一样同样也要同比例放大或者缩小每一帧图像。然后有一个重要操作,就是一定要将BGR图像通道改成RGB通道顺序。

  1. if args["output"] is not None and writer is None:
  2. fourcc = cv2.VideoWriter_fourcc(*"MJPG")
  3. writer = cv2.VideoWriter(args["output"], fourcc, 30,
  4. (frame.shape[1], frame.shape[0]), True)

这里是保存数据,如果output这个文件夹是空的并且writer也是空的,那么我们将实时视频保存下来。这个就涉及到了视频保存的代码,有需要的可以自行提取。

  1. if len(trackers) == 0:
  2. # 获取blob数据
  3. (h, w) = frame.shape[:2]
  4. blob = cv2.dnn.blobFromImage(frame, 0.007843, (w, h), 127.5)

cv2.dnn.blobFromImage主要是对图像进行一个预处理,其中0.007843表示各通道数值的缩放比例。127.5表示各个通道减去的均值。

  1. net.setInput(blob)
  2. detections = net.forward()

这里面把预处理的图像输入到了模型的输入当中,然后进行了一次前向传播。这里面我们就得到了很多的检测框框了。

  1. for i in np.arange(0, detections.shape[2]):
  2. # 能检测到多个结果,只保留概率高的
  3. confidence = detections[0, 0, i, 2]
  4. # 过滤
  5. if confidence > args["confidence"]:
  6. # extract the index of the class label from the
  7. # detections list
  8. idx = int(detections[0, 0, i, 1])
  9. label = CLASSES[idx]
  10. # 只保留人的
  11. if CLASSES[idx] != "person":
  12. continue

这里面在前向传播当中,我们得到一些概率值较大的,这里怎么定义较大呢,用args["confidence"]这个数值来定义,如果大于我们设定的概率数值,我们就把他的索引拿出来,然后取出来对应的标签,如果不是人的话我们就过滤除去,最后留下这一帧图像当中所有检测到的人。

  1. box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
  2. (startX, startY, endX, endY) = box.astype("int")

这里面就是我们要得到这个框框,然后拿到这个框框的左上角和右下角坐标。

  1. t = dlib.correlation_tracker()
  2. rect = dlib.rectangle(int(startX), int(startY), int(endX), int(endY))
  3. t.start_track(rgb, rect)

然后我们创建一个追踪器,然后得到检测到的框框,然后开始追踪,追踪的时候按照rgb,并且在第一帧图像的时候开始追踪。

  1. labels.append(label)
  2. trackers.append(t)

然后添加人的标签,并且添加多个追踪器,因为不仅仅一个目标。

  1. cv2.rectangle(frame, (startX, startY), (endX, endY),
  2. (0, 255, 0), 2)
  3. cv2.putText(frame, label, (startX, startY - 15),
  4. cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)

然后我们把框画出来,并且把标签贴上去。都是人的标签。

  1. else:
  2. for (t, l) in zip(trackers, labels):
  3. t.update(rgb)#更新追踪器
  4. pos = t.get_position()#获得位置
  5. # 得到位置
  6. startX = int(pos.left())
  7. startY = int(pos.top())
  8. endX = int(pos.right())
  9. endY = int(pos.bottom())

如果检测到框框了,那么就我们遍历一下追踪器和标签,然后更新追踪器,并且获得追踪器的位置。并且得到位置。

  1. if writer is not None:
  2. writer.write(frame)
  3. # 显示
  4. cv2.imshow("Frame", frame)
  5. key = cv2.waitKey(1) & 0xFF
  6. # 退出
  7. if key == 27:
  8. break
  9. # 计算FPS
  10. fps.update()
  11. fps.stop()
  12. print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
  13. print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
  14. if writer is not None:
  15. writer.release()
  16. cv2.destroyAllWindows()
  17. vs.release()

后面这些就是一些退出的一些简单的操作了。

FPS就是表示一秒钟可以处理17帧图片。运行时间是大概有20秒。然后我们想法就是继续进行一下改进,让处理的快一些。那么我们想到的就是使用多线程进行操作。多线程是指从软件或者硬件上实现多个线程并发执行的技术。

然后我们使用多线程进行改进程序:这里主函数就是要加上多线程。

  1. if __name__ == '__main__':
  2. while True:
  3. (grabbed, frame) = vs.read()
  4. if frame is None:
  5. break
  6. (h, w) = frame.shape[:2]
  7. width=600
  8. r = width / float(w)
  9. dim = (width, int(h * r))
  10. frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
  11. rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)#深度学习必要要处理的部分
  12. if args["output"] is not None and writer is None:
  13. fourcc = cv2.VideoWriter_fourcc(*"MJPG")
  14. writer = cv2.VideoWriter(args["output"], fourcc, 30,
  15. (frame.shape[1], frame.shape[0]), True)
  16. #首先检测位置
  17. if len(inputQueues) == 0:
  18. (h, w) = frame.shape[:2]
  19. blob = cv2.dnn.blobFromImage(frame, 0.007843, (w, h), 127.5)#图像的预处理操作 详情看笔记
  20. net.setInput(blob)
  21. detections = net.forward()#输出追踪 因为是多个 所以我们下方要进行过滤
  22. for i in np.arange(0, detections.shape[2]): #检测了多少个模型
  23. confidence = detections[0, 0, i, 2]#置信度 这里我们可以理解为每一个模型对应CLASS的概率 然后选出来一个最高的
  24. if confidence > args["confidence"]:
  25. idx = int(detections[0, 0, i, 1])#表示CLASS的类别序号
  26. label = CLASSES[idx]#选出来
  27. if CLASSES[idx] != "person":#过滤掉除了人以外所有的追踪目标
  28. continue
  29. box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])#这里标记处框架 这里表示按照长宽背书来定义
  30. (startX, startY, endX, endY) = box.astype("int")
  31. bb = (startX, startY, endX, endY)
  32. # 创建输入q和输出q
  33. iq = multiprocessing.Queue()#定义多进程
  34. oq = multiprocessing.Queue()
  35. inputQueues.append(iq)
  36. outputQueues.append(oq)
  37. # 多核
  38. p = multiprocessing.Process(#八所有追踪器放进进程当中,本电脑为812核会更快
  39. target=start_tracker,
  40. args=(bb, label, rgb, iq, oq))
  41. p.daemon = True
  42. p.start()
  43. cv2.rectangle(frame, (startX, startY), (endX, endY),
  44. (0, 255, 0), 2)
  45. cv2.putText(frame, label, (startX, startY - 15),
  46. cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)
  47. else:
  48. # 多个追踪器处理的都是相同输入
  49. for iq in inputQueues:
  50. iq.put(rgb)
  51. for oq in outputQueues:
  52. # 得到更新结果
  53. (label, (startX, startY, endX, endY)) = oq.get()
  54. # 绘图
  55. cv2.rectangle(frame, (startX, startY), (endX, endY),
  56. (0, 255, 0), 2)
  57. cv2.putText(frame, label, (startX, startY - 15),
  58. cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)
  59. if writer is not None:
  60. writer.write(frame)
  61. cv2.imshow("Frame", frame)
  62. key = cv2.waitKey(1) & 0xFF
  63. if key == 27:
  64. break
  65. fps.update()
  66. fps.stop()
  67. print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
  68. print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
  69. if writer is not None:
  70. writer.release()
  71. cv2.destroyAllWindows()
  72. vs.release()

这里就是5个线程一起跑。一秒钟可以处理24帧图像,运行时间14秒。大大的改进整体的进程。

如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦!这就是给予我最大的支持!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/566857
推荐阅读
相关标签
  

闽ICP备14008679号