1. 下载网络结构及模型
1.1 下载 MobileNet V1 定义网络结构的文件
MobileNet V1 的网络结构可以直接从官方 GitHub 库中下载定义网络结构的文件, 地址为:
1.2 下载 MobileNet V1 预训练模型
MobileNet V1 预训练的模型文在如下地址中下载:
打开以上网址, 可以看到 MobileNet V1 官方预训练的模型, 官方提供了不同输入尺寸和不同网络中通道数的多个模型, 并且提供了每个模型对应的精度. 可以根据实际的需要下载对应的模型, 如下图所示.
MobileNet V1 不同输入和不同通道数的官方预训练模型
这里以选择 MobileNet_v1_1.0_192 为例, 表示网络中的所有卷积后的通道数为标准通道数 (即 1.0 倍), 输入图像尺寸为 192X192.
2. 构建网络结构及加载模型参数
2.1 构建网络结构
在 1.1 小节中下载 mobilenet_v1.py 文件后, 使用其中的 mobilenet_v1 函数构建网络结构静态图, 如下代码所示.
- import tensorflow as tf
- from mobilenet_v1 import mobilenet_v1,mobilenet_v1_arg_scope
- slim = tf.contrib.slim
- def build_model(inputs):
- with slim.arg_scope(mobilenet_v1_arg_scope(is_training=False)):
- logits, end_points = mobilenet_v1(inputs, is_training=False, depth_multiplier=1.0, num_classes=1001)
- scores = end_points['Predictions']
- print(scores)
- #取概率最大的 3 个类别及其对应概率
- output = tf.nn.top_k(scores, k=3, sorted=True)
- #indices 为类别索引, values 为概率值
- return output.indices,output.values
上面代码中, 使用函数 tf.nn.top_k 取概率最大的 3 个类别机器对应概率.
2.2 加载模型参数
- CKPT = 'mobilenet_v1_1.0_192.ckpt'
- def load_model(sess):
- loader = tf.train.Saver()
- loader.restore(sess,CKPT)
- inputs=tf.placeholder(dtype=tf.float32,shape=(1,192,192,3))
- classes_tf,scores_tf = build_model(inputs)
- with tf.Session() as sess:
- load_model(sess)
先定义 placeholder 输入 inputs, 再通过函数 build_model 完成静态图的定义. 接下来传入 tf.Session 对象到 load_model 函数中完成模型加载.
3. 模型测试
3.1 加载 Label
网络输出结果为类别的索引值, 需要将索引值转为对应的类别字符串. 先从官网下载 label 数据, 需要注意的是 MobileNet V1 使用的是 ILSVRC-2012-CLS http://www.image-net.org/challenges/LSVRC/2012/ 数据, 因此需要下载对应的 Label 信息 (本文后面附件中会提供). 解析 Label 数据代码如下.
- def load_label():
- label=['其他']
- with open('label.txt','r',encoding='utf-8') as r:
- lines = r.readlines()
- for l in lines:
- l = l.strip()
- arr = l.split(',')
- label.append(arr[1])
- return label
3.2 测试结果
使用如下图片进行测试.
测试图片
执行 inference.py 后, 控制台输出结果如下所示.
识别 test_images/test1.PNG 结果如下:
No. 0 类别: 军用飞机 概率: 0.9363691
No. 1 类别: 飞机翅膀 概率: 0.032617383
No. 2 类别: 炮弹 概率: 0.01853972
识别 test_images/test2.PNG 结果如下:
No. 0 类别: 小儿床 概率: 0.9455737
No. 1 类别: 摇篮 概率: 0.044925883
No. 2 类别: 板架 概率: 0.007288801
4 完整代码
inference.py 完整的代码如下所示.
- import tensorflow as tf
- from mobilenet_v1 import mobilenet_v1,mobilenet_v1_arg_scope
- import cv2
- import os
- import numpy as np
- slim = tf.contrib.slim
- CKPT = 'mobilenet_v1_1.0_192.ckpt'
- dir_path = 'test_images'
- def build_model(inputs):
- with slim.arg_scope(mobilenet_v1_arg_scope(is_training=False)):
- logits, end_points = mobilenet_v1(inputs, is_training=False, depth_multiplier=1.0, num_classes=1001)
- scores = end_points['Predictions']
- print(scores)
- #取概率最大的 5 个类别及其对应概率
- output = tf.nn.top_k(scores, k=3, sorted=True)
- #indices 为类别索引, values 为概率值
- return output.indices,output.values
- def load_model(sess):
- loader = tf.train.Saver()
- loader.restore(sess,CKPT)
- def get_data(path_list,idx):
- img_path = images_path[idx]
- img = cv2.imread(img_path)
- img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
- img = cv2.resize(img,(192,192))
- img = np.expand_dims(img,axis=0)
- img = (img/255.0-0.5)*2.0
- return img_path,img
- def load_label():
- label=['其他']
- with open('label.txt','r',encoding='utf-8') as r:
- lines = r.readlines()
- for l in lines:
- l = l.strip()
- arr = l.split(',')
- label.append(arr[1])
- return label
- inputs=tf.placeholder(dtype=tf.float32,shape=(1,192,192,3))
- classes_tf,scores_tf = build_model(inputs)
- images_path =[dir_path+'/'+n for n in os.listdir(dir_path)]
- label=load_label()
- with tf.Session() as sess:
- load_model(sess)
- for i in range(len(images_path)):
- path,img = get_data(images_path,i)
- classes,scores = sess.run([classes_tf,scores_tf],feed_dict={inputs:img})
- print('\n 识别',path,'结果如下:')
- for j in range(3):#top 3
- idx = classes[0][j]
- score=scores[0][j]
- print('\tNo.',j,'类别:',label[idx],'概率:',score)
5. 附件下载
来源: https://www.qcloud.com/developer/article/1356892