一、前言
环境:Win10 + anaconda3 + jupyternotebook
图像的分类:
根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。
常见的分类算法:
包括朴素贝叶斯分类器、决策树、K最近邻分类算法、支持向量机、神经网络和基于规则的分类算法等,同时还有用于组合单一类方法的集成学习算法,如Bagging和Boosting等。
本文以朴素贝叶斯分类为主进行讨论,它适用于数据集较少的情况;而数据集少,基于复杂的模型用了太多假设,会导致欠拟合,因此这算是朴素贝斯算法的特点。
二、入门实例–花卉实例
17个类别的花卉数据集:
每个类别有80张图像。选择的花是英国的一些普通花。图像具有较大的比例,姿势和光线变化,并且在类内还存在图像变化较大且与其他类非常相似的类。类别可以在下图中看到。我们将数据集随机分为3个不同的训练,验证和测试集。图像的子集已被地面标记为分段。
1.下载数据集
下载17种花卉数据图片,
这里做简单实验,我只下载了数据集1360张(大小58M,有17类花卉每种40张,有txt图片名称列表)。
根据txt对,每40张分类到不同的文件夹中:
分类存放:shutil.move()
移动文件
"""1.下载17种花卉数据图片,每40张分类到一个文件夹中
下载地址:http://www.robots.ox.ac.uk/~vgg/data/flowers/17/
"""
import os
import shutil
n=0
label=0
with open("images/jpg/files.txt","r") as f:
for line in f.readlines():
if n < 40:
n=n+1
else:
label=label+1
n=0
path = 'images/jpg/'+ line.replace("\n", "")
path2 ='images/train/'+str(label)+'/'
if not os.path.exists(path2):
os.makedirs(path2)
shutil.move( path , path2+line.replace("\n", ""))
2.beyes分类原理
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。即假定给定目标值时属性之间相互条件独立。也就是说没有哪个属性变量对于决策结果来说占有着较大的比重,也没有哪个属性变量对于决策结果占有着较小的比重。
最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBM)。和决策树模型相比,朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率。
算法流程:
拆分:
- 待分类项 X 有10*40=400张图片:(我们取前10类花种),这个集合叫做训练样本集。
- 有类别10集合 y1 为 0类花种,40张;y2为1类花种,40张图像
- 统计10个花种类别各个特征属性的条件概率估计。
- 如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导
因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。
朴素贝叶斯分类分为三个阶段:
- 第一阶段——
准备工作阶段
,这个阶段的任务是为朴素贝叶斯分类做必要的准备,主要工作是根据具体情况确定特征属性,并对每个特征属性进行适当划分,然后由人工对一部分待分类项进行分类,形成训练样本集合。这一阶段的输入是所有待分类数据,输出是特征属性和训练样本。这一阶段是整个朴素贝叶斯分类中唯一需要人工完成的阶段,其质量对整个过程将有重要影响,分类器的质量很大程度上由特征属性、特征属性划分及训练样本质量决定。 - 第二阶段——
分类器训练阶段
,这个阶段的任务就是生成分类器,主要工作是计算每个类别在训练样本中的出现频率及每个特征属性划分对每个类别的条件概率估计,并将结果记录。其输入是特征属性和训练样本,输出是分类器。这一阶段是机械性阶段,根据前面讨论的公式可以由程序自动计算完成。 - 第三阶段——
应用阶段
。这个阶段的任务是使用分类器对待分类项进行分类,其输入是分类器和待分类项,输出是待分类项与类别的映射关系。这一阶段也是机械性阶段,由程序完成。
3.实例
-
切分训练集和测试集:
一共有400张图片,70%作为训练集286张;30%作为测试集,123张。 -
图像读取及转换为
像素直方图
(这里是特征提取标准,这里暂时用直方图特征来提取,简化过程;实际运用中,这里的提取标准应该是你自定义优化特征提取的函数) -
基于朴素贝叶斯的图像分类处理
采用BernoulliNB().fit(XX_train, y_train)
#伯努利贝叶斯分类器
predictions_labels = clf.predict(XX_test)
训练图片预测
classification_report(y_test, predictions_labels)
测试图片结果分析over!
完整代码:
"""2.朴素贝叶斯分类识别
将400张图像按照训练集为70%,测试集为30%的比例随机划分,
再获取每张图像的像素直方图,(这里后面替换为你的提取特征的方法)
根据像素的特征分布情况进行图像分类分析。
"""
# -*- coding: utf-8 -*-
import os
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, classification_report
#----------------------------------------------------------------------------------
# 第一步 切分训练集和测试集
#----------------------------------------------------------------------------------
X = [] #定义图像名称
Y = [] #定义图像分类类标
#Z = [] #定义图像像素
for i in range(0, 10):
#遍历文件夹,读取图片
for f in os.listdir("images/train/%s" % i):
#获取图像名称
X.append("images/train/" +str(i) + "/" + str(f))
#获取图像类标即为文件夹名称
Y.append(i)
X = np.array(X)
Y = np.array(Y)
#随机率为100% 选取其中的30%作为测试集
X_train, X_test, y_train, y_test = train_test_split(X, Y,test_size=0.3, random_state=1)
print(len(X_train), len(X_test), len(y_train), len(y_test))
#----------------------------------------------------------------------------------
# 第二步 图像读取及转换为像素直方图
#----------------------------------------------------------------------------------
#训练集
XX_train = []
for i in X_train:
#读取图像
#print i
image = cv2.imread(i)
#图像像素大小一致
img = cv2.resize(image, (256,256),interpolation=cv2.INTER_CUBIC)
#计算图像直方图并存储至X数组
hist = cv2.calcHist([img], [0,1], None,[256,256], [0.0,255.0,0.0,255.0])
XX_train.append(((hist/255).flatten()))
#测试集
XX_test = []
for i in X_test:
#读取图像
#print i
image = cv2.imread(i)
#图像像素大小一致
img = cv2.resize(image, (256,256),interpolation=cv2.INTER_CUBIC)
#计算图像直方图并存储至X数组
hist = cv2.calcHist([img], [0,1], None,[256,256], [0.0,255.0,0.0,255.0])
XX_test.append(((hist/255).flatten()))
#----------------------------------------------------------------------------------
# 第三步 基于朴素贝叶斯的图像分类处理
#----------------------------------------------------------------------------------
from sklearn.naive_bayes import BernoulliNB
# 使用训练集训练模型
clf = BernoulliNB().fit(XX_train, y_train)#伯努利贝叶斯分类器
predictions_labels = clf.predict(XX_test)
# 使用测试集预测结果
print(u'预测结果:')
print(predictions_labels)
# 生成文本型分类报告
print(u'算法评价:')#算法评价准确率(Precision)、召回率(Recall)和F值(F1-score)
print((classification_report(y_test, predictions_labels)))
# 生成字典型分类报告
report = classification_report(y_test, predictions_labels, output_dict=True)
print(u'第二张图的字典型分类报告:')
for key, value in report["1"].items():
print(f"{key:10s}:{value:10.2f}")
#输出前10张图片及预测结果
k = 0
while k<10:
#读取图像
print(X_test[k])
image = cv2.imread(X_test[k])
print(predictions_labels[k])
#显示图像
cv2.imshow("img", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
k = k + 1
结果:
一共有400张图片,70%作为训练集286张;30%作为测试集,123张。
123张的预测结果:
算法评价:算法评价准确率(Precision)、召回率(Recall)和F值(F1-score)
前十张的预测结果有有两张正确,因为我们的训练样本太少,以及特征提取仅依靠直方图一个因素进行判断,所以这里准确率不高。