Python+OpenCV內(nèi)置方法實(shí)現(xiàn)行人檢測(cè)
您是否知道 OpenCV 具有執(zhí)行行人檢測(cè)的內(nèi)置方法?
OpenCV 附帶一個(gè)預(yù)訓(xùn)練的 HOG + 線性 SVM 模型,可用于在圖像和視頻流中執(zhí)行行人檢測(cè)。
今天我們使用Opencv自帶的模型實(shí)現(xiàn)對(duì)視頻流中的行人檢測(cè),只需打開(kāi)一個(gè)新文件,將其命名為 detect.py ,然后加入代碼:
# import the necessary packages from __future__ import print_function import numpy as np import argparse import cv2 import os
導(dǎo)入需要的包,然后定義項(xiàng)目需要的方法。
def nms(boxes, probs=None, overlapThresh=0.3):
# if there are no boxes, return an empty list
if len(boxes) == 0:
return []
# if the bounding boxes are integers, convert them to floats -- this
# is important since we'll be doing a bunch of divisions
if boxes.dtype.kind == "i":
boxes = boxes.astype("float")
# initialize the list of picked indexes
pick = []
# grab the coordinates of the bounding boxes
x1 = boxes[:, 0]
y1 = boxes[:, 1]
x2 = boxes[:, 2]
y2 = boxes[:, 3]
# compute the area of the bounding boxes and grab the indexes to sort
# (in the case that no probabilities are provided, simply sort on the
# bottom-left y-coordinate)
area = (x2 - x1 + 1) * (y2 - y1 + 1)
idxs = y2
# if probabilities are provided, sort on them instead
if probs is not None:
idxs = probs
# sort the indexes
idxs = np.argsort(idxs)
# keep looping while some indexes still remain in the indexes list
while len(idxs) > 0:
# grab the last index in the indexes list and add the index value
# to the list of picked indexes
last = len(idxs) - 1
i = idxs[last]
pick.append(i)
# find the largest (x, y) coordinates for the start of the bounding
# box and the smallest (x, y) coordinates for the end of the bounding
# box
xx1 = np.maximum(x1[i], x1[idxs[:last]])
yy1 = np.maximum(y1[i], y1[idxs[:last]])
xx2 = np.minimum(x2[i], x2[idxs[:last]])
yy2 = np.minimum(y2[i], y2[idxs[:last]])
# compute the width and height of the bounding box
w = np.maximum(0, xx2 - xx1 + 1)
h = np.maximum(0, yy2 - yy1 + 1)
# compute the ratio of overlap
overlap = (w * h) / area[idxs[:last]]
# delete all indexes from the index list that have overlap greater
# than the provided overlap threshold
idxs = np.delete(idxs, np.concatenate(([last],
np.where(overlap > overlapThresh)[0])))
# return only the bounding boxes that were picked
return boxes[pick].astype("int")
image_types = (".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff")
def list_images(basePath, contains=None):
# return the set of files that are valid
return list_files(basePath, validExts=image_types, contains=contains)
def list_files(basePath, validExts=None, contains=None):
# loop over the directory structure
for (rootDir, dirNames, filenames) in os.walk(basePath):
# loop over the filenames in the current directory
for filename in filenames:
# if the contains string is not none and the filename does not contain
# the supplied string, then ignore the file
if contains is not None and filename.find(contains) == -1:
continue
# determine the file extension of the current file
ext = filename[filename.rfind("."):].lower()
# check to see if the file is an image and should be processed
if validExts is None or ext.endswith(validExts):
# construct the path to the image and yield it
imagePath = os.path.join(rootDir, filename)
yield imagePath
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
# 如果高和寬為None則直接返回
if width is None and height is None:
return image
# 檢查寬是否是None
if width is None:
# 計(jì)算高度的比例并并按照比例計(jì)算寬度
r = height / float(h)
dim = (int(w * r), height)
# 高為None
else:
# 計(jì)算寬度比例,并計(jì)算高度
r = width / float(w)
dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation=inter)
# return the resized image
return resized
nms函數(shù):非極大值抑制。
list_images:讀取圖片。
resize:等比例改變大小。
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", default='test1', help="path to images directory")
args = vars(ap.parse_args())
# 初始化 HOG 描述符/人物檢測(cè)器
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
定義輸入圖片的文件夾路徑。
初始化HOG檢測(cè)器。
# loop over the image paths
for imagePath in list_images(args["images"]):
# 加載圖像并調(diào)整其大小以
# (1)減少檢測(cè)時(shí)間
# (2)提高檢測(cè)精度
image = cv2.imread(imagePath)
image = resize(image, width=min(400, image.shape[1]))
orig = image.copy()
print(image)
# detect people in the image
(rects, weights) = hog.detectMultiScale(image, winStride=(4, 4),
padding=(8, 8), scale=1.05)
# draw the original bounding boxes
print(rects)
for (x, y, w, h) in rects:
cv2.rectangle(orig, (x, y), (x + w, y + h), (0, 0, 255), 2)
# 使用相當(dāng)大的重疊閾值對(duì)邊界框應(yīng)用非極大值抑制,以嘗試保持仍然是人的重疊框
rects = np.array([[x, y, x + w, y + h] for (x, y, w, h) in rects])
pick = nms(rects, probs=None, overlapThresh=0.65)
# draw the final bounding boxes
for (xA, yA, xB, yB) in pick:
cv2.rectangle(image, (xA, yA), (xB, yB), (0, 255, 0), 2)
# show some information on the number of bounding boxes
filename = imagePath[imagePath.rfind("/") + 1:]
print("[INFO] {}: {} original boxes, {} after suppression".format(
filename, len(rects), len(pick)))
# show the output images
cv2.imshow("Before NMS", orig)
cv2.imshow("After NMS", image)
cv2.waitKey(0)
遍歷 --images 目錄中的圖像。
然后,將圖像調(diào)整為最大寬度為 400 像素。嘗試減少圖像尺寸的原因有兩個(gè):
- 減小圖像大小可確保需要評(píng)估圖像金字塔中的滑動(dòng)窗口更少(即從線性 SVM 中提取 HOG 特征,然后將其傳遞給線性 SVM),從而減少檢測(cè)時(shí)間(并提高整體檢測(cè)吞吐量)。
- 調(diào)整我們的圖像大小也提高了我們行人檢測(cè)的整體準(zhǔn)確性(即更少的誤報(bào))。
通過(guò)調(diào)用 hog 描述符的 detectMultiScale 方法,檢測(cè)圖像中的行人。 detectMultiScale 方法構(gòu)造了一個(gè)比例為1.05 的圖像金字塔,滑動(dòng)窗口步長(zhǎng)分別為x 和y 方向的(4, 4) 個(gè)像素。
滑動(dòng)窗口的大小固定為 64 x 128 像素,正如開(kāi)創(chuàng)性的 Dalal 和 Triggs 論文《用于人體檢測(cè)的定向梯度直方圖》所建議的那樣。 detectMultiScale 函數(shù)返回 rects 的 2 元組,或圖像中每個(gè)人的邊界框 (x, y) 坐標(biāo)和 weights ,SVM 為每次檢測(cè)返回的置信度值。
較大的尺度大小將評(píng)估圖像金字塔中的較少層,這可以使算法運(yùn)行得更快。然而,規(guī)模太大(即圖像金字塔中的層數(shù)較少)會(huì)導(dǎo)致行人無(wú)法被檢測(cè)到。同樣,過(guò)小的比例尺會(huì)顯著增加需要評(píng)估的圖像金字塔層的數(shù)量。這不僅會(huì)造成計(jì)算上的浪費(fèi),還會(huì)顯著增加行人檢測(cè)器檢測(cè)到的誤報(bào)數(shù)量。也就是說(shuō),在執(zhí)行行人檢測(cè)時(shí),比例是要調(diào)整的最重要的參數(shù)之一。我將在以后的博客文章中對(duì)每個(gè)參數(shù)進(jìn)行更徹底的審查以檢測(cè)到多尺度。
獲取初始邊界框并將它們繪制在圖像上。
但是,對(duì)于某些圖像,您會(huì)注意到每個(gè)人檢測(cè)到多個(gè)重疊的邊界框。
在這種情況下,我們有兩個(gè)選擇。我們可以檢測(cè)一個(gè)邊界框是否完全包含在另一個(gè)邊界框內(nèi)?;蛘呶覀兛梢詰?yīng)用非最大值抑制并抑制與重要閾值重疊的邊界框。
應(yīng)用非極大值抑制后,得到最終的邊界框,然后輸出圖像。
運(yùn)行結(jié)果:
nms前:

