基于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()


运行这个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]])


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

测试模型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]])


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

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

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

  • 5
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值