赞
踩
Scikit-image
中的模块对数据集进行训练和分类
但是光靠这些方法还不足以实现一个目标检测项目。
计算机视觉中的图像分类:
例如:下面公式表示我们定义了一个集合 D D D, c a t cat cat 、 d o g dog dog 则被称为集合 D D D 的 2 个不同标签。
D = { c a t , d o g } D = \{cat,\ dog\} D={cat, dog}
以下图为例,图像分类任务就是:
在计算机视觉中我们希望构建一个系统:
更具体的来说:
要想通过机器学习或深度学习实现图像分类
数据集:
我们希望机器学习或深度学习算法
故机器学习和深度学习是数据驱动的方法:
为了构建一个图像分类模型,我们首先需要收集不同的图片创建一个数据集
还有一点需要注意的是:我们在创建数据集时要尽量让每种类别的图片数量相差不太大
收集好数据集后通常我们会将其分为三份:
训练集、验证集、测试集。
有了数据集并且划分了训练集和测试集,我们就可以训练自己的模型了。
首先我们需要一个评分函数(Score Function)将输入图片映射到类别标签。
然后一个损失函数(Loss Function)将会被用于评估输出的结果与该数据所对应的真实标签的近似程度
完成训练后我们用测试集评估获得的模型
下面我们将使用 Scikit-learn
工具教会大家使用线性分类器:
我们将使用学习过的方向梯度直方图
首先我们先了解下我们将使用的数据集
people
和 background
两个子文件夹
这个文件夹内各包含两千多张图片
people
文件夹内都是人的图片backgorund
内都是一些背景图片我们将使用这个数据集训练一个用于分辨人和背景的分类模型
首先我们将创建一个用于处理数据集路径的函数。
在模型训练阶段,我们将从这两个列表中读取数据集中的图片和其对应的标签。
from os import listdir
from os.path import join
上面的代码表示从 os
、os.path
中导入需要的功能模块。
接着我们创建一个 preprocessing
函数
datasetpath
,这个参数是数据集的路径。def preprocessing(datasetpath):
dataset = []
labels = []
categories = [join(datasetpath, i) for i in listdir(datasetpath)]
for i in categories:
dataset.extend([join(i, f) for f in listdir(i)])
labels = [i.split("/")[1] for i in dataset]
return (dataset, labels)
然后我们创建两个列表 dataset
、labels
。
dataset
用于存放每张图片的路径labels
用于存放每张图片对应的标签。
在代码中:
categories
中存储数据集下的每个子文件夹的路径。listdir
方法获取 datasetpath
下每个子文件夹名称join
方法将 datasetpath
的路径和每个子文件夹的名称拼接获取子文件夹的路径。"pedestrian"
作为函数的输入值,则 categories
的值为:["pedestrian/people", "pedestrian/background"]
。
接着我们用一个 for
循环将每张图片的路径保存在 dataset
中。
listdir
获取每个子文件夹下所有图片的名称join
方法将子文件夹的路径和它里面的图片名称拼接extend
方法将每张图片的路径存储到 dataset
中。在代码中,我们使用列表解析获取每张图片的标签 labels
。
dataset
中保存的每个路径 i
split("/")[1]
方法获取每张图片所属的文件夹名称labels
中(dataset, labels)
。
执行下面的代码来看一下函数的输出结果。
preprocessing
函数并将数据集的路径 pedestrian
作为函数的输入值dataset
和 labels
。输出结果:
我们已经学习了方向梯度直方图
feature
模块。from skimage import feature
然后我们创建一个 HOG
类并初始化 __init__
构造函数。
orientations
、 pixelsPerCell
、cellsPerBlock
、 transform
orientations
表示要将梯度方向分成几个区间,这里我们设置一个默认值 9
。pixelsPerCell
表示每个 Cell 中有几个像素,我们设置默认值为 (8, 8)
。cellsPerBlock
表示每个 Block 中有几个 Cells,我们设置默认值为 (3, 3)
。transform
是一个布尔类型,表示是否使用伽马校正预先对图片进行归一化处理,我们设置默认值为 False
。class HOG:
def __init__(self, orientations = 9, pixelsPerCell = (8, 8),
cellsPerBlock = (3, 3), transform = False):
self.orienations = orientations
self.pixelsPerCell = pixelsPerCell
self.cellsPerBlock = cellsPerBlock
self.transform = transform
def describe(self, image):
hist = feature.hog(image, orientations = self.orienations,
pixels_per_cell = self.pixelsPerCell,
cells_per_block = self.cellsPerBlock,
transform_sqrt = self.transform)
return hist
接下来我们再定义一个函数 describe
image
,表示要进行 HOG 特征描述的图片。feature.hog
方法计算 HOG 特征feature.hog
对应的参数,最后返回 feature.hog
的计算结果即可。
现在我们将使用这两个模块编写一个训练数据集的脚本。
首先导入需要用到的模块
这些模块的作用我们将稍后一一为大家介绍。
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.svm import LinearSVC
import joblib
import cv2
import numpy as np
接着调用 preprocessing
函数
pedestrian
作为函数的输入dataset
以及图片对应的标签 labels
。(dataset, labels) = preprocessing("pedestrian")
下面:
sklearn.preprocessing
中导入的 LabelEncoder
类实例化一个对象 L
.fit_transform
方法将 labels
中的字符串转换为各不相同的整数。L = LabelEncoder()
labels = L.fit_transform(labels)
因为 sklearn
中的算法需要整数编码的标签
labels
中的字符串标签 background
和 people
编码为不同的整数labels
自动编码为[1,1,1 ... 0,0,0]
的形式。
接下来:
HOG
类初始化一个 hog
实例transform
参数设为 True
。hog = HOG(transform = True)
data
列表用于存储从每张图片中提取的 HOG 特征for
循环将每张图片转化为 HOG 特征data
中data = []
for i in dataset:
image = cv2.imread(i)
gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
resized = cv2.resize(gray, (64, 128), interpolation = cv2.INTER_AREA)
hist = hog.describe(resized)
data.append(hist)
具体的操作是:
cv2.imread
读取数据集中每张图片cv2.cvtColor
方法将图片转化为灰度图cv2.resize
将每张图片都缩放到相同尺寸:
64
×
128
64\times128
64×128
需要注意的是如果每张图片不是相同的尺寸,那么在后面的训练模型时会产生错误。
hog
实例中的 describe
函数将图片转化为 HOG 特征data
中。
将所有特征保存好之后:
sklearn.model_selection
模块导入的 train_test_split
方法(trainData, testData, trainLabels, testLabels) = train_test_split(
np.array(data), np.array(labels), test_size=0.15, random_state=42)
传入 4 个参数给该方法,其参数意义如下所示:
data
是保存的所有特征
labels
是 data
中每个特征对应的标签
test_size
表示我们测试集占总样本比例
0.15
表示数据集中的 15% 的图片将被划分为测试集。random_state
表示随机种子42
。
执行函数我们将获得:
trainData
testData
trainLabels
testLabels
。
sklearn.svm
模块导入的 LinearSVC
类model
。print("### Training model...")
model = LinearSVC()
model.fit(trainData, trainLabels)
model
实例的 fit
方法训练模型fit
方法需要两个参数:
trainData
是我们的训练集
模型训练好后我们就可以使用 model
实例的 predict
方法在测试集上进行分类测试
testData
作为参数传入 preditct
方法即可print("### Evaluating model...")
predictions = model.predict(testData)
接着:
sklearn.metrics
导入的 classification_report
方法print(classification_report(testLabels, predictions, target_names=L.classes_))
我们给该方法传入 3 个参数,其参数意义如下所示:
testLabels
是测试集中图片对应的标签。predictions
是模型推理的分类标签。target_names
表示类别
L
的 class_
属性people
和 background
传递给该参数。
可以看到我们的模型在 349 个测试图片上的准确度 (accuracy)是 99%。
最后我们使用 joblib
模块的 dump
方法保存训练好的模型。
model
是我们训练好的模型"model"
是模型保存的路径。joblib.dump(model, "model")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。