一、项目简介
- OpenCV是一个用于图像处理、分析、机器视觉方面的开源工具包。无论科学研究,还是商业应用,OpenCV都是进行图像识别的不二之选。熟练掌握OpenCV的图片识别能力,在图片识别领域里飞起来不是梦!
- 本文利用kaggle数据库上的水果图片数据集(fruit-images-for-object-detection)展示如何训练机器学习模型识别水果图片的类别。
- 数据地址(kaggle数据库地址需要插件支持才能正常访问,请自行百度):
https://www.kaggle.com/mbkinaci/fruit-images-for-object-detection
二、图片数据分析
- 数据库分为训练集(train)和测试集(test)两部分
- 训练集包含四类apple,orange,banana,mixed(多种水果混合)四类237张图片;测试集包含每类图片各两张。图片集如下图所示。
- 图片类别可由图片名称中提取。
训练集图片预览
测试集预览
三、模型构建和实现
- 建模思路:将rgb图片转化为gray灰度图,进而提取关键点信息,训练hmm模型进行图片预测。
- 核心工具包:cv2,hmmlearn
1、导入工具包
import os
import warnings
import numpy as np
import cv2 as cv
import hmmlearn.hmm as hl
warnings.filterwarnings(
'ignore', category=DeprecationWarning)
np.seterr(all='ignore')
2、收集文件路径
- 将图片文件(jpg,png等…)收集在字典中备用
def search_objects(directory):
# 将文件路径格式化,以便适应于各种操作系统
directory = os.path.normpath(directory)
# 如果输入路径不是文件件则抛出异常
if not os.path.isdir(directory):
raise IOError(directory + '不是文件夹')
objects = {}
# 遍历文件夹收集jpg文件,放入字典
for curdir, _, files in os.walk(directory):
for jpeg in [file for file in files
if file.endswith('.jpg')]:
path = os.path.join(curdir, jpeg)
# 从文件名中提取图片所属类别
label = jpeg.split('_')[0]
# label = path.split(os.path.sep)[-2]
if label not in objects:
objects[label] = []
objects[label].append(path)
return objects
3、图片特征值提取
- 定义flags主要是来区分训练集合测试集,测试集需要保存图片并呈现,训练集不需要。
# 收集图片数据集的标签和灰度值
def label_desc02(objects, flags=None):
data_x, data_y, data_z = [], [], []
# 遍历类别标签及对应的文件名
for label, files in objects.items():
descs = np.array([])
for file in files:
image = cv.imread(file)
# 训练阶段可不收集图片,不用给定flags值
if flags:
# 保存(测试集)中的图片
data_z.append([])
data_z[-1].append(image)
# 将图片转化为灰度图
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
h, w = gray.shape[:2]
f = 600 / min(h, w)
gray = cv.resize(gray, None, fx=f, fy=f)
# 提取灰度图的关键点特征值
star = cv.xfeatures2d.StarDetector_create()
keypoints = star.detect(gray)
sift = cv.xfeatures2d.SIFT_create()
_, desc = sift.compute(gray, keypoints)
if len(descs) == 0:
descs = desc
# print(descs)
else:
descs = np.append(descs, desc, axis=0)
# print(descs)
if flags:
# 测试集按图片进行特征值收集
data_x.append(descs)
data_y.append(label)
if not flags:
# 训练集按类别进行特征值收集
data_x.append(descs)
data_y.append(label)
return data_x, data_y, data_z
4、模型的创建和预测
# 训练模型函数,hmm模型
def model_train(data_x, data_y):
models = {}
for descs, label in zip(data_x, data_y):
model = hl.GaussianHMM(
n_components=4, covariance_type='diag',
n_iter=1000) # 提取4个主要特征,训练上限为1000轮
models[label] = model.fit(descs)
return models
# 定义利用图像识别进行模型预测的函数
def model_pred(test_x, models):
pred_test_y = []
for descs in test_x:
# for desc in descs:
# 定义最优得分和预测标签
best_score, best_label = None, None
for label, model in models.items():
score = model.score(descs)
# 选择则有得分的预测标签保存,作为预测值
if not best_score or (
best_score < score):
best_score, best_label = score, label
pred_test_y.append(best_label)
return pred_test_y
4、图片可视化
- 将测试集和预测结果进行可视化,观察预测效果
# 可视化识别的图片
def show_pics(test_y, pred_test_y, test_z):
i = 0
for label, pred_label, images in zip(
test_y, pred_test_y, test_z):
for image in images:
i += 1
cv.imshow('{} - {} {} {}'.format(
i, label,
'==' if label == pred_label
else '!=', pred_label), image)
5、模型执行
# 给定训练集、测试集路径地址
train_path = 'train'
test_path = 'test'
# 收集训练集、测试集的jpg文件
train_files = search_objects(train_path)
test_files = search_objects(test_path)
# 提取训练集、测试集图片文件关键点特征值
# 通过flags赋值区分测试集和训练集
train_x, train_y, _ = label_desc02(train_files)
test_x, test_y, test_z = label_desc02(test_files, flags=1)
# 观察测试集真实类别和预测类别列表
print(test_y)
print(pred_test_y)
测试集真实与预测类别列表
models = model_train(train_x, train_y)
# 利用模型进行测试集预测
pred_test_y = model_pred(test_x, models)
# 将预测结果与真实结果进行图片可视化
show_pics(test_y, pred_test_y, test_z)
# 设置键盘阻塞,保留图片
cv.waitKey()
测试集预测结果如下
四、模型评估
- 由预测结果可知,8张图片类型均预测正确。即使进行多次实验,模型仍具有较好的预测精度。
- 该模型可以作为四类水果的简单预测模型。
- 更加复杂准确的预测模型与上述模型具有相同的原理,可根据实际应用需求进行更新。
github地址:
https://github.com/Willsgao/Personal-projects/tree/master/跟着OpenCV飞起来_kaggle水果图片识别