第三阶段-tensorflow项目之图像image相关--Image Recognition图像识别

时间:2022-08-02 13:51:38

Image Recognition图像识别

我们大脑识别图像非常简单。我们的大脑让视觉看起来很容易。 对于人类来说,分开一只狮子和一只美洲虎,读一个标牌,或者认出一个人的脸,并不费事。 但使用计算机来识别图像的内容是非常不易的。

在过去的几年里,机器学习领域在解决这些难题方面取得了巨大的进步。 具体而言,我们发现一种称为深度卷积神经网络CNNs的模型能够在硬视觉识别任务上达到合理的性能 - 在某些领域匹配或超出人类的表现。

图像研究人员通过对ImageNet的努力,证明了计算机视觉方面的稳定进展。ImageNet –an academic benchmark for computer vision. 是计算机视觉的学术基准。一连串的成功模型不断提升图片识别准确率,每一次都实现了一个新的最新的结果:QuocNet,AlexNet,Inception(GoogLeNet),BN-Inception-v2。 Google内部和外部的研究人员已经发表了描述所有这些模型的论文,但是结果仍然难以重现。 我们下一步通过发布我们的最新模型Inception-v3,运行图像识别。

Inception-v3使用2012年的数据对ImageNet大型视觉识别挑战进行了训练。这是计算机视觉中的一项标准任务,模型试图将整个图像分为1000个类,如“Zebra”,“Dalmatian”和“Dishwasher”。 例如,下面是AlexNet对一些图像进行分类的结果:
第三阶段-tensorflow项目之图像image相关--Image Recognition图像识别

为了对比模型,我们检查了模型错误率,作为前5个猜测之一 - 被称为“前5模型错误率”。 AlexNet通过设置2012年验证数据集的前5位错误率达到15.3%
初始(GoogLeNet)达到6.67%;
BN-Inception-v2达到4.9%;
Inception-v3达到3.46%。

1,Usage with Python API(使用pythonAPI实现)

本教程将教你如何使用Inception-v3。使用Python或C ++ ,您将学习如何将图像分类到1000个类中。 我们还将讨论如何从这个模型中提取更高级别的特征,这些特征可能会被其他视觉任务重用。

我们很高兴看到社区使用Python API用到这个模型。
当程序第一次运行时,classify_image.py从tensorflow.org下载训练好的模型。 您的硬盘上需要大约200M的可用空间。我们可以从github上下载源码

python classify_image.py

上述命令将分类出一只熊猫的图像。

如果模型正确运行,将产生以下输出:

giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.88493)
indri, indris, Indri indri, Indri brevicaudatus (score = 0.00878)
lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00317)
custard apple (score = 0.00149)
earthstar (score = 0.00127)

如果你想提供其他JPEG图像,你可以通过编辑–image_file参数来实现。

  • 如果你将模型数据下载到不同的目录,你需要将–model_dir指向所使用的目录。

注解代码

# -*- coding: utf-8 -*-


""" 一个简单的图像分类器 使用ImageNet 2012 Challenge数据训练的Inception运行图像分类 组。 该程序从保存的GraphDef协议缓冲区中创建一个图形, 并在输入的JPEG图像上运行。 它输出人类可读的 排名前5的预测字符串及其概率。 将--image_file参数更改为任何jpg图像来计算a 该图像的分类。 请参阅教程和网站,了解如何进行详细说明 使用这个python脚本来执行图像识别。 https://tensorflow.org/tutorials/image_recognition/ """

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import os.path
import re
import sys
import tarfile

import numpy as np
from six.moves import urllib
import tensorflow as tf

FLAGS = None

# pylint: disable=line-too-long,数据下载地址。
DATA_URL = 'http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz'
# pylint: enable=line-too-long


