在我們介紹目標物體檢測算法時,前期小編的文章也分享了很多目標檢測算法,比如YOLO, Faster RCNN等,喜歡目標檢測的小伙伴們可以參考往期的文章學習,本期的文章代碼也 在往期文章中有較多的介紹。前幾天剛聽說YOLO V4的出現打破了YOLO系列作者不更新目標檢測算法的新聞,突然又聽說YOLO V5已經出現,且檢測速度與精度有了較大的提高。不得不說現在的節奏太快,一不留神,我們就錯過了很多。目標檢測算法YOLO V3算是當今最受大家喜歡,且檢測速度與精度都有很大的優勢,這里我們利用YOLO V3目標檢測算法來進行人物的檢測,并計算人與人之間的距離
目標檢測
首先我們建立一個目標檢測函數來檢測人物
from scipy.spatial import distance as dist
import numpy as np
import cv2
import os
def detect_people(frame, net, ln, personIdx=0):
(H, W) = frame.shape[:2]
results = []
blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
layerOutputs = net.forward(ln)
boxes = []
centroids = []
confidences = []
from scipy.spatial import distance as dist歐拉距離,主要用于質心之間的距離計算
detect_people(frame, net, ln, personIdx=0)這里接受四個參數
frame:從視頻幀中提取的圖片幀,用于后期的目標檢測
net:基于yolo v3的目標檢測算法的神經網絡
ln:我們提取yolo v3輸出層的神經網絡,用于神經網絡的前向傳播的輸入層,便于進行目標檢測
personIdx:神經網絡檢測到人的目標的索引
(H, W) = frame.shape[:2]:獲取視頻幀圖片的尺寸
blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
layerOutputs = net.forward(ln)
此三行代碼便是yolo v3目標檢測算法的核心代碼了,我們計算圖片的blob值
放入神經網絡進行預測,并把輸出層進行反向傳播進行目標的預測
for output in layerOutputs:
for detection in output:
scores = detection[5:]
classID = np.argmax(scores)
confidence = scores[classID]
if classID == personIdx and confidence > 0.5:
box = detection[0:4] * np.array([W, H, W, H])
(centerX, centerY, width, height) = box.astype("int")
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
boxes.Append([x, y, int(width), int(height)])
centroids.append((centerX, centerY))
confidences.append(float(confidence))
神經網絡檢測完成后,所有檢測結果放置在layerOutputs里面
通過for循環遍歷出每個目標的置信度,我們只提取目標為人且置信度大于0.5的目標,其它目標直接忽略
box = detection[0:4] * np.array([W, H, W, H])
(centerX, centerY, width, height) = box.astype("int")
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
當檢測到我們需要的目標時,我們記錄其目標的中心(質心)坐標值以及目標box,并保存
idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.3, 0.3)
if len(idxs) > 0:
for i in idxs.flatten():
(x, y) = (boxes[i][0], boxes[i][1])
(w, h) = (boxes[i][2], boxes[i][3])
r = (confidences[i], (x, y, x + w, y + h), centroids[i])
results.append(r)
return results
由于人在移動過程中,很容易拍到的圖片2個人有重合的區域,這里使用非極大值抑制(NMS)算法,進行目標的低置信度的篩選
最后,我們把檢測到的目標box,目標質心坐標,以及置信度保存到results中便于后期的運算
初始化神經網絡
labelsPath = os.path.sep.join(["yolo-coco", "coco.names"])
LABELS = open(labelsPath).read().strip().split("n")
weightsPath = os.path.sep.join(["yolo-coco", "yolov3.weights"])
configPath = os.path.sep.join(["yolo-coco", "yolov3.cfg"])
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
vs = cv2.VideoCapture("123.mp4")
#vs=cv2.VideoCapture(0)打開攝像頭
目標檢測函數完成后,需要初始化神經網絡,這里直接使用opencv的dnn.readNetFromDarknet來加載yolo v3模型
ln = [ln[i[0] - 1] for i in
net.getUnconnectedOutLayers()]來提取神經網絡的輸出層,為什么這里需要提取輸出層,小伙伴們可以參考往期文章
這里為了演示,直接打開一段視頻來進行神經網絡的檢測
進行目標檢測,并計算目標距離
while True:
# read the next frame from the file
(grabbed, frame) = vs.read()
# if the frame was not grabbed, then we have reached the end
# of the stream
if not grabbed:
break
# resize the frame and then detect people (and only people) in it
frame = imutils.resize(frame, width=700)
results = detect_people(frame, net, ln,personIdx=LABELS.index("person"))
# initialize the set of indexes that violate the minimum social
# distance
violate = set()
# ensure there are *at least* two people detections (required in
# order to compute our pairwise distance maps)
if len(results) >= 2:
# extract all centroids from the results and compute the
# Euclidean distances between all pairs of the centroids
centroids = np.array([r[2] for r in results])
D = dist.cdist(centroids, centroids, metric="euclidean")
# loop over the upper triangular of the distance matrix
for i in range(0, D.shape[0]):
for j in range(i + 1, D.shape[1]):
# check to see if the distance between any two
if D[i, j] < 50:
violate.add(i)
violate.add(j)
for (i, (prob, bbox, ce
(cX, cY) = centroid
color = (0, 255, 0)
if i in violate:
color = (0, 0, 255)
cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)
cv2.circle(frame, (cX, cY), 5, color, 1)
text = " Distancing: {}".format(len(violate))
cv2.putText(frame, text, (10, frame.shape[0] - 25),
cv2.FONT_HERSHEY_SIMPLEX, 0.85, (0, 0, 255), 3)
if 1 > 0:
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
cv2.stop()
cv2.destroyAllwindows()
當打開視頻后,實時提取視頻幀中的圖片,并resize圖片,這里為了進行更快的目標檢測
results = detect_people(frame, net, ln,personIdx=LABELS.index("person"))使用前面的目標檢測函數進行人物的目標檢測
當獲取了目標信息后,我們要確保視頻幀中要多于2個人的存在,因為這樣距離計算才有意義
centroids = np.array([r[2] for r in results])
D = dist.cdist(centroids, centroids, metric="euclidean")
當檢測到目標后,我們提取所有目標的質心,并計算每個質心之間的歐拉距離
for i in range(0, D.shape[0]):
for j in range(i + 1, D.shape[1]):
if D[i, j] < 50:
violate.add(i)
violate.add(j)
通過for循環來判斷是否存在質心距離小于設置值的質心,并記錄質心的索引
for (i, (prob, bbox, centroid)) in enumerate(results):
(startX, startY, endX, endY) = bbox
(cX, cY) = centroid
color = (0, 255, 0)
if i in violate:
color = (0, 0, 255)
為了便于區分,當2個質心的間距小于設置值時,我們更改為紅色顏色框,相反,其他的設置為綠色框
最后,實時把數據以及box顯示在視頻中
說在最后
本期主要使用yolo v3來實時進行圖片幀的人物檢測,并計算質心的距離,這樣的方式導致了大量計算都是在神經網絡的目標檢測上,因為每幀視頻都要進行一次目標的檢測與質心的運算
當然你的電腦配置夠好的話,可以參考這樣的設計
我們這里提供另外一個方式,就是質心追蹤與質心運算,感興趣的小伙伴可以參考小編的專欄
《打造屬于自己的天眼目標追蹤系統》
本專欄詳細介紹了目標的質心追蹤與目標的質心距離運算,以及其他更多的目標追蹤技術,由于我們采用目標質心追蹤算法,不在用大量的資源來進行神經網絡的檢測,更好更快的來達到了我們的目的
通過質心的目標追蹤算法來搭配質心距離的計算,能夠更好的運行本期的代碼

專欄
作者:人工智能研究所






