0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

用Inception-v3进行图像识别的方法

Tensorflowers 来源:cg 2018-12-31 09:22 次阅读

对于我们的大脑来说,视觉识别似乎是一件特别简单的事。人类不费吹灰之力就可以分辨狮子和美洲虎、看懂路标或识别人脸。但对计算机而言,这些实际上是很难处理的问题:这些问题只是看起来简单,因为大脑非常擅长理解图像。

在过去几年内,机器学习领域在解决此类难题方面取得了巨大进展。尤其是,我们发现一种称为深度卷积神经网络的模型可以很好地处理较难的视觉识别任务 - 在某些领域的表现与人类大脑不相上下,甚至更胜一筹。

研究人员通过用ImageNet(计算机视觉的一种学术基准)验证其工作成果,证明他们在计算机视觉方面取得了稳步发展。他们陆续推出了以下几个模型,每一个都比上一个有所改进,且每一次都取得了新的领先成果:QuocNet、AlexNet、Inception (GoogLeNet)、BN-Inception-v2。Google 内部和外部的研究人员均发表过关于所有这些模型的论文,但这些成果仍是难以复制的。现在我们将采取后续步骤,发布用于在我们的最新模型Inception-v3上进行图像识别的代码。

Inception-v3 使用 2012 年的数据针对ImageNet大型视觉识别挑战赛训练而成。它处理的是标准的计算机视觉任务,在此类任务中,模型会尝试将所有图像分成1000 个类别,如 “斑马”、“斑点狗” 和 “洗碗机”。例如,以下是AlexNet对某些图像进行分类的结果:

为了比较各个模型,我们会检查正确答案不在模型预测的最有可能的 5 个选项中的频率,称为 “top-5 错误率”。AlexNet在 2012 年的验证数据集上实现了 15.3% 的 top-5 错误率;Inception (GoogLeNet)、BN-Inception-v2和Inception-v3的 top-5 错误率分别达到 6.67%、4.9% 和 3.46%。

人类在 ImageNet 挑战赛上的表现如何?Andrej Karpathy 曾尝试衡量自己的表现,他发表了一篇博文,提到自己的 top-5 错误率为 5.1%。

教程将介绍如何使用Inception-v3。您将了解如何使用 PythonC++ 将图像分成1000 个类别。此外,我们还将讨论如何从该模型提取更高级别的特征,以重复用于其他视觉任务。

我们期待看到社区会用该模型完成什么任务。

使用 Python API

首次运行程序时,classify_image.py会从tensorflow.org下载经过训练的模型。您的硬盘上需要有约 200M 的可用空间。

首先,从 GitHub 克隆TensorFlow 模型代码库。运行以下命令:

cd models/tutorials/image/imagenetpython 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指向所使用的目录。

使用 C++ API

您可以使用 C++ 运行同一Inception-v3模型,以在生产环境中使用模型。为此,您可以下载包含 GraphDef 的归档文件,GraphDef 会以如下方式定义模型(从 TensorFlow 代码库的根目录运行):

curl -L "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz" |tar -C tensorflow/examples/label_image/data -xz

接下来,我们需要编译包含加载和运行图的代码的 C++ 二进制文件。如果您按照针对您平台的说明下载 TensorFlow 源安装文件,则应该能够通过从 shell 终端运行以下命令来构建该示例:

bazel build tensorflow/examples/label_image/...

上述命令应该会创建一个可执行的二进制文件,然后您可以运行该文件,如下所示:

bazel-bin/tensorflow/examples/label_image/label_image

这里使用的是框架附带的默认示例图像,输出结果应与以下内容类似:

I tensorflow/examples/label_image/main.cc:206] military uniform (653): 0.834306I tensorflow/examples/label_image/main.cc:206] mortarboard (668): 0.0218692I tensorflow/examples/label_image/main.cc:206] academic gown (401): 0.0103579I tensorflow/examples/label_image/main.cc:206] pickelhaube (716): 0.00800814I tensorflow/examples/label_image/main.cc:206] bulletproof vest (466): 0.00535088

