代码参考+数据集来源:https://github.com/FrankMa123/-
注意使用的scikit-learn库的版本为0.22,高于该版本的scikit-learn库,代码会报出错误(joblib库无法正常使用)
本文:主要对原作者的代码进行注释,以便于理解HOG+SVM检测,并有利于将该模型应用到其他分类。
致敬原作者!!!
#包含人的图片数据集的路径
pos_im_path = '../data/images/pos_person'
#不包含人的图片数据集的路径
neg_im_path = '../data/images/neg_person'
min_wdw_sz = [68, 124]
step_size = [10, 10]
orientations = 9
#一个cell为6*6个像素点
pixels_per_cell = [6, 6]
#一个block包含2*2个cell
cells_per_block = [2, 2]
visualize = False
normalize = True
pos_feat_ph = '../data/features/pos'
neg_feat_ph = '../data/features/neg'
model_path = '../data/models/'
threshold = .3
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 20 14:04:30 2019
@author: maqianli
"""
from skimage.feature import hog
from skimage.io import imread
import joblib
import glob
import os
from config import *
def extract_features():
if not os.path.isdir(pos_feat_ph):
os.makedirs(pos_feat_ph)
if not os.path.isdir(neg_feat_ph):
os.makedirs(neg_feat_ph)
for im_path in glob.glob(os.path.join(pos_im_path, "*")):
#对每一张包含人的图片进行处理
im = imread(im_path, as_grey=True)
print(im.shape)
#求取hog特征
fd = hog(im, orientations=9, pixels_per_cell=[8,8], cells_per_block=[2,2],
visualise=False, transform_sqrt=True)
print(fd.shape)
#将得到的特征进行存储
fd_name = os.path.split(im_path)[1].split(".")[0] + ".feat"
fd_path = os.path.join(pos_feat_ph, fd_name)
joblib.dump(fd, fd_path)
for im_path in glob.glob(os.path.join(neg_im_path, "*")):
#对每一张不包含人的图片进行处理
im = imread(im_path, as_grey=True)
#求取hog特征
fd = hog(im, orientations=9, pixels_per_cell=[8,8], cells_per_block=[2,2],
visualise=False, transform_sqrt=True)
#将得到的特征进行存储
fd_name = os.path.split(im_path)[1].split(".")[0] + ".feat"
fd_path = os.path.join(neg_feat_ph, fd_name)
joblib.dump(fd, fd_path)
print('completed')
if __name__=='__main__':
extract_features()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 20 14:56:42 2019
@author: maqianli
"""
#以上信息为原作者信息
from sklearn.svm import LinearSVC
import joblib
import glob
import os
from config import *
import numpy as np
def train_svm():
#利用hog特征训练SVM
pos_feat_path = '../data/features/pos'
neg_feat_path = '../data/features/neg'
model_path = '../data/models/svm_model'
#分别存放特征和标签
fds, labels = [], []
#对得到的特征进行打标签,分别包含有人和无人的情况
for feat_path in glob.glob(os.path.join(pos_feat_path, "*.feat")):
fd = joblib.load(feat_path)
fds.append(fd)
labels.append(1)
for feat_path in glob.glob(os.path.join(neg_feat_path, "*.feat")):
fd = joblib.load(feat_path)
fds.append(fd)
labels.append(0)
#用线性SVM
clf = LinearSVC()
clf.fit(fds, labels)
if not os.path.isdir(os.path.split(model_path)[0]):
os.makedirs(os.path.split(model_path)[0])
#print('Classifier save to {}'.format(model_path))
#将训练好的模型存储到model_path下
joblib.dump(clf, model_path)
print('Classifier save to {}'.format(model_path))
if __name__=='__main__':
train_svm()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 20 15:33:30 2019
@author: maqianli
"""
import numpy as np
from skimage.transform import pyramid_gaussian
from imutils.object_detection import non_max_suppression
import imutils
from skimage.feature import hog
import joblib
import cv2
from config import *
from skimage import color
import matplotlib.pyplot as plt
import os
import glob
model_path = '../data/models/svm_model'
#滑动窗口,即得到图片的一部分
def sliding_window(image, window_size, step_size):
for y in range(0, image.shape[0], step_size[1]):
for x in range(0, image.shape[1], step_size[0]):
yield x, y, image[y: y + window_size[1], x:x + window_size[0]]
def detector(filename):
im = cv2.imread(filename)
#对图片大小进行控制
im = imutils.resize(im, width=min(400, im.shape[1]))
#最小窗口大小
min_wdw_sz = (64, 128)
step_size = (10, 10)
#图像金字塔缩放倍数
downscale = 1.25
#导入训练好的SVM模型
clf = joblib.load(model_path)
#detections存放图片中的人物
detections = []
#scale为缩放的次数
scale = 0
#对图片进行缩放
for im_scaled in pyramid_gaussian(im, downscale=downscale):
#如果图片比我们规定的图片小,那么就结束,不进行下面的hog检测
if im_scaled.shape[0] < min_wdw_sz[1] or im_scaled.shape[1] < min_wdw_sz[0]:
break
#对滑动窗口进行hog特征检测
for (x, y, im_window) in sliding_window(im_scaled, min_wdw_sz, step_size):
if im_window.shape[0] != min_wdw_sz[1] or im_window.shape[1] != min_wdw_sz[0]:
continue
#将得到的图像进行灰度化
im_window = color.rgb2gray(im_window)
#hog特征检测
fd = hog(im_window, orientations=9, pixels_per_cell=[8, 8], cells_per_block=[2, 2],
transform_sqrt=True)
#将fd特征转换成向量,并调用训练好的模型进行预测
fd = fd.reshape(1, -1)
pred = clf.predict(fd)
#如果检测到图片中有人
if pred == 1:
if clf.decision_function(fd) > 0.5:
#保存 包含人的矩形
detections.append((int(x * (downscale ** scale)), int(y * (downscale ** scale)),
clf.decision_function(fd),
int(min_wdw_sz[0] * (downscale ** scale)),
int(min_wdw_sz[1] * (downscale ** scale))))
scale += 1
#克隆一遍原图,画出矩形,进行输出
clone = im.copy()
for (x_t1, y_t1, _, w, h) in detections:
cv2.rectangle(im, (x_t1, y_t1), (x_t1 + w, y_t1 + h), (0, 255, 0), thickness=2)
rects = np.array([[x, y, x + w, y + h] for (x, y, _, w, h) in detections])
sc = [score[0] for (x, y, score, w, h) in detections]
print("sc: ", sc)
sc = np.array(sc)
pick = non_max_suppression(rects, probs=sc, overlapThresh=0.3)
# print("shape, ",pick.shape)
for (xA, yA, xB, yB) in pick:
cv2.rectangle(clone, (xA, yA), (xB, yB), (0, 255, 0), 2)
plt.axis("off")
plt.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
plt.title('Raw Detection before NMS')
plt.show()
plt.axis("off")
plt.imshow(cv2.cvtColor(clone, cv2.COLOR_BGR2RGB))
plt.title("Final Detections after applying NMS")
plt.show()
def test_folder(foldername):
filenames = glob.iglob(os.path.join(foldername, '*'))
for filename in filenames:
#对foldername下的每一张图片进行detect
print(filename)
detector(filename)
if __name__ == '__main__':
#对test_image里面的图片进行预测
foldername = 'test_image'
test_folder(foldername)