基于Tensorflow的卷积神经⽹络模型⽔果识别分类(实践案
例)
⼀、案例描述
图集下载地址:
⼆、项⽬步骤
整个项⽬可分为以下6个步骤
1. 数据采集
2. 数据可视化(每个分类⽂件夹中的第5张图⽚的显⽰)
3. 数据预处理
4. 搭建Tensorflow构建卷积神经⽹络模型
5. 优化器的选择与效果⽐较
6. 查看模型在测试集上的准确率
三、实践过程
1、数据的采集
##导包
import os
import skimage
import numpy as np
import matplotlib.pyplot as plt
from skimage import color,data,transform
from sklearn.utils import shuffle
import keras
from keras.utils import np_utils
未识别的网络将当前路径改为图集⽂件路径
##改变当前路径
os.chdir('D://fruits//fruits-360')
读图函数,⽅法很多,我是通过os.listdir()这个函数来实现⽂件夹下的循环读图,返回的数据有所有的图集数据以列表形式存放;其对应的标签,这⾥的标签由于其⽂件夹是字符串,不便于后期的独热编码转换,故⽽存放为外循环的迭代数;每个⽂件夹下的第5张图⽚以及其对应的⽂件夹名作为标签,⽤于后⾯实现⽼师要求的第五张图⽚的可视化。
##获取对应路径⽂件夹下的图⽚数据
def load_data(dir_path):
images=[] ##新建⼀个空列表⽤于存放图⽚数集
labels=[] ##新建⼀个空列表⽤于存放标签数集
no5_imgs=[] ##新建⼀个空列表⽤于存放每个⽂件夹下的第五张图⽚
labels_no5=[] ##新建⼀个空列表⽤于存放第五张图⽚对应的⽂件夹名
lab=os.listdir(dir_path)
n=0
for l in lab:
img=os.listdir(dir_path+l) ##img为对应路径下的⽂件夹
for i in img:
img_path=dir_path+l+'/'+i ##是的话获取图⽚路径
labels.append(int(n)) ##将外循环的迭代数n存于labels中
images.append(skimage.data.imread(img_path)) ##读取对应路径图像存放于datasets中
n+=1
no5_img=format_path(img) ##将图⽚按正确顺序排列⼀下,便于取得第5张图⽚
img5_path=dir_path+l+'/'+no5_img
labels_no5.append(l)
no5_imgs.append(skimage.data.imread(img5_path)) ##将每个类别的第五张图⽚读出后存放于数据集no5_imgs中
return images,labels,no5_imgs,labels_no5 ##返回的images内的图⽚存放顺序与实际⽂件夹中存放的顺序不同
为了让你们更好地看到⽂件的读取顺序以及以上函数的作业,我输出⼀下读取的图⽚路径,输出代码不显⽰在以上函数中
我们可以看到本来想要的读取顺序是0_100.jpg、10_100.jpg……,但是最终读到的结果不是这样的,如果你们只是做模型训练可以不管读图顺序,但由于我们有要求要显⽰ ⽂件夹下的第五张图⽚,故⽽引申出以下两个函数
调整获取到的图集的顺序的函数,由于部分图⽚的命名规则不同⼤致可以分为两类,⼀类是⽂件名分割后的第⼀部分可以转换为整型的和不可以转换为整型的,⼤致命名格式如下图:
##⽤于顺序读取⽂件夹内⽂件的函数
def format_path(img): ##img为 os.listdir(标签⽂件夹) 的结果
yes_int=[] ##新建列表⽤于存放分割后的第⼀项可转化为整型的⽂件名
for s in range(len(img)): ##遍历
img[s] = img[s].split('_') ##把⽂件名以'_'为间隔符分开
if(is_number(img[s][0])): ##判断⽂件名分割后的第⼀部分能否转化为整型
img[s][0]=int(img[s][0]) ##把⽂件名第⼀部分转换为整数
yes_int.append(img[s]) ##将该⽂件名放到没有带r的列表中
yes_int.sort() ##可以转化为整型的⽂件名的列表进⾏排序
for yi in range(len(yes_int)): ##变量
yes_int[yi][0]=str(yes_int[yi][0]) ##把之前转为整型的部分再转回字符串
yes_int[yi]=yes_int[yi][0]+'_'+yes_int[yi][1] ##进⾏拼接
no5_img=yes_int[4]
return no5_img
##判断⼀个⼀个数据是否能够转换为整形
def is_number(s):
try:
float(s)
return True
except ValueError:
pass
try:
import unicodedata
unicodedata.numeric(s)
return True
except (TypeError, ValueError):
pass
return False
最终获取到的77类⽔果图⽚的数据集
##最终数据集与标签
images,labels,no5_imgs,labels_no5=load_data('./Training/')
print(len(images),len(labels),len(no5_imgs))
同理加载测试集
##最终测试数据集与标签
images_test,labels_test,no5_imgs_test=load_data('./Test/')
print(len(images_test),len(labels_test),len(no5_imgs_test),len(labels_no5)
2、数据的可视化
定义⼀个函数遍历no5_imgs数据集,显⽰⾥⾯的图⽚以及对应的标签labels_no5
##定义第5张图⽚可视化函数
def display_no5_img(no5_imgs,labels_no5):
fig = plt.figure(figsize=(15,15)) ##显⽰的尺⼨为15*15
for i in range(len(no5_imgs)):
plt.subplot(11,7,(i+1)) ##显⽰为11⾏,每⾏7个
plt.title("{0}".format(labels_no5[i])) ##显⽰标题
plt.imshow(no5_imgs[i]) ##显⽰图⽚
plt.axis('off') ##不显⽰坐标轴
plt.show()
##调⽤显⽰函数
display_no5_img(no5_imgs,labels_no5)
结果如下所⽰
3、数据的预处理
由于77类⽔果的数据集约3万多张图⽚,我的电脑承受不了这么多图⽚的训练,故⽽我只选取数据集中的前20类进⾏训练,当然如果你们的电脑可以承受,你们可以⾃⼰去试⼀下,或者对图⽚进⾏批量裁剪可能可以进⾏77类的实验。下⾯是加载⼩数据集的函数。
##由于数据集过⼤,先加载⼩部分进⾏训练,n代表⼏个类
def load_small_data(dir_path,m):
images_m=[] ##新建⼀个空列表⽤于存放图⽚数集
labels_m=[] ##新建⼀个空列表⽤于存放标签数集
lab=os.listdir(dir_path)
n=0
for l in lab:
if(n>=m):
break
img=os.listdir(dir_path+l) ##img为对应路径下的⽂件夹
for i in img:
img_path=dir_path+l+'/'+i ##是的话获取图⽚路径
labels_m.append(int(n)) ##将图⽚的上层⽂件夹转换为int类型存于labels中
images_m.append(skimage.data.imread(img_path)) ##读取对应路径图像存放于images_m中
n+=1
return images_m,labels_m ## m类标签以及数据
images_20,labels_20=load_small_data('./Training/',20) ##训练集
images_test_20,labels_test_20=load_small_data('./Test/',20) ##测试集
在图像处理的领域中,有很多种⽅式,如图像的去噪、平移、反转、灰度化、裁剪等,下⾯会有⼀些
相关的处理函数,你们可以选择⽤或者不⽤,但在本次实验中我并未⽤的这些上述的处理⽅式,⽽是简单的把图像数据集转换为数组形式,并将其乱序,对变迁数据集进⾏keras 的独热编码。我使⽤过进⾏过灰度处理后的图像数据集对模型进⾏训练,结果对测试集的预测的准确率有所降低,我的导师给我的建议是不进⾏灰度处理,因为颜⾊也属于⽔果的特征之⼀。但我还是将之前写的灰度处理函数和图⽚裁剪函数贴上来。
##使⽤列表推导式完成图像的批量裁剪
def cut_image(images,w,h):
new_images=[size(I,(w,h)) for I in images]
return new_images
##预处理数据函数(数组化,乱序)
def prepare_data(images,labels,n_classes):
##images64=cut_image(images,64,64) ##裁剪图⽚⼤⼩为64*64
train_x=np.array(images)
train_y=np.array(labels)
##images_b2gray(images_a) ##转灰度
indx=np.arange(0,train_y.shape[0])
indx=shuffle(indx)
train_x=train_x[indx]
train_y=train_y[indx]
train_y=_categorical(train_y,n_classes) ##one-hot独热编码
return train_x,train_y
##训练集数据预处理
train_x,train_y=prepare_data(images_20,labels_20,20)
##测试数据集与标签的数组化和乱序
test_x,test_y=prepare_data(images_test_20,labels_test_20,20)
4、Tensorflow卷积神经⽹络的搭建
发布评论