class NodeLookup(object):
  """ 将整数节点ID转换为人类可读标签。"""

  def __init__(self, label_lookup_path=None, uid_lookup_path=None):
    if not label_lookup_path:
      label_lookup_path = os.path.join(
          FLAGS.model_dir, 'imagenet_2012_challenge_label_map_proto.pbtxt')
    if not uid_lookup_path:
      uid_lookup_path = os.path.join(
          FLAGS.model_dir, '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):
    """ 为每个softmax节点加载一个人类可读的英文名称。 ARGS: label_lookup_path:字符串UID到整数节点ID。 uid_lookup_path:将UID转换为可读的字符串。 return: 从整数节点ID字符到可读的字符串。 """
    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)

    # 将字符串UID映射到可读的字符串
    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

    # 加载从字符串UID到整数节点ID的映射。
    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]

    # 将整数节点ID的最终映射加载到可读的字符串
    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]


def create_graph():
  """从保存的GraphDef文件创建一个图形并返回一个Saver。"""
  # 从 saved graph_def.pb 创建一个 graph
  with tf.gfile.FastGFile(os.path.join(
      FLAGS.model_dir, 'classify_image_graph_def.pb'), 'rb') as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
    _ = tf.import_graph_def(graph_def, name='')


def run_inference_on_image(image):
  """Runs inference on an image. Args: image: 图像名称. Returns:无 """
  if not tf.gfile.Exists(image):
    tf.logging.fatal('File does not exist %s', image)
  image_data = tf.gfile.FastGFile(image, 'rb').read()

  # 从 saved GraphDef 创建一个 graph 
  create_graph()

  with tf.Session() as sess:
     # 一些有用的张量:
     #'softmax:0':包含归一化预测的张量
     # 1000个标签。
     #'pool_3:0':包含2048的倒数第二层的张量
     # 浮动图像的描述。
     #'DecodeJpeg / contents:0':包含提供JPEG的字符串的张量。
     # 编码图像。
     # 通过将image_data作为输入提供给图表来运行softmax张量。
    softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')
    predictions = sess.run(softmax_tensor,
                           {'DecodeJpeg/contents:0': image_data})
    predictions = np.squeeze(predictions)

    # 创建一个ID --> 英文字符串lookup.
    node_lookup = NodeLookup()

    top_k = predictions.argsort()[-FLAGS.num_top_predictions:][::-1]
    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))


def maybe_download_and_extract():
  """下载训练的tar包文件。"""
  dest_directory = FLAGS.model_dir
  if not os.path.exists(dest_directory):
    os.makedirs(dest_directory)
  filename = DATA_URL.split('/')[-1]
  filepath = os.path.join(dest_directory, filename)
  if not os.path.exists(filepath):
    def _progress(count, block_size, total_size):
      sys.stdout.write('\r>> Downloading %s %.1f%%' % (
          filename, float(count * block_size) / float(total_size) * 100.0))
      sys.stdout.flush()
    filepath, _ = urllib.request.urlretrieve(DATA_URL, filepath, _progress)
    print()
    statinfo = os.stat(filepath)
    print('Successfully downloaded', filename, statinfo.st_size, 'bytes.')
  tarfile.open(filepath, 'r:gz').extractall(dest_directory)


def main(_):
  maybe_download_and_extract()
  image = (FLAGS.image_file if FLAGS.image_file else
           os.path.join(FLAGS.model_dir, 'cropped_panda.jpg'))
  run_inference_on_image(image)


if __name__ == '__main__':
  parser = argparse.ArgumentParser()
   # classify_image_graph_def.pb:
   # GraphDef协议缓冲区的二进制表示。
   # imagenet_synset_to_human_label_map.txt:
   # 从synset ID映射到可读的字符串。
   # imagenet_2012_challenge_label_map_proto.pbtxt:
   # 将标签映射到synset ID的协议缓冲区的文本表示。
  parser.add_argument(
      '--model_dir',
      type=str,
      default='/tmp/imagenet',
      help="""\ Path to classify_image_graph_def.pb, imagenet_synset_to_human_label_map.txt, and imagenet_2012_challenge_label_map_proto.pbtxt.\ """
  )
  parser.add_argument(
      '--image_file',
      type=str,
      default='',
      help='Absolute path to image file.'
  )
  parser.add_argument(
      '--num_top_predictions',
      type=int,
      default=5,
      help='Display this many predictions.'
  )
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

更多的学习资源。

1, Michael Nielsen’s free online book is an excellent resource.
2, Chris Olah has some nice blog posts
3, Michael Nielsen’s book has a great chapter covering them.