传统目标检测方法研究(三)采用支持向量机实现行人检测

1.4 HOG特征+支持向量机实现行人检测

为了把前面知识串起来,参考书籍做了以下实验。

import cv2
import matplotlib.pyplot as plt
from matplotlib import patches
import numpy as np
import random
import os
from numpy.lib.shape_base import take_along_axis
from sklearn import model_selection as ms
from sklearn import metrics
random.seed(42)
# 可视化数据样本
for i in range(5):
    filename = "MIT/MIT_jpg/per0001%d.jpg"%(i)
    # print(filename)
    img = cv2.imread(filename)
    plt.subplot(1,5,i+1)
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.axis("off")
plt.savefig("pos_sample.png")
plt.show()

在这里插入图片描述

# 提取HOG特征
win_size = (64,128)
block_size = (16,16)
block_stride = (8,8)
cell_size = (8,8)
num_bins = 9
hog = cv2.HOGDescriptor(win_size,block_size,block_stride,
                            cell_size,num_bins)
X_pos = [] # 用于存储HOG特征以构建正样本数据集
# 从924张图像选出400张,提取出hog特征
for i in random.sample(range(900),400):
    filename = "MIT/MIT_jpg/per%05d.jpg"%(i)
    img = cv2.imread(filename)
    if img is None:
        print("Could not find image %s" % filename)
        continue
    X_pos.append(hog.compute(img,(8,8)))
X_pos = np.array(X_pos,dtype=np.float32)
y_pos = np.ones(X_pos.shape[0],dtype=np.int32)
print(y_pos)
print(X_pos.shape,y_pos.shape)
# 生成负样本数据集 使用的数据集是256*256的,为了和前面保持一致,需要切出64*128的图片
negdir = "pedestrians_neg/"
wroi = 64
hroi = 128
idx = 0
# 随机从负样本数据集选择5张图片可视化
for filename in random.sample(os.listdir(negdir),5):
    idx += 1
    img_path = negdir + filename
    img = cv2.imread(img_path)
    img = cv2.resize(img,(512,512)) 
    rand_y = random.randint(0,img.shape[0]-hroi)
    rand_x = random.randint(0,img.shape[1]-wroi)
    roi = img[rand_y:rand_y+hroi, rand_x:rand_x+wroi]   
    plt.subplot(1,5,idx)
    plt.imshow(cv2.cvtColor(roi,cv2.COLOR_BGR2RGB))
    plt.axis("off")
plt.savefig("neg_sample.png")
plt.show()

在这里插入图片描述

X_neg = [] # 用于存储HOG特征以构建负样本数据集
for negfile in os.listdir(negdir):
    filename = negdir + negfile
    # print(filename)
    img = cv2.imread(filename)
    img = cv2.resize(img,(512,512))
    # 随机选择左上角坐标,切分出64*128大小的区域
    for j in range(5):
        rand_y = random.randint(0,img.shape[0]-hroi)
        rand_x = random.randint(0,img.shape[1]-wroi)
        roi = img[rand_y:rand_y+hroi, rand_x:rand_x+wroi, : ]
        X_neg.append(hog.compute(roi,(8,8)))

X_neg = np.array(X_neg,dtype=np.float32)
y_neg = -np.ones(X_neg.shape[0],dtype=np.int32)
print(y_neg)
print(X_neg.shape, y_neg.shape)

# 合并数据集
X = np.concatenate((X_pos,X_neg))
y = np.concatenate((y_pos,y_neg))
print(X.shape, y.shape)

X_train, X_test, y_train, y_test = ms.train_test_split(X, y, 
                                                        test_size=0.2,random_state=42)

# 实现支持向量机
def train_svm(X_train,y_train) :
    svm = cv2.ml.SVM_create()
    svm.setKernel(cv2.ml.SVM_LINEAR)
    svm.train(X_train, cv2.ml.ROW_SAMPLE, y_train)
    return svm

svm1 = train_svm(X_train,y_train)

def score_svm(svm,X,y):
    _,y_pred = svm.predict(X)
    # print(y_pred)
    return metrics.accuracy_score(y,y_pred)

# 测试训练集和测试集的准确率
print("train_acc: ", score_svm(svm1, X_train, y_train))
print("test_acc: ", score_svm(svm1, X_test, y_test))

# 模型自举
'''
    将假正样本添加到训练集中重新训练SVM
'''
score_train = []
score_test = []
# 重复3次训练过程
for j in range(3):
    # 训练并评估模型
    svm2 = train_svm(X_train,y_train)
    svm2.save("SVM2.xml")
    score_train.append(score_svm(svm2,X_train,y_train))
    score_test.append(score_svm(svm2,X_test,y_test))
    # 从测试数据集中找到假正图片 ravel()和flatten()用法一样
    _,y_pred = svm2.predict(X_test)
    false_pos = np.logical_and((y_test.ravel()==-1),(y_pred.ravel()==1))
    if not np.any(false_pos):
        print("no more false positives: done")
        break
    # 把假正的图片加入到训练集中,然后重复训练过程
    X_train = np.concatenate((X_train,X_test[false_pos,:]), axis=0)
    y_train = np.concatenate((y_train,y_test[false_pos]), axis=0)

print("train acc: ",score_train)
print("test acc: ",score_test)

# 在更大的图像中检测行人
# '''
# 将图像分割成不同的块,对所有的块进行循环,检测是否包含行人
# '''
# 固定尺度检测
stride = 16
found = []
img_test = cv2.imread("testimg/3.jpg")
for ystart in np.arange(0,img_test.shape[0],stride):
    for xstart in np.arange(0,img_test.shape[1],stride):
        # 确保不超出图像边界
        if ystart + hroi > img_test.shape[0]:
            continue
        if xstart + wroi > img_test.shape[1]:
            continue
        # 提取感兴趣区域并进行分类
        roi = img_test[ystart:ystart + hroi, xstart:xstart + wroi, : ]
        feat = np.array([hog.compute(roi,(64,64))])
        _,ypred = svm2.predict(feat)
        print(ypred)
        # 如果是行人 把它加入到成功检测的列表中
        if np.allclose(ypred,1):
            found.append((ystart,xstart,hroi,wroi))
# 把检测到的人画出来
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(cv2.cvtColor(img_test,cv2.COLOR_BGR2RGB))
for f in found:
    ax.add_patch(patches.Rectangle((f[1],f[0]),f[3],f[2],color='r',linewidth=3,fill=False))
plt.savefig("result.png")
plt.show()

在这里插入图片描述

如果采用opencv多尺度方法进行预测以获得更好的效果,参考链接行人 检测

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开始学AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值