利用HOG+SVM实现行人检测

利用HOG+SVM实现行人检测

很久以前做的行人检测,现在稍加温习,上传记录一下。

首先解析视频,提取视频的每一帧形成图片存到磁盘。代码如下

import os

import cv2

videos_src_path = 'D:\\test1'
videos_save_path = 'D:\\test2'

videos = os.listdir(videos_src_path)
videos = filter(lambda x: x.endswith('avi'), videos)

for each_video in videos:
    print (each_video)

    # get the name of each video, and make the directory to save frames
    each_video_name, _ = each_video.split('.')
    os.mkdir(videos_save_path + '/' + each_video_name)               

    each_video_save_full_path = os.path.join(videos_save_path, each_video_name) + '/'

    # get the full path of each video, which will open the video tp extract frames
    each_video_full_path = os.path.join(videos_src_path, each_video)

    cap  = cv2.VideoCapture(each_video_full_path)
    frame_count = 1
    success = True
    while(success):
        success, frame = cap.read()
        print ('Read a new frame: ', success)

        params = []
        params.append(1)
        params.append(1)
        cv2.imwrite(each_video_save_full_path + each_video_name + "_%05d.ppm" % frame_count, frame, params)

        frame_count = frame_count + 1

cap.release()

对于图片的行人检测应用了梯度方向直方图和支持向量机。代码如下
这段代码可以实现对行人的标记。

# import the necessary packages
from __future__ import print_function
from imutils.object_detection import non_max_suppression
from imutils import paths
import numpy as np
import argparse
import imutils
import cv2
import os

# initialize the HOG descriptor/person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())



list = []
path = 'D:\\test2\\111'

videos = os.listdir(path)
videos = filter(lambda x: x.endswith('ppm'), videos)
for each in videos:
    new_path=path + "\\" + each
    list.append(new_path)




# loop over the image paths
for imagePath in list:
    # load the image and resize it to (1) reduce detection time
    # and (2) improve detection accuracy
    image = cv2.imread(imagePath)
    image = imutils.resize(image, width=min(400, image.shape[1]))
    orig = image.copy()

    # detect people in the image
    (rects, weights) = hog.detectMultiScale(image, winStride=(4, 4),
        padding=(8, 8), scale=1.05)

    # draw the original bounding boxes
    for (x, y, w, h) in rects:
        cv2.rectangle(orig, (x, y), (x + w, y + h), (0, 0, 255), 2)

    # apply non-maxima suppression to the bounding boxes using a
    # fairly large overlap threshold to try to maintain overlapping
    # boxes that are still people
    rects = np.array([[x, y, x + w, y + h] for (x, y, w, h) in rects])
    pick = non_max_suppression(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(1)
    

在这里应用了非极大值抑制方法(NMS),处理了重叠标记的问题。但是这里存在一个问题就是,部分两个人物距离过近或者产生重叠的情况下,优化后会将两个人标记称为一个人,这个问题还没有解决。

最后,将多张标记后的图片按一定帧数还原成视频,就完成了对视频的行人检测。 完整代码如下

# import the necessary packages
from __future__ import print_function
from imutils.object_detection import non_max_suppression
from imutils import paths
import numpy as np
import argparse
import imutils
import cv2
import os
'''
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", required=True, help="path to images directory")
args = vars(ap.parse_args())
'''
# initialize the HOG descriptor/person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())



list = []
path = 'D:\\test2\\111'

videos = os.listdir(path)
videos = filter(lambda x: x.endswith('ppm'), videos)
for each in videos:
    new_path=path + "\\" + each
    list.append(new_path)

fourcc = cv2.VideoWriter_fourcc(*'I420')
videoWriter = cv2.VideoWriter('D:\\test2\\111\\saveVideo.avi',-1,24,(720,404))


# loop over the image paths
for imagePath in list:
    # load the image and resize it to (1) reduce detection time
    # and (2) improve detection accuracy
    image = cv2.imread(imagePath)
    if image is None:
        break
    image = imutils.resize(image, width=min(400, image.shape[1]))
    orig = image.copy()

    # detect people in the image
    (rects, weights) = hog.detectMultiScale(image, winStride=(4, 4),
        padding=(8, 8), scale=1.05)

    # draw the original bounding boxes
    for (x, y, w, h) in rects:
        cv2.rectangle(orig, (x, y), (x + w, y + h), (0, 0, 255), 2)

    # apply non-maxima suppression to the bounding boxes using a
    # fairly large overlap threshold to try to maintain overlapping
    # boxes that are still people
    rects = np.array([[x, y, x + w, y + h] for (x, y, w, h) in rects])
    pick = non_max_suppression(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)
    videoWriter.write(image)
    cv2.waitKey(1)
videoWriter.release()

运行截图如下
image
image

优化:预处理部分图像结果存在的磁盘上,导致运行速度偏难,可以先加载到内存中,以便加速。
关于视频,没有进行上下文处理,只是单纯的将图片合成视频,没有相互关联起来。

posted @ 2018-11-24 21:09  magicalzh  阅读(6036)  评论(0编辑  收藏  举报