在本例中,我们使用的是默认的海军上将格蕾丝·赫柏的图像,您可以看到,网络可正确识别她穿的是军装,分数高达 0.8。

接下来,您可以通过调整 --image= 参数,用自己的图像试一试,例如:

bazel-bin/tensorflow/examples/label_image/label_image --image=my_image.png

我们希望此代码可帮助您将 TensorFlow 集成到您自己的应用中,因此我们将逐步介绍主要函数:

命令行标记可控制文件加载路径以及输入图像的属性。由于应向模型输入 299x299 RGB 的正方形图像,因此标记input_width和input_height应设成这些值。此外,我们还需要将像素值从介于 0 至 255 之间的整数缩放成浮点值,因为图执行运算时采用的是浮点数。我们使用input_mean和input_std标记控制缩放;先用每个像素值减去input_mean,然后除以input_std。

这些值看起来可能有点不可思议,但它们只是原模型作者根据他 / 她想要用做输入图像以用于训练的内容定义的。如果您有自行训练的图,只需对值做出调整,使其与您在训练过程中使用的任何值一致即可。

您可以参阅ReadTensorFromImageFile()函数,了解这些标记是如何应用到图像的。

首先,我们创建一个GraphDefBuilder对象,它可用于指定要运行或加载的模型。

string input_name = "file_reader"; string output_name = "normalized"; tensorflow::Node* file_reader = tensorflow::ops::ReadFile(tensorflow::ops::Const(file_name, b.opts()), b.opts().WithName(input_name));

然后,为要运行的小型模型创建节点,以加载、调整和缩放像素值,从而获得主模型期望作为其输入的结果。我们创建的第一个节点只是一个Const操作,它会存储一个张量,其中包含要加载的图像的文件名。然后,该张量会作为第一个输入传递到ReadFile操作。您可能会注意到,我们将b.opts()作为最后一个参数传递到所有操作创建函数。该参数可确保该节点会添加到GraphDefBuilder中存储的模型定义中。此外,我们还通过向b.opts()发起WithName()调用来命名ReadFile运算符,从而命名该节点,虽然这不是绝对必要的操作(因为如果您不执行此操作,系统会自动为该节点分配名称),但确实可简化调试过程。

// Now try to figure out what kind of file it is and decode it. const int wanted_channels = 3; tensorflow::Node* image_reader; if (tensorflow::StringPiece(file_name).ends_with(".png")) { image_reader = tensorflow::ops::DecodePng( file_reader, b.opts().WithAttr("channels", wanted_channels).WithName("png_reader")); } else { // Assume if it's not a PNG then it must be a JPEG. image_reader = tensorflow::ops::DecodeJpeg( file_reader, b.opts().WithAttr("channels", wanted_channels).WithName("jpeg_reader")); } // Now cast the image data to float so we can do normal math on it. tensorflow::Node* float_caster = tensorflow::ops::Cast( image_reader, tensorflow::DT_FLOAT, b.opts().WithName("float_caster")); // The convention for image ops in TensorFlow is that all images are expected // to be in batches, so that they're four-dimensional arrays with indices of // [batch, height, width, channel]. Because we only have a single image, we // have to add a batch dimension of 1 to the start with ExpandDims(). tensorflow::Node* dims_expander = tensorflow::ops::ExpandDims( float_caster, tensorflow::ops::Const(0, b.opts()), b.opts()); // Bilinearly resize the image to fit the required dimensions. tensorflow::Node* resized = tensorflow::ops::ResizeBilinear( dims_expander, tensorflow::ops::Const({input_height, input_width}, b.opts().WithName("size")), b.opts()); // Subtract the mean and divide by the scale. tensorflow::ops::Div( tensorflow::ops::Sub( resized, tensorflow::ops::Const({input_mean}, b.opts()), b.opts()), tensorflow::ops::Const({input_std}, b.opts()), b.opts().WithName(output_name));

