文章目录[隐藏]
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多尺度方法进行预测以获得更好的效果,参考链接行人 检测
版权声明:本文为CSDN博主「开始学AI」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41964545/article/details/121246116
暂无评论