99行Swift编写人工智能图片识别服务器

更新时间:2017-06-21 14:54:00 点击次数:1961次

Swift 兼容性说明

本项目目前使用 Swift 3.1 或者 Swift 4.0 工具链编译,可以在macOS / Ubuntu上使用。

编译运行

运行以下命令可以运行本示例程序并在8080端口创建服务器:

git clone https://github.com/PerfectExamples/Perfect-TensorFlow-Demo-Vision.git cd Perfect-TensorFlow-Demo-Vision
./install.sh ./.build/debug/PerfectTensorFlowDemo
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

应该能够看到以下输出:

[INFO] Starting HTTP server localhost on 0.0.0.0:8080
  • 1
  • 1

意味着服务器已经准备好,请访问 http://localhost:8080/ 查看演示主页,您可以如下图所示上载一个本地图片考验计算机是否能够识别,或者甚至可以用鼠标手绘一个草图来测试计算机视觉识别能力。下面的例子是上载了一个信封✉️的照片,然后服务器识别返回给客户端,用英语问这是不是一个信封,并列出了可能是信封的概率::

识别一个信封

组合键control-c可以停止服务器运行。

服务器API

本项目的目标是制作这样的一个服务器,在调用根目录/recog函数API之后,客户端可以给服务器用POST表单发送一张图片,然后服务器对图像内容进行识别,识别完成之后返回给客户端一个json字符串,其中内容就是识别图像内容的结果;即如果图像内容是一个闹钟⏰,则回复字符串{“value”:”clock”}。

识别一个手绘闹钟

简介

本样例代码使用了一个预先训练好的机器视觉模型(数学家万岁,搞人工神经网络的数学家万岁万岁万万岁!): 
(http://arxiv.org/abs/1512.00567).

您可以将人工神经网络模型文件加载到一个Perfect TensorFlow Session对象,像这样:

let g = try TF.Graph()
let def = try TF.GraphDef(serializedData: model) try g.import(definition: def)
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

连同模型一起下载的还有一个已知物体的名单(英文)文件:

try fTag.open(.read)
let lines = try fTag.readString()
tags = lines.utf8.split(separator: 10).map { String(describing: $0) }
// 字符串数组变量应该看起来像这样:
// tags = ["dummy", "kit fox", "English setter", "Siberian husky" ...]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

一旦从客户端收到图片后,服务器会将图片内容正规化:

 public func constructAndExecuteGraphToNormalizeImage(_ g: TF.Graph, imageBytes: Data) throws -> TF.Tensor { let H:Int32 = 224 let W:Int32 = 224 let mean:Float = 117 let scale:Float = 1 let input = try g.constant(name: "input2", value: imageBytes) let batch = try g.constant( name: "make_batch", value: Int32(0)) let scale_v = try g.constant(name: "scale", value: scale) let mean_v = try g.constant(name: "mean", value: mean) let size = try g.constantArray(name: "size", value: [H,W]) let jpeg = try g.decodeJpeg(content: input, channels: 3) let cast = try g.cast(value: jpeg, dtype: TF.DataType.dtFloat) let images = try g.expandDims(input: cast, dim: batch) let resizes = try g.resizeBilinear(images: images, size: size) let subbed = try g.sub(x: resizes, y: mean_v) let output = try g.div(x: subbed, y: scale_v) let s = try g.runner().fetch(TF.Operation(output)).run()
    guard s.count > 0 else { throw TF.Panic.INVALID } return s[0]
  }//end normalize
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

然后就可以跑一下TensorFlow的会话输出:

let result = try g.runner().feed("input", tensor: image).fetch("output").run()
  • 1
  • 1

结果是一个概率数组,其长度与名单吻合,用于预测名单中每一个对象可能的概率。因此只要找出数组中大概率就可以获得图像被“识别”的结果:

public func match(_ g: TF.Graph, image: Data) throws -> (Int, Int) { let normalized = try constructAndExecuteGraphToNormalizeImage(imageBytes: image) let possibilities = try executeInceptionGraph(image: normalized)
    guard let m = possibilities.max(), let i = possibilities.index(of: m) else { throw TF.Panic.INVALID
    }//end guard return (i, Int(m * 100))
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

后一步就是把概率索引转换为对象名称,然后发给客户端:

let tag = tags[result.0] let p = result.1 response.setHeader(.contentType, value: "text/json")
        .appendBody(string: "{\"value\": \"Is it a \(tag)? (Possibility: \(p)%)\"}")
        .completed()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

大功告成!就是这样简单!

当然,如果您仍然觉得服务器配置和部署比较麻烦,那么请访问Perfect官网perfect.org,下载Perfect Assistant 2.0 ,即软件助手2.0版本,即可实现Swift函数库和预装人工智能服务器整体打包管理、编译、部署一条龙,目前支持亚马逊弹性计算和谷歌应用引擎,还将陆续增加更多服务器部署方案选择,这样您就可以随时改进自己的程序应用,逐步增加人工智能和神经网络、以及机器深度学习的新功能啦!

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!