接下来,我们继续添加更多节点,以便将文件数据解码为图像、将整数转换为浮点值、调整大小,最终对像素值运行减法和除法运算。

// This runs the GraphDef network definition that we've just constructed, and // returns the results in the output tensor. tensorflow::GraphDef graph; TF_RETURN_IF_ERROR(b.ToGraphDef(&graph));

最后,我们获得一个存储在变量 b 中的模型定义,并可以使用ToGraphDef()函数将其转换成一个完整的图定义。

std::unique_ptr session( tensorflow::NewSession(tensorflow::SessionOptions())); TF_RETURN_IF_ERROR(session->Create(graph)); TF_RETURN_IF_ERROR(session->Run({}, {output_name}, {}, out_tensors)); return Status::OK();

接下来,创建一个tf.Session对象(它是实际运行图的接口)并运行它,从而指定要从哪个节点获得输出,以及将输出数据存放在什么位置。

这为我们提供了一个由Tensor对象构成的向量,在此例中,我们知道它将仅是单个对象的长度。在这种情况下,您可以将Tensor视为多维数组,它将 299 像素高、299 像素宽、3 通道的图像存储为浮点值。如果您的产品中已有自己的图像处理框架,则应该能够使用该框架,只要在将图像馈送到主图之前对其应用相同的转换即可。

下面是使用 C++ 动态创建小型 TensorFlow 图的简单示例,但对于预训练的 Inception 模型,我们需要从文件中加载更大的定义。您可以查看LoadGraph()函数,了解我们如何做到这一点。

// Reads a model graph definition from disk, and creates a session object you// can use to run it.Status LoadGraph(string graph_file_name, std::unique_ptr* session) { tensorflow::GraphDef graph_def; Status load_graph_status = ReadBinaryProto(tensorflow::Env::Default(), graph_file_name, &graph_def); if (!load_graph_status.ok()) { return tensorflow::errors::NotFound("Failed to load compute graph at '", graph_file_name, "'"); }

如果您已经浏览图像加载代码,则应该对许多术语都比较熟悉了。我们会加载直接包含GraphDef的 protobuf 文件,而不是使用GraphDefBuilder生成GraphDef对象。

session->reset(tensorflow::NewSession(tensorflow::SessionOptions())); Status session_create_status = (*session)->Create(graph_def); if (!session_create_status.ok()) { return session_create_status; } return Status::OK();}

然后,我们从该GraphDef创建一个 Session 对象,并将其传递回调用程序,以便调用程序稍后可以运行它。

GetTopLabels()函数很像图像加载,只是在本例中,我们想要获取运行主图得到的结果,并将其转换成得分最高的标签的排序列表。与图像加载器类似,该函数可创建一个GraphDefBuilder,向其添加几个节点,然后运行较短的图,从而获取一对输出张量。在本例中,它们分别表示最高结果的经过排序的得分和索引位置。

// Analyzes the output of the Inception graph to retrieve the highest scores and// their positions in the tensor, which correspond to categories.Status GetTopLabels(const std::vector& outputs, int how_many_labels, Tensor* indices, Tensor* scores) { tensorflow::GraphDefBuilder b; string output_name = "top_k"; tensorflow::ops::TopK(tensorflow::ops::Const(outputs[0], b.opts()), how_many_labels, b.opts().WithName(output_name)); // This runs the GraphDef network definition that we've just constructed, and // returns the results in the output tensors. tensorflow::GraphDef graph; TF_RETURN_IF_ERROR(b.ToGraphDef(&graph)); std::unique_ptr session( tensorflow::NewSession(tensorflow::SessionOptions())); TF_RETURN_IF_ERROR(session->Create(graph)); // The TopK node returns two outputs, the scores and their original indices, // so we have to append :0 and :1 to specify them both. std::vector out_tensors; TF_RETURN_IF_ERROR(session->Run({}, {output_name + ":0", output_name + ":1"}, {}, &out_tensors)); *scores = out_tensors[0]; *indices = out_tensors[1]; return Status::OK();

