版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/weixin_44474718/article/details/87200512
datasets.make_classification([n_samples, ...])
: This functiondatasets.make_regression([n_samples, ...])
: This function generates adatasets.make_blobs([n_samples, n_features, ...])
: This functionsvm.setKernel(cv2.ml.SVM_LINEAR)
# 可以设置不同的模式(直线)操作np.c_
是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等。plt.contour
还是plt.contourf
,都是绘制三维图,其中前两个参数x和y为两个等长一维数组,第三个参数z为二维数组(表示平面点xi,yi映射的函数值)from sklearn import datasets
import matplotlib.pyplot as plt
import numpy as np
from sklearn import model_selection as ms
import cv2
from sklearn import metrics
# 数据集生成
x , y = datasets.make_classification(n_samples=100,n_features=2,n_redundant=0,n_classes=2,random_state=7816)
# 数据集可视化
plt.scatter(x[:,0],x[:,1],c=y, s=100) # 目标标签作为色彩值传入 c=y
plt.xlabel('x1 values')
plt.ylabel('x2 values')
plt.show()
# 数据预处理
x = x.astype(np.float32) # 使数据兼容OpenCv
y = y * 2 - 1
x_train , x_test , y_train , y_test = ms.train_test_split(x , y , test_size= 0.2, random_state=42)
# 构建支持向量机
svm = cv2.ml.SVM_create()
svm.setKernel(cv2.ml.SVM_LINEAR) # 可以设置不同的模式(直线)操作
svm.train(x_train, cv2.ml.ROW_SAMPLE, y_train) # 调用分类器的train方法来找到最优决策边界
_ , y_pred = svm.predict(x_test) # 调用分类器的predict方法来预测测试数据集中所有数据样本的目标标签
print(metrics.accuracy_score(y_test, y_pred))
# 决策边界可视化
def plot_decision_boundary (svm, x_test, y_test):
x_min, x_max = x_test[:,0].min()-1, x_test[:,0].max()+1 # 使得所有的点在方格子内
y_min, y_max = x_test[:,0].min()-1, x_test[:,0].max()+1
h = 0.02 # 取样步长
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),np.arange(y_min, y_max, h)) # 创建网格
# np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等。
# 把这些(xx,yy)坐标值当作假设的数据点。因此可以把它们叠成为一个Nx2的矩阵
x_hypo = np.c_[xx.ravel().astype(np.float32),yy.ravel().astype(np.float32)] #最终的数据为一个Nx2的矩阵
_, zz = svm.predict(x_hypo)
# 得到的结构目标标签zz将会被用来创建一个特征结构的颜色映射
zz = zz.reshape(xx.shape)
plt.contourf(xx, yy, zz, cmap=plt.cm.coolwarm, alpha=0.8) # 绘制三维图
plt.scatter(x_test[:,0],x_test[:,1], c=y_test,s=200)
plot_decision_boundary(svm, x_test, y_test)
plt.show()
cv2.ml.SVM_LINEAR:
提供一个线性的决策边界。cv2.ml.SVM_POLY:
这个核在原始特征空间提供一个多项式的函数作为决策边界,通过 svm.setCoef0
(通常为0) 指定一个系数,通过 svm.setDegree
.指定多项式的项数。cv2.ml.SVM_RBF:
高斯函数类型cv2.ml.SVM_SIGMOID:
sigmoid函数类型cv2.ml.SVM_INTER:
由 OpenCV 3 新提供的. 它根据类别的直方图的相似性来分类。# 创建不同的核函数
kernels = [cv2.ml.SVM_LINEAR, cv2.ml.SVM_INTER, cv2.ml.SVM_SIGMOID, cv2.ml.SVM_RBF]
kernels1 = ['LINEAR','INTER','SIGMOID','RBF']
for idx, kernel in enumerate(kernels):
svm = cv2.ml.SVM_create() # 创建SVM
svm.setKernel(kernel) # 设置核函数
svm.train(x_train, cv2.ml.ROW_SAMPLE, y_train) # 训练数据集
_1, y_pred1 = svm.predict(x_test) # 评分
accuracy1 = metrics.accuracy_score(y_test, y_pred1)
plt.subplot(2,2,idx + 1)
plot_decision_boundary(svm, x_test, y_test)
title1='% s : accuracy = %.2f' % (kernels1[idx], accuracy1) print(title1)
plt.title(title1)
plt.show()
cv2.HOGDescriptor
来设置,win_size
= (48, 96) ,检测窗口大小(检测对象的最小尺寸48 * 96)对HOG影响最大block_size
= (16, 16), 块的大小(每个块最大为16 * 16)block_stride
= (8, 8) , 单元格尺寸cell_size
= (8, 8), 单元格步长(从一个单元格移动8*8像素到另外一个单元格)num_bins
= 9 , 对于每一个单元格,统计9个方向的梯度直方图。import cv2
import matplotlib.pyplot as plt
import numpy as np
import random
import os
from sklearn import model_selection as ms
from sklearn import metrics
random.seed(42)
# 设置正负数据集所在的位置
datadir = "data-new/chapter6"
dataset = "pedestrians128x64"
datafile = "%s/%s.tar.gz" % (datadir, dataset)
extractdir = "%s/%s" % (datadir, dataset)
negset = "pedestrians_neg"
negfile = "%s/%s.tar.gz" % (datadir, negset)
negdir = "%s/%s" % (datadir, negset)
# 解压数据集
def extract_tar(datafile, extractdir): # 定义解压缩文件函数 datafile待解压的文件,
try:
import tarfile
except ImportError:
raise ImportError("You do not have tarfile installed. "
"Try unzipping the file outside of Python.")
tar = tarfile.open(datafile)
tar.extractall(path=extractdir)
tar.close()
print("%s successfully extracted to %s" % (datafile, extractdir))
extract_tar(datafile, datadir) # 解压正样本数据集至指定位置
extract_tar(negfile, datadir) # 解压负样本数据集至指定位置
for i in range(5):
filename = "%s/per0010%d.ppm" % (extractdir, i) # 读取文件中第100到104的5张图片
img = cv2.imread(filename)
plt.subplot(1,5,i+1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()
# 设置HOG描述符参数
win_size = (48, 96) # 检测窗口大小(检测对象的最小尺寸48 * 96)
block_size = (16, 16) #(每个块最大为16 * 16)
block_stride = (8, 8) # 单元格尺寸
cell_size = (8, 8) #(从一个单元格移动8*8像素到另外一个单元格)
num_bins = 9 # 对于每一个单元格,统计9个方向的梯度直方图。
hog = cv2.HOGDescriptor(win_size, block_size, block_stride, cell_size, num_bins) # 设置HOG描述符参数
# 构建正样本
x_pos = []
for i in random.sample(range(900), 400): # 在0到900张图片中随机挑选400张图片
filename = "%s/per%05d.ppm" % (extractdir, i)
img = cv2.imread(filename)
if img is None:
print('Could not find image %s' % filename)
continue
x_pos.append(hog.compute(img, (64, 64))) # 利用HOG进行计算
x_pos = np.array(x_pos, dtype=np.float32) # 数据类型转换,兼容OpenCv
y_pos = np.ones(x_pos.shape[0], dtype=np.int32) # 将训练样本赋值给y_pos
print (x_pos.shape, y_pos.shape) # (399, 1980, 1) (399,) 399个训练样本,1980特征值
# 构建负样本 图像尺寸与正样本一样
hroi = 128
wroi = 64
x_neg = []
for negfile in os.listdir(negdir):
filename = '%s/%s' % (negdir, negfile)
img = cv2.imread(filename)
img = cv2.resize(img, (512, 512))
for j in range(5):
rand_y = random.randint(0, img.shape[0] - hroi) # uniform:随机浮点数 randint:随机整数 randrange:随机偶数
rand_x = random.randint(0, img.shape[1] - wroi)
roi = img[rand_y:rand_y + hroi, rand_x:rand_x + wroi, :] # 随机选择左上角的坐标来切出一个64*128像素的感兴趣区域
x_neg.append(hog.compute(roi, (64, 64))) # 利用HOG进行计算
x_neg = np.array(x_neg, dtype=np.float32) # 数据类型转换,兼容OpenCv
y_neg = -np.ones(x_neg.shape[0], dtype=np.int32) # 将训练样本赋值给y_neg
print(x_neg.shape, y_neg.shape) # (250, 1980, 1) (250,) 250个训练样本,1980特征值
# 将X 和Y (正样本和负样本)合并
x = np.concatenate((x_pos, x_neg))
y = np.concatenate((y_pos, y_neg))
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.train(X_train, cv2.ml.ROW_SAMPLE, y_train)
return svm
def score_svm(svm, X, y): # 把评分过程封装为一个函数
_, y_pred = svm.predict(X)
return metrics.accuracy_score(y, y_pred)
svm = train_svm(x_train, y_train) # 训练
print('训练集分数:%.5f ,测试集分数:%.5f' % (score_svm(svm, x_train, y_train),score_svm(svm, x_test, y_test))) # 在训练集上的评分
# 模型自举
score_train = []
score_test = []
for i in range(3):
svm = train_svm(x_train, y_train) # 训练评估模型
score_train.append(score_svm(svm, x_train, y_train))
score_test.append(score_svm(svm, x_test, y_test))
_, y_pred = svm.predict(x_test) # 从测试数据集中找到假正的图片,如果没有,就完成了训练
false_pos = np.logical_and((y_test.ravel() == -1), (y_pred.ravel() == 1)) # 都为真,即存在假正 false_pos为布尔值
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('训练集分数:%s ,测试集分数:%s' % (score_train,score_test))
detectMultiScale
# 行人可能出现在不同的图像中的区域,且大小不一样需要对图像进行缩放
hog = cv2.HOGDescriptor(win_size, block_size, block_stride, cell_size, num_bins)
rho, _, _ = svm.getDecisionFunction(0) # 返回决策函数的参数,从核响应的加权和减去的一个标量
sv = svm.getSupportVectors() # 以浮点矩阵的形式返回所有的支持向量
hog.setSVMDetector(np.append(sv[0, :].ravel(), rho)) # 为线性分类器设置系数
"""
# 使用默认的SVM分类
hogdef = cv2.HOGDescriptor() # 设置HOG默认参数
hogdef.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 用于人员检测的分类器(64x128窗口)的简短返回系数
"""
found, _ = hog.detectMultiScale(img_test) # 调用检测函数 ,返回检测到行人的框的列表
fig = plt.figure(figsize=(10, 6)) # 画出测试图像
ax = fig.add_subplot(111)
ax.imshow(cv2.cvtColor(img_test, cv2.COLOR_BGR2RGB))
for f in found: # 标记图像中检测到的行人
ax.add_patch(patches.Rectangle((f[0], f[1]), f[2], f[3], color='y', linewidth=3, fill=False))
plt.savefig('detected.png')
plt.show()
import cv2
import matplotlib.pyplot as plt
import numpy as np
import random
import os
from sklearn import model_selection as ms
from sklearn import metrics
from matplotlib import patches
random.seed(42)
# 设置正负数据集所在的位置
datadir = "data-new/chapter6"
dataset = "pedestrians128x64"
datafile = "%s/%s.tar.gz" % (datadir, dataset)
extractdir = "%s/%s" % (datadir, dataset)
negset = "pedestrians_neg"
negfile = "%s/%s.tar.gz" % (datadir, negset)
negdir = "%s/%s" % (datadir, negset)
# 解压数据集
def extract_tar(datafile, extractdir): # 定义解压缩文件函数 datafile待解压的文件,
try:
import tarfile
except ImportError:
raise ImportError("You do not have tarfile installed. "
"Try unzipping the file outside of Python.")
tar = tarfile.open(datafile)
tar.extractall(path=extractdir)
tar.close()
print("%s successfully extracted to %s" % (datafile, extractdir))
extract_tar(datafile, datadir) # 解压正样本数据集至指定位置
extract_tar(negfile, datadir) # 解压负样本数据集至指定位置
for i in range(5):
filename = "%s/per0010%d.ppm" % (extractdir, i) # 读取文件中第100到104的5张图片
img = cv2.imread(filename)
plt.subplot(1,5,i+1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()
# 设置HOG描述符参数
win_size = (48, 96) # 检测窗口大小(检测对象的最小尺寸48 * 96)
block_size = (16, 16) #(每个块最大为16 * 16)
block_stride = (8, 8) # 单元格尺寸
cell_size = (8, 8) #(从一个单元格移动8*8像素到另外一个单元格)
num_bins = 9 # 对于每一个单元格,统计9个方向的梯度直方图。
hog = cv2.HOGDescriptor(win_size, block_size, block_stride, cell_size, num_bins) # 设置HOG描述符参数
# 构建正样本
x_pos = []
for i in random.sample(range(900), 400): # 在0到900张图片中随机挑选400张图片
filename = "%s/per%05d.ppm" % (extractdir, i)
img = cv2.imread(filename)
if img is None:
print('Could not find image %s' % filename)
continue
x_pos.append(hog.compute(img, (64, 64))) # 利用HOG进行计算
x_pos = np.array(x_pos, dtype=np.float32) # 数据类型转换,兼容OpenCv
y_pos = np.ones(x_pos.shape[0], dtype=np.int32) # 将训练样本赋值为1给y_pos
print (x_pos.shape, y_pos.shape) # (399, 1980, 1) (399,) 399个训练样本,1980特征值
# 构建负样本 图像尺寸与正样本一样
hroi = 128
wroi = 64
x_neg = []
for negfile in os.listdir(negdir):
filename = '%s/%s' % (negdir, negfile)
img = cv2.imread(filename)
img = cv2.resize(img, (512, 512))
for j in range(5):
rand_y = random.randint(0, img.shape[0] - hroi) # uniform:随机浮点数 randint:随机整数 randrange:随机偶数
rand_x = random.randint(0, img.shape[1] - wroi)
roi = img[rand_y:rand_y + hroi, rand_x:rand_x + wroi, :] # 随机选择左上角的坐标来切出一个64*128像素的感兴趣区域
x_neg.append(hog.compute(roi, (64, 64))) # 利用HOG进行计算
x_neg = np.array(x_neg, dtype=np.float32) # 数据类型转换,兼容OpenCv
y_neg = -np.ones(x_neg.shape[0], dtype=np.int32) # 将训练样本赋值给y_neg np.ones 填充1
print(x_neg.shape, y_neg.shape) # (250, 1980, 1) (250,) 250个训练样本,1980特征值
# 将X 和Y (正样本和负样本)合并
x = np.concatenate((x_pos, x_neg))
y = np.concatenate((y_pos, y_neg))
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.train(X_train, cv2.ml.ROW_SAMPLE, y_train)
return svm
def score_svm(svm, X, y): # 把评分过程封装为一个函数
_, y_pred = svm.predict(X)
return metrics.accuracy_score(y, y_pred)
svm = train_svm(x_train, y_train) # 训练
print('训练集分数:%.5f ,测试集分数:%.5f' % (score_svm(svm, x_train, y_train),score_svm(svm, x_test, y_test))) # 在训练集上的评分
# 模型自举
score_train = []
score_test = []
for i in range(3):
svm = train_svm(x_train, y_train) # 训练评估模型
score_train.append(score_svm(svm, x_train, y_train))
score_test.append(score_svm(svm, x_test, y_test))
_, y_pred = svm.predict(x_test) # 从测试数据集中找到假正的图片,如果没有,就完成了训练
false_pos = np.logical_and((y_test.ravel() == -1), (y_pred.ravel() == 1)) # 都为真,即存在假正 false_pos为布尔值
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('训练集分数:%s ,测试集分数:%s' % (score_train,score_test))
# 在更大的图像中检测行人
img_test = cv2.imread('data-new/chapter6/pedestrian_test.jpg')
stride = 16 # 设置需要移动的像素点
found = [] # 检测列表
for ystart in np.arange(0, img_test.shape[0], stride):
for xstart in np.arange(0, img_test.shape[1], stride): # 每次将感兴趣的区域移动一个小的stride像素点
if ystart + hroi > img_test.shape[0]: # 确保不会超过图像的边界
continue
if xstart + wroi > img_test.shape[1]: #当xstart + wroi > img_test.shape[1]时,结束当前循环进入下一个循环
continue
roi = img_test[ystart:ystart + hroi, xstart:xstart + wroi, :] # 切下来roi区域预处理并且分类
feat = np.array([hog.compute(roi, (64, 64))])
_2, ypred = svm.predict(feat)
if np.allclose(ypred, 1): # 如果检测到是行人则添加至列表
found.append((ystart, xstart, hroi, wroi))
# 行人可能出现在不同的图像中的区域,且大小不一样需要对图像进行缩放
hog = cv2.HOGDescriptor(win_size, block_size, block_stride, cell_size, num_bins)
rho, _, _ = svm.getDecisionFunction(0) # 返回决策函数的参数,从核响应的加权和减去的一个标量
sv = svm.getSupportVectors() # 以浮点矩阵的形式返回所有的支持向量
hog.setSVMDetector(np.append(sv[0, :].ravel(), rho)) # 为线性分类器设置系数
"""
# 使用默认的SVM分类
hogdef = cv2.HOGDescriptor() # 设置HOG默认参数
hogdef.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 用于人员检测的分类器(64x128窗口)的简短返回系数
"""
found, _ = hog.detectMultiScale(img_test) # 调用检测函数 ,返回检测到行人的框的列表
fig = plt.figure(figsize=(10, 6)) # 画出测试图像
ax = fig.add_subplot(111)
ax.imshow(cv2.cvtColor(img_test, cv2.COLOR_BGR2RGB))
for f in found: # 标记图像中检测到的行人
ax.add_patch(patches.Rectangle((f[0], f[1]), f[2], f[3], color='y', linewidth=3, fill=False))
plt.savefig('detected.png')
plt.show()