图像识别开放API-Tensorflow+Flask

一直在关注知乎的编程方向的栏目,一直在看各种大牛的文章,今天正好闲下来写了一个图像识别的开放API,该小型项目基于google人工智能框架Tensorflow以及Python方面的微型web框架Flask, 具体请移步Tensorflow以及Flask,本文将展示如何使用这两个工具搭建我们的第一个图像识别API,所有的代码皆可在github上发现。

搭建环境

其实搭建环境的话,就安装Tensorflow比较麻烦。首先安装Anaconda 3.5版本,本人使用的机器为windows,Tensorflow从0.12版本开始支持windows系统,可以这样安装

pip install --upgrade --ignore-installed tensorflow

一定要按照我这样的安装,不然会有问题的。。。

构建Tensorflow图像识别模型

学过一点点机器学习的同学们都知道,图像识别率的高低与训练好坏是有非常大的关系的,作为学生党,没有资金建立起自己的图像训练机器,好在Google已经将训练好的模型公开,我们只需要使用就可以。具体可以移步inception首先下载开放模型,并解压到文件夹。下面来开始搭建模型 classify_api.py

import re

import numpy as np
import tensorflow as tf


class NodeLookup(object):
    ####这段代码就是将模型中的类别以数字形式转换为人类可以理解的文字形式
    def __init__(self,
                 label_lookup_path=None,
                 uid_lookup_path=None):
        if not label_lookup_path:
            label_lookup_path = 'models/imagenet_2012_challenge_label_map_proto.pbtxt'
        if not uid_lookup_path:
            uid_lookup_path = 'models/imagenet_synset_to_human_label_map.txt'
        self.node_lookup = self.load(label_lookup_path, uid_lookup_path)

    def load(self, label_lookup_path, uid_lookup_path):
        if not tf.gfile.Exists(uid_lookup_path):
            tf.logging.fatal('File does not exist %s', uid_lookup_path)
        if not tf.gfile.Exists(label_lookup_path):
            tf.logging.fatal('File does not exist %s', label_lookup_path)
        proto_as_ascii_lines = tf.gfile.GFile(uid_lookup_path).readlines()
        uid_to_human = {}
        p = re.compile(r'[n\d]*[ \S,]*')
        for line in proto_as_ascii_lines:
            parsed_items = p.findall(line)
            uid = parsed_items[0]
            human_string = parsed_items[2]
            uid_to_human[uid] = human_string
        node_id_to_uid = {}
        proto_as_ascii = tf.gfile.GFile(label_lookup_path).readlines()
        for line in proto_as_ascii:
            if line.startswith('  target_class:'):
                target_class = int(line.split(': ')[1])
            if line.startswith('  target_class_string:'):
                target_class_string = line.split(': ')[1]
                node_id_to_uid[target_class] = target_class_string[1:-2]
        node_id_to_name = {}
        for key, val in node_id_to_uid.items():
            if val not in uid_to_human:
                tf.logging.fatal('Failed to locate: %s', val)
            name = uid_to_human[val]
            node_id_to_name[key] = name

        return node_id_to_name

    def id_to_string(self, node_id):
        if node_id not in self.node_lookup:
            return ''
        return self.node_lookup[node_id]


with tf.gfile.FastGFile('models/classify_image_graph_def.pb', 'rb') as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
    _ = tf.import_graph_def(graph_def, name='')

node_lookup = NodeLookup()

sess = tf.Session()
softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')


def classify(image_data):
    predictions = sess.run(softmax_tensor,
                           {'DecodeJpeg/contents:0': image_data})
    predictions = np.squeeze(predictions)
    top_k = predictions.argsort()[-10:][::-1]
    results = []
    for node_id in top_k:
        human_string = node_lookup.id_to_string(node_id)
        score = predictions[node_id]
        # print('%s (score = %.5f)' % (human_string, score))
        results.append({'label': human_string, 'score': '{:.2}'.format(score)})
    return results

当模型建立起来,我们可以使用Flask来开发web API。

from flask import Flask, request, render_template

from image_classify.classify_api import classify

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/classify', methods=['POST'])
def cls():
if request.files.get('file'):`
        file = request.files.get('file')
        data = file.read()
        results = classify(data)
# return jsonify({'res': classify(data)})
        return render_template('result.html', **locals())
else:
    return index()


if __name__ == '__main__':
    app.run(debug=True)

其中,主页与显示结果页为html文件,具体如下:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图像识别系统开放API</title>
</head>
<body>
<h1 style="color: chartreuse;text-align: center">图像识别系统开放API!</h1>
<form action="/classify" method="post" enctype="multipart/form-data">
    <div style="align-items: center">
        请选择文件:<br/>
        <input type='file' name='file'/>
        <br/>
        <input type="submit" value="提交">
    </div>
</form>
</body>
</html>

result.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        .label {color: red;font-size: larger;}
        .result {color: green;font-size: larger;}
</style>
</head>
<body>
<h1 style="color: chartreuse;text-align: center">图像识别系统开放API!</h1>
<h3>识别结果为:</h3>
{% for result in results %}
<p>可能为 <span class="label">{{ result.get('label') }}</span>, 概率为 <span class="result">{{ result.get('score') }}</span></p>
{% endfor %}
</body>
</html>

整个系统的架构如下:

好了,我们开始运行起来,界面很丑。。。

我们选择一张图片,并点击提交,就会跳转到另一个页面,显示结果:

看到这里,是不是有点心动呢,赶紧学习起来,发挥你们想象力,使用Tensorflow做更多有趣的东西吧。记住,idea很便宜,做出来才是你自己的。

编辑于 2017-08-13

文章被以下专栏收录

    主要内容: 1. Python 奇淫技巧 2. Python 数据分析 3. Python 科学计算 4. Python 爬虫 愿景:提高工作效率,提升幸福感。 每篇必有码,码在 Github,接收 "有码" 投稿。