PrintTopLabels()函数会采用这些经过排序的结果,并以友好的方式输出这些结果。CheckTopLabel()函数与其极为相似,但出于调试目的,需确保最有可能的标签是我们预期的值。

最后,main()将所有这些调用绑定在一起。

int main(int argc, char* argv[]) { // We need to call this to set up global state for TensorFlow. tensorflow::port::InitMain(argv[0], &argc, &argv); Status s = tensorflow::ParseCommandLineFlags(&argc, argv); if (!s.ok()) { LOG(ERROR) << "Error parsing command line flags: " << s.ToString();    return -1;  }  // First we load and initialize the model.  std::unique_ptr session;  string graph_path = tensorflow::io::JoinPath(FLAGS_root_dir, FLAGS_graph);  Status load_graph_status = LoadGraph(graph_path, &session);  if (!load_graph_status.ok()) {    LOG(ERROR) << load_graph_status;    return -1;  }

加载主图

// Get the image from disk as a float array of numbers, resized and normalized // to the specifications the main graph expects. std::vector resized_tensors; string image_path = tensorflow::io::JoinPath(FLAGS_root_dir, FLAGS_image); Status read_tensor_status = ReadTensorFromImageFile( image_path, FLAGS_input_height, FLAGS_input_width, FLAGS_input_mean, FLAGS_input_std, &resized_tensors); if (!read_tensor_status.ok()) { LOG(ERROR) << read_tensor_status;    return -1;  }  const Tensor& resized_tensor = resized_tensors[0];

加载、处理输入图像并调整其大小

// Actually run the image through the model. std::vector outputs; Status run_status = session->Run({ {FLAGS_input_layer, resized_tensor}}, {FLAGS_output_layer}, {}, &outputs); if (!run_status.ok()) { LOG(ERROR) << "Running model failed: " << run_status;    return -1;  }

在本示例中,我们将图像作为输入,运行已加载的图

// This is for automated testing to make sure we get the expected result with // the default settings. We know that label 866 (military uniform) should be // the top label for the Admiral Hopper image. if (FLAGS_self_test) { bool expected_matches; Status check_status = CheckTopLabel(outputs, 866, &expected_matches); if (!check_status.ok()) { LOG(ERROR) << "Running check failed: " << check_status;      return -1;    }    if (!expected_matches) {      LOG(ERROR) << "Self-test failed!";      return -1;    }  }

出于测试目的,我们可以在下方检查以确保获得了预期的输出

// Do something interesting with the results we've generated. Status print_status = PrintTopLabels(outputs, FLAGS_labels);

最后,输出我们找到的标签

if (!print_status.ok()) { LOG(ERROR) << "Running print failed: " << print_status;    return -1;  }

在本示例中,我们使用 TensorFlow 的Status对象处理错误,它非常方便,因为通过它,您可以使用ok()检查工具了解是否发生了任何错误,如果有错误,则可以输出可以读懂的错误消息。

在本示例中,我们演示的是对象识别,但您应该能够对您在各种领域找到的或自行训练的其他模型使用非常相似的代码。我们希望这一小示例可就如何在自己的产品中使用 TensorFlow 为您带来一些启发。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 图像识别
    +关注

    关注

    8

    文章

    447

    浏览量

    37907
  • 机器学习
    +关注

    关注

    66

    文章

    8120

    浏览量

    130550

原文标题:如何使用 Inception-v3,进行图像识别

文章出处:【微信号:tensorflowers,微信公众号:Tensorflowers】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    使用Python卷积神经网络(CNN)进行图像识别的基本步骤

    Python 卷积神经网络(CNN)在图像识别领域具有广泛的应用。通过使用卷积神经网络,我们可以让计算机从图像中学习特征,从而实现对图像的分类、识别和分析等任务。以下是使用 Pytho
    的头像 发表于 11-20 11:20 1784次阅读

    基于LabVIEW图像识别的物体外观实时分类研究

    基于LabVIEW图像识别的物体外观实时分类研究
    发表于 04-26 13:07

    基于DSP的快速纸币图像识别技术研究

    本课题通过对现有图像识别技术进行研究和分析,针对当前DSP(数字信号处理)技术的新发展,提出了基于DSP的快速图像识别概念。快速图像识别技术以嵌入式系统为算法的实现平台,它结合了当前最
    发表于 11-05 14:43

    图像识别水果的智能称(我是一个新手求指点学习的道路)

    想问下我是一个大学的本科生现在还什么都不懂也没有做个什么项目想要用大学的四年做这样一个项目就是一个称可以起到图像识别的功能识别水果并且计算他的重量然后通过我已保存的相应的水果单价求出它的价格这样
    发表于 10-12 12:01

    基于vuforia的图像识别Jar的使用

    ,然后上传需要识别的图像。点击Add。图片上传过后,服务器会对图片的可辨识度进行打分,这个过程需要等候几分钟。处理好了以后封面会显示出刚才上传的图像。以及系统对
    发表于 09-20 11:58

    【HarmonyOS HiSpark AI Camera】渔业卫士-基于图像识别的多自由度水下机器人

    项目名称:渔业卫士-基于图像识别的多自由度水下机器人试用计划:1、申请理由希望早日接触、应用国产的鸿蒙系统。2、项目名称渔业卫士-基于图像识别的多自由度水下机器人3、计划(1)约三个月时间,应用该款
    发表于 09-25 10:11

    如何构建基于图像识别的印制线路板精密测试系统?

    如何构建基于图像识别的印制线路板精密测试系统?图像识别技术在印刷线路板精密测试中的应用
    发表于 04-27 06:25

    MATLAB图像识别物体计数

    MATLAB图像识别物体计数:MATLAB 图像识别物体计数,将图像中的物体识别出来,并进行计数,SIMULINK编程
    发表于 02-08 14:40 247次下载

    基于FPGA的智能车路径图像识别的预处理设计

    基于FPGA的智能车路径图像识别的预处理设计
    发表于 09-22 12:41 23次下载

    一文读懂图像识别,真的前景不可限量?

    图像识别技术人工智能 图像识别技术是人工智能的一个重要领域。它是指对图像进行对象识别,以识别各种
    发表于 08-21 17:25 627次阅读

    实验python进行图像识别的示例代码资料免费下载

    本文档的主要内容详细介绍的是实验python进行图像识别的示例代码资料免费下载。
    发表于 06-14 08:00 3次下载

    使用FPGA平台实现遗传算法的图像识别的研究设计说明

    利用模板匹配方法,采用基于遗传算法的图像识别技术,完成了对图像目标识别的算法验证。在此基础上进行了基于该算法的
    发表于 01-26 15:02 13次下载
    使用FPGA平台实现遗传算法的<b class='flag-5'>图像识别的</b>研究设计说明

    模拟矩阵在图像识别中的应用

    讯维模拟矩阵在图像识别中的应用主要是通过构建一个包含多种图像数据的模拟矩阵,来训练和测试深度学习模型,从而提高图像识别的准确性和效率。 在图像识别中,讯维模拟矩阵可以用来做以下几方面的
    的头像 发表于 09-04 14:17 323次阅读
    模拟矩阵在<b class='flag-5'>图像识别</b>中的应用

    一种基于图像识别的第五版人民币成色检测方法

    电子发烧友网站提供《一种基于图像识别的第五版人民币成色检测方法.pdf》资料免费下载
    发表于 10-13 11:19 0次下载
    一种基于<b class='flag-5'>图像识别的</b>第五版人民币成色检测<b class='flag-5'>方法</b>

    如何使用Python进行图像识别的自动学习自动训练?

    如何使用Python进行图像识别的自动学习自动训练? 使用Python进行图像识别的自动学习和自动训练需要掌握一些重要的概念和技术。在本文中,我们将介绍如何使用Python中的一些常用
    的头像 发表于 01-12 16:06 213次阅读