nms后:

結(jié)論:
相比現(xiàn)在的深度學(xué)習(xí)方法,機(jī)器學(xué)習(xí)的精度低了很多。?
到此這篇關(guān)于Python+OpenCV內(nèi)置方法實(shí)現(xiàn)行人檢測(cè)的文章就介紹到這了,更多相關(guān)Python OpenCV行人檢測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Django實(shí)現(xiàn)商城驗(yàn)證碼模塊的方法
本文主要涉及圖形驗(yàn)證碼的相關(guān)功能,主要包括,圖形驗(yàn)證碼獲取、驗(yàn)證碼文字存儲(chǔ)、驗(yàn)證碼生成等。需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06
python實(shí)現(xiàn)人民幣大寫(xiě)轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)人民幣大寫(xiě)轉(zhuǎn)換的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
python關(guān)于調(diào)用函數(shù)外的變量實(shí)例
今天小編就為大家分享一篇python關(guān)于調(diào)用函數(shù)外的變量實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
如何利用python創(chuàng)建、讀取和修改CSV數(shù)據(jù)文件
csv文件與txt文件類(lèi)似,區(qū)別點(diǎn)就是在csv文件中,字段間使用“,”或“|”隔開(kāi),達(dá)到類(lèi)似與表格的效果,下面這篇文章主要給大家介紹了關(guān)于如何利用python創(chuàng)建、讀取和修改CSV數(shù)據(jù)文件的相關(guān)資料,需要的朋友可以參考下2022-05-05
讓你的Python代碼實(shí)現(xiàn)類(lèi)型提示功能
今天小編就為大家分享一篇讓你的Python代碼實(shí)現(xiàn)類(lèi)型提示功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
在Python中居然可以定義兩個(gè)同名通參數(shù)的函數(shù)
今天小編就為大家分享一篇在Python中居然可以定義兩個(gè)同名通參數(shù)的函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01
pandas dataframe統(tǒng)計(jì)填充空值方式
這篇文章主要介紹了pandas dataframe統(tǒng)計(jì)填充空值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
Python函數(shù)isalnum用法示例小結(jié)
isalnum()函數(shù)是Python中的一個(gè)內(nèi)置函數(shù),用于判斷字符串是否只由數(shù)字和字母組成,其內(nèi)部實(shí)現(xiàn)原理比較簡(jiǎn)單,只需遍歷字符串中的每一個(gè)字符即可,這篇文章主要介紹了Python函數(shù)isalnum用法介紹,需要的朋友可以參考下2024-01-01

