首页 > 分享 > 基于TensorFlow的CNN卷积网络模型花卉分类(1)

基于TensorFlow的CNN卷积网络模型花卉分类(1)

一、项目描述

使用TensorFlow进行卷积神经网络实现花卉分类的项目,加载十种花分类,建立模型后进行预测分类图片
环境:win10 +TensorFlow gpu 1.12.0+pycharm
训练集
训练数据存放路径为:‘D:/LearnMSA/flower/train/花文件名/*.jpg’
训练模型存储路径为:'D:/LearnMSA/flower/model/‘
测试样本路径及文件名为:'D:/LearnMSA/flower/test/花文件名/**.jpg‘
测试用图片文件从训练数据中任意拷贝一张即可。

训练模型

建立模型=导入库+获取数据集+图片处理+搭建模型+小批量处理+训练模型+保存模型

文件名:CnnFlower.py

from skimage import io, transform import glob import os import tensorflow as tf import numpy as np import time os.environ['TF_CPP_MIN_LOG_LEVEL']='2' # 数据集地址 path='D:/LearnMSA/flower/train/' #模型保存地址 model_path='D:/LearnMSA/flower/model/model.ckpt' #设置图像处理后的大小 #分别是长*宽*通道3 w=100 h=100 c=3 # 1.读取图片 def read_img(path): # os.listdir(path)表示在path路径下的所有文件和和文件夹列表 # 用cate记录十种花的文件路径 cate=[path+x for x in os.listdir(path) if os.path.isdir(path+x)] imgs=[] #存放所有的图片 labels=[] #图片的类别标签 for idx,folder in enumerate(cate): # enumerate函数用于将一个可遍历的数据对象组合为一个索引序列,同时列出数据和下标,一般用在for循环当中 for im in glob.glob(folder+'/*.jpg'): # 利用glob.glob函数搜索每个层级文件下面符合特定格式“/*.jpg”进行遍历 try: print('reading the images:%s'%(im)) # 遍历图像的同时,打印每张图片的“路径+名称”信息 img=io.imread(im) # 利用io.imread函数读取每一张被遍历的图像并将其赋值给img try: #对异常图片进行处理 if img.shape[2] == 3: img = transform.resize(img, (w, h)) imgs.append(img) labels.append(idx) except: continue except: print("Cannot open image!") # 利用np.asarray函数对生成的imgs和labels列表数据进行转化,之后转化成数组数据(imgs转成浮点数型,labels转成整数型) return np.asarray(imgs,np.float32),np.asarray(labels,np.int32) data,label=read_img(path) print('shape of data=',data.shape) #查看样本数组大小 print('shape od labels=',label.shape) #查看标签数组大小 #5.数据预处理 # 打乱顺序 ###调用np.random.shuffle函数将有序数组变无序 ###返回打乱顺序后的图片和对应的标签 num_example = data.shape[0] #表示矩阵的行数 arr = np.arange(num_example) #生成0到num_example个数 np.random.shuffle(arr) # 随机打乱arr数组 data = data[arr] # 将data以arr索引重新组合 label = label[arr] # 将label以arr索引重新组合 # 将所有数据分为训练集和验证集 ratio = 0.8 #设置训练集比例 s = np.int(num_example*ratio) x_train = data[:s] y_train = label[:s] x_val = data[s:] y_val = label[s:] # -----------------构建网络---------------------- #占位符设置输入参数的大小和格式 # 插入一个张量的占位符,这个张量总是被喂入图片数据。相当于一个形参。 x = tf.placeholder(tf.float32, shape=[None,w,h,c,], name='x') #用于传递样本数据 y_ = tf.placeholder(tf.int32, shape=[None,], name='Y_') #用于传递标签 print('x:',x.shape) print('y:',y_.shape) #6.建立训练模型 def inference(input_tensor,train,regularizer): # -----------------------第一层---------------------------- with tf.variable_scope('layer1-conv1'): # 初始化权重conv1_weights为可保存变量,大小为5x5,3个通道(RGB),数量为32个 conv1_weight = tf.get_variable('weight', [5, 5, 3, 32], initializer=tf.truncated_normal_initializer(stddev=0.1)) # 初始化偏置conv1_biases,数量为32个 conv1_bias = tf.get_variable('bias', [32], initializer=tf.constant_initializer(0.0)) # conv1_weights为权重,strides=[1, 1, 1, 1]表示左右上下滑动步长为1,padding='SAME'表示输入和输出大小一样,即补0 conv1 = tf.nn.conv2d(input_tensor, conv1_weight, strides=[1, 1, 1, 1], padding='SAME') # 激励计算,调用tensorflow的relu函数 relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_bias)) with tf.name_scope('layer2-pool1'): # 池化计算,调用tensorflow的max_pool函数,strides=[1,2,2,1],表示池化边界,2个对一个生成,padding="VALID"表示不操作。 pool1=tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='VALID') # -----------------------第二层---------------------------- with tf.variable_scope('layer3-conv2'): # 定义第二个卷积层,原理和第一层相同 conv2_weight = tf.get_variable('weight', [5, 5, 32, 64], initializer=tf.truncated_normal_initializer(stddev=.1)) conv2_bias = tf.get_variable('bias', [64], initializer=tf.constant_initializer(0.0)) conv2 = tf.nn.conv2d(pool1, conv2_weight, strides=[1, 1, 1, 1], padding='SAME') relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_bias)) with tf.variable_scope('layer4-pool2'): pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID') # -----------------------第三层--------------------------- with tf.variable_scope('layer5-conv3'): # 定义第二个卷积层,原理和第一层相同 conv3_weight = tf.get_variable('weight', [3, 3, 64, 128], initializer=tf.truncated_normal_initializer(stddev=.1)) conv3_bias = tf.get_variable('bias', [128], initializer=tf.constant_initializer(0.0)) conv3 = tf.nn.conv2d(pool2, conv3_weight, strides=[1, 1, 1, 1], padding='SAME') relu3 = tf.nn.relu(tf.nn.bias_add(conv3, conv3_bias)) with tf.variable_scope('layer6-pool3'): pool3 = tf.nn.max_pool(relu3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID') # -----------------------第四层---------------------------- with tf.variable_scope('layer7-conv4'): # 定义第二个卷积层,原理和第一层相同 conv4_weight = tf.get_variable('weight', [3, 3, 128, 128], initializer=tf.truncated_normal_initializer(stddev=.1)) conv4_bias = tf.get_variable('bias', [128], initializer=tf.constant_initializer(0.0)) conv4 = tf.nn.conv2d(pool3, conv4_weight, strides=[1, 1, 1, 1], padding='SAME') relu4 = tf.nn.relu(tf.nn.bias_add(conv4, conv4_bias)) with tf.variable_scope('layer8-pool4'): pool4 = tf.nn.max_pool(relu4, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID') # 第八层输出的是矩阵:【6,6,128】,把矩阵变成向量,每张图片排列成6*6*128 的向量 nodes = 6 * 6 * 128 reshape = tf.reshape(pool4, [-1, nodes]) # 使用变形函数转化结构 # -----------------------第五层--------------------------- with tf.variable_scope('layer9-FC1'): fc1_weight = tf.get_variable('weight', [nodes, 1024], initializer=tf.truncated_normal_initializer(stddev=0.1)) if regularizer != None: tf.add_to_collection('losses', regularizer(fc1_weight)) # fc1_biases = tf.get_variable('bias', [1024], initializer=tf.constant_initializer(0.1)) fc1 = tf.nn.relu(tf.matmul(reshape, fc1_weight) + fc1_biases) if train: fc1 = tf.nn.dropout(fc1, 0.5) # -----------------------第六层---------------------------- with tf.variable_scope('layer10-FC2'): fc2_weight = tf.get_variable('weight', [1024, 512], initializer=tf.truncated_normal_initializer(stddev=0.1)) if regularizer != None: tf.add_to_collection('losses', regularizer(fc2_weight)) fc2_biases = tf.get_variable('bias', [512], initializer=tf.constant_initializer(0.1)) fc2 = tf.nn.relu(tf.matmul(fc1, fc2_weight) + fc2_biases) if train: fc2 = tf.nn.dropout(fc2, 0.5) # -----------------------第七层---------------------------- with tf.variable_scope('layer11-FC3'): fc3_weight = tf.get_variable('weight', [512, 10], initializer=tf.truncated_normal_initializer(stddev=0.1)) if regularizer != None: tf.add_to_collection('losses', regularizer(fc3_weight)) # fc3_biases = tf.get_variable('bias', [5], initializer=tf.constant_initializer(0.1))这个分类5,用于测试5种花卉 fc3_biases = tf.get_variable('bias', [10], initializer=tf.constant_initializer(0.1))#分10类 logits = tf.matmul(fc2, fc3_weight) + fc3_biases # 返回最后的计算结果 return logits # ---------------------------网络结束--------------------------- #设置正则化参数为0.0001 regularizer=tf.contrib.layers.l2_regularizer(0.001) #将上述构建网络结构引入 logits=inference(x,False,regularizer) print('shape of logits:',logits.shape) # (小处理)将logits乘以1赋值给logits_eval,定义name,方便在后续调用模型时通过tensor名字调用输出tensor b=tf.constant(value=1,dtype=tf.float32) logits_eval=tf.multiply(logits,b,name='logits_eval') #常数和矩阵想成 #设置损失函数,作为模型训练优化的参考标准,loss越小,模型越优 loss=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,labels=y_) #设置整体学习率为α为0.001 optimizer=tf.train.AdamOptimizer(learning_rate=0.001) #设置预测精度 train_op=optimizer.minimize(loss) correct_prediction=tf.equal(tf.cast(tf.argmax(logits,1),tf.int32),y_) #计算准确率 acc=tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) #7训练和测试 #定义一个函数,按照批次取数据 def minibatches(inputs=None,targets=None,batch_size=None,shuffle=False): assert len(inputs)==len(targets) if shuffle: indices = np.arange(len(inputs)) np.random.shuffle(indices) for start_idx in range(0, len(inputs) - batch_size + 1, batch_size): if shuffle: excerpt = indices[start_idx:start_idx + batch_size] else: excerpt = slice(start_idx, start_idx + batch_size) yield inputs[excerpt], targets[excerpt] n_epoch=10 batch_size=64 saver=tf.train.Saver() sess=tf.Session() sess.run(tf.global_variables_initializer()) for epoch in range(n_epoch): print('epoch:',epoch+1) start_time=time.time() #training train_loss,train_acc,n_batch=0,0,0 for x_train_a,y_train_a in minibatches(x_train,y_train,batch_size,shuffle=True): _,err,ac=sess.run([train_op,loss,acc],feed_dict={x:x_train_a,y_:y_train_a}) train_loss+=err train_acc+=ac n_batch+=1 print('train loss:%f'%(np.sum(train_loss)/n_batch)) print("train acc: %f" % (np.sum(train_acc) / n_batch)) #评估 val_loss,val_acc,n_batch=0,0,0 for x_vale_a,y_val_a in minibatches(x_val,y_val,batch_size,shuffle=False): err,ac=sess.run([loss,acc],feed_dict={x:x_vale_a,y_:y_val_a}) val_loss+=err val_acc+=ac n_batch+=1 print('validation loss : %f'%(np.sum(val_loss)/n_batch)) print('validation acc: %f'%(np.sum(val_acc)/n_batch)) print('epoch time:%f'%(time.time()-start_time)) print('-------------------------------------------') #8.保存模型 saver.save(sess,model_path) #把运算后的模型保存 sess.close()

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244

运行这个py文件,会不断的读图,最后生成模型,运行图如下:
在这里插入图片描述
运行成功如下:
在这里插入图片描述
D:/LearnMSA/flower/model/ 下生成模型
在这里插入图片描述

测试模型1

测试模型=读取图片+导入模型+测试模型
文件名:test_independent.py

from skimage import io,transform import tensorflow as tf import numpy as np import os import glob #glob 文件通配符模块 os.environ['TF_CPP_MIN_LOG_LEVEL']='2' w=100 h=100 c=3 path1 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/0向日葵107.jpg" path2 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/1樱花53.jpg" path3 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/2水仙花178.jpg" path4 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/3牡丹136.jpg" path5 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/5百合花284.jpg" path6 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/6莲花161.jpg" path7 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/9郁金香119.jpg" path8 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/4玫瑰1.jpg" path9 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/8蝴蝶兰263.jpg" path10 = "F:/DeskTop/大三下学期/机器学习/LearnMSA/flower/test/7菊花1.jpg" flower_dict = {0:'向日葵',1:'樱花',2:'水仙花',3:'牡丹',4:'玫瑰',5:'百合花',6:'莲花',7:'菊花', 8:'蝴蝶兰', 9:'郁金香'} model_path='D:/LearnMSA/flower/model/' def read_one_image(path): img = io.imread(path) img = transform.resize(img,(w,h)) return np.asarray(img) with tf.Session() as sess: data = [] data1 = read_one_image(path1) data2 = read_one_image(path2) data3 = read_one_image(path3) data4 = read_one_image(path4) data5 = read_one_image(path5) data6 = read_one_image(path6) data7 = read_one_image(path7) data8 = read_one_image(path8) data9 = read_one_image(path9) data10 = read_one_image(path10) data.append(data1) data.append(data2) data.append(data3) data.append(data4) data.append(data5) data.append(data6) data.append(data7) data.append(data8) data.append(data9) data.append(data10) saver = tf.train.import_meta_graph(model_path+'model.ckpt.meta') saver.restore(sess,tf.train.latest_checkpoint(model_path)) graph = tf.get_default_graph() x = graph.get_tensor_by_name("x:0") feed_dict = {x:data} logits = graph.get_tensor_by_name("logits_eval:0") classification_result = sess.run(logits,feed_dict) #打印出预测矩阵 print(classification_result) #打印出预测矩阵每一行最大值的索引 print(tf.argmax(classification_result,1).eval()) #根据索引通过字典对应花的分类 output = [] output = tf.argmax(classification_result,1).eval() for i in range(len(output)): print("第",i+1,"朵花预测:"+flower_dict[output[i]])

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475

运行结果图如下:
在这里插入图片描述

测试模型2

设置一个文件夹的目录,读取目录下的图片,随机选择一个图片并显示处理
文件名:test.py

from skimage import io,transform import tensorflow as tf import numpy as np import os import matplotlib.pyplot as plt from PIL import Image os.environ['TF_CPP_MIN_LOG_LEVEL']='2' w=100 h=100 c=3 path=r'D:/LearnMSA/flower/test/8蝴蝶兰/' model_path='D:/LearnMSA/flower/model/' flower_dict = {0:'向日葵',1:'樱花',2:'水仙花',3:'牡丹',4:'玫瑰',5:'百合花',6:'莲花',7:'菊花', 8:'蝴蝶兰', 9:'郁金香'} # 随机选择一张图片 def get_one_image(path): # 输入参数:path,测试图片的路径 # 返回参数:image,从测试图片中随机抽取一张图片 print(path) allPic = [] for pic in os.listdir(path): if pic.endswith("jpg") or pic.endswith("png"): allPic.append(pic) print(pic) n = len(allPic) ind = np.random.randint(0, n) img_dir = allPic[ind] # 随机选择测试的图片 img = io.imread(path + img_dir) img = transform.resize(img, (w, h)) imgshow = Image.open(path + img_dir) plt.imshow(imgshow) plt.show() image = np.array(img) return image with tf.Session() as sess: data = [] data1 = get_one_image(path) data.append(data1) saver = tf.train.import_meta_graph(model_path+'model.ckpt.meta') saver.restore(sess,tf.train.latest_checkpoint(model_path)) graph = tf.get_default_graph() x = graph.get_tensor_by_name("x:0") feed_dict = {x:data} logits = graph.get_tensor_by_name("logits_eval:0") classification_result = sess.run(logits,feed_dict) #打印出预测矩阵 print(classification_result) #打印出预测矩阵每一行最大值的索引 print(tf.argmax(classification_result,1).eval()) #根据索引通过字典对应花的分类 output = [] output = tf.argmax(classification_result,1).eval() for i in range(len(output)): print("第",i+1,"朵花预测:"+flower_dict[output[i]])

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

运行结果如下:
在这里插入图片描述

结果预测跟文件夹里的图片一样,要提一点,要保证一些图片读取或者模型保存及读取的路径要正确,需要在程序里修改一下。

下一期再倒腾一个GUI的花卉识别

相关知识

基于tensorflow的花卉识别
深度学习之基于Tensorflow卷积神经网络花卉识别系统
colab cnn实现花卉图片分类识别
基于深度卷积神经网络的移动端花卉识别系统
花卉识别(tensorflow)
基于深度学习和迁移学习的识花实践
深度学习机器学习卷积神经网络的花卉识别花种类识别
基于深度学习的花卉识别研究
毕业设计 深度学习花卉识别
毕设分享 深度学习花卉识别

网址: 基于TensorFlow的CNN卷积网络模型花卉分类(1) https://m.huajiangbk.com/newsview37016.html

所属分类:花卉
上一篇: 花卉的赏析
下一篇: 花卉的含义,花自身的含义是什么?