图片分类的基本思路如下
rose.png
需要使用的库函数和功能说明
# 标签处理
from sklearn.preprocessing import LabelEncoder
# 随机森林分类器模型
from sklearn.ensemble import RandomForestClassifier
# 对数据集进行有效划分的方法,划分成训练集和测试集
# from sklearn.cross_validation import train_test_split
# 在python新版本中,train_test_split被移动到model_selection中
from sklearn.model_selection import train_test_split
# 分类器性能评估报告
from sklearn.metrics import classification_report
# 基本矩阵运算库
import numpy as np
# 文件操作模块,主要是进行文件搜索和通配符操作
import glob
# opencv函数库
import cv2
glob函数使用参考:python glob model - 漩涡鸣人 - 博客园
# 加载所有的图片和蒙版
imagePath = "dataset/images"
maskPath = "dataset/masks"
# 利用sorted函数实现名字的一一对应,对每个图片进行蒙版的加载
imagePaths = sorted(glob.glob(imagePath + "/*.png"))
maskPaths = sorted(glob.glob(maskPath + "/*.png"))
# 计算直方图,返回的是均一化之后的彩色直方图数据
features = desc.describe(image,mask)
# 构造测试数据集的特征信息集合
data.append(features)
# 注意图片的命名格式为"image_crocus_0001.png",我们需要提取的"crocus"是倒数第二个
target.append(imagePath.split("_")[-2])
# 初始化一个打标签的对象
le = LabelEncoder()
# 对target进行数字化标签index(因为字符串这种特征是不能直接拿来训练的,需要转换成唯一的数值)
target = le.fit_transform(target)
标签处理:unique()
和fit_transform()
的用法
target = ["happy","birthday","happy","wedding","happy","ending"]
unique
对这串字符串进行去重:
targetNames = np.unique(target)
print(targetNames)
['birthday' 'ending' 'happy' 'wedding']
fit_transform
最后算出每个字符串label
对应的标签序号,此时brithday
,ending
,happy
,wedding
按照字母表顺序,分别对应0~3。
le = LabelEncoder()
target = le.fit_transform(target)
print(target)
[2 0 2 3 2 1]
# 对数据进行训练集和测试集的划分,划分比例是7:3
(trainData,testData,trainTarget,testTarget) = \
train_test_split(data,target,test_size=0.3,random_state=42)
# 初始化一个随机森林分类器模型
model = RandomForestClassifier(n_estimators=25,random_state=84)
# 用训练集训练这个分类器模型
model.fit(trainData,trainTarget)
# 用测试集合评估分类器性能,并打印出来
print(classification_report(testTarget, model.predict(testData),\
target_names=targetNames))
# 生成图片的特征(彩色直方图)
features = desc.describe(image,mask)
# 预测输出,从数字index转换成对应的字符串标签
flower = le.inverse_transform(model.predict([features]))[0]
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
# from sklearn.cross_validation import train_test_split
# 在python新版本中,train_test_split被移动到model_selection中
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import numpy as np
import glob
import cv2
# 定义一个RGB直方图的类和方法
class RGBHistogram:
def __init__(self,bins):
self.bins = bins
# 定义对图片特征的描述为彩色直方图
def describe(self,image,mask=None):
# 计算三个通道的直方图
hist=cv2.calcHist([image],[0,1,2],mask,self.bins,[0,256,0,256,0,256])
# 直方图均一化,减少图片亮度和对比度信息的干扰
cv2.normalize(hist,hist)
return hist.flatten()
# 加载所有的图片和蒙版
imagePath = "dataset/images"
maskPath = "dataset/masks"
# 利用sorted函数实现名字的一一对应,对每个图片进行蒙版的加载
imagePaths = sorted(glob.glob(imagePath + "/*.png"))
maskPaths = sorted(glob.glob(maskPath + "/*.png"))
# data保存彩色直方图信息,保存测试数据集的feature
data = []
# target保存图片名称的字符串信息,相当于测试数据的label
target = []
# 实例化一个计算RGB直方图的对象,类似于一个操作句柄
desc = RGBHistogram([8,8,8])
# 数据预处理,把照片信息转换成可训练的数据
for (imagePath,maskPath) in zip(imagePaths,maskPaths):
# 读取照片和蒙版
image = cv2.imread(imagePath)
mask = cv2.imread(maskPath)
# 虽然蒙版已经是黑白的了,但要确保图片格式也是灰度表示的
mask = cv2.cvtColor(mask,cv2.COLOR_BGR2GRAY)
# 计算直方图,返回的是均一化之后的彩色直方图数据
features = desc.describe(image,mask)
# 构造测试数据集的特征信息集合
data.append(features)
# 注意图片的命名格式为"image_crocus_0001.png",我们需要提取的"crocus"是倒数第二个
target.append(imagePath.split("_")[-2])
# 这时候的target里面保存的是字符串,并不是具体的数值,还不能进行学习
# 对名字进行去重处理,注意target本身没变,targetNames是去重之后的标签名
targetNames = np.unique(target)
# 初始化一个打标签的对象
le = LabelEncoder()
# 对target进行数字化标签index(因为字符串这种特征是不能直接拿来训练的,需要转换成唯一的数值)
target = le.fit_transform(target)
######################### 至此,数据预处理已经全部完成 ##############################
# 对数据进行训练集和测试集的划分,划分比例是7:3
(trainData,testData,trainTarget,testTarget) = \
train_test_split(data,target,test_size=0.3,random_state=42)
# 初始化一个随机森林分类器模型
model = RandomForestClassifier(n_estimators=25,random_state=84)
# 用训练集训练这个分类器模型
model.fit(trainData,trainTarget)
# 用测试集合评估分类器性能,并打印出来
print(classification_report(testTarget, model.predict(testData),\
target_names=targetNames))
######################### 至此,训练已经全部完成 ##############################
# 随机抽取10个案例进行测试
for i in np.random.choice(np.arange(0,len(imagePaths)),10):
imagePath = imagePaths[i]
maskPath = maskPaths[i]
image = cv2.imread(imagePath)
mask = cv2.imread(maskPath)
mask = cv2.cvtColor(mask,cv2.COLOR_BGR2GRAY)
# 生成特征(彩色直方图)
features = desc.describe(image,mask)
# 预测输出,从数字index转换成对应的字符串标签
flower = le.inverse_transform(model.predict([features]))[0]
print(imagePath)
print("According to RFT, this flower is {}".format(flower))
cv2.imshow("predicted to be {}".format(flower.upper()),image)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.destroyAllWindows()
学习器的性能如下
precision recall f1-score support
crocus 0.92 1.00 0.96 12
daisy 0.88 0.93 0.90 15
pansy 1.00 0.85 0.92 20
sunflower 0.96 1.00 0.98 24
accuracy 0.94 71
macro avg 0.94 0.95 0.94 71
weighted avg 0.95 0.94 0.94 71
预测输出效果: