Serverless 打造智能微信小程序:图像识别分析文本

栏目: 编程工具 · 发布时间: 6年前

内容简介:结束了五一国庆的八天假期后,便开始着手为微信小程序《代码协作》制作一个图片识别代码的功能。这个需求的主要来源是,在有的公司、组织、团队上,代码是不能直接拷贝出来的。但是,拍照是允许的。为了协作方便,一般会拍照在微信群里讨论。对于我而言,因此这样一个真实需求的存在,我便想试试能不能做这样的一个功能。对于图片识别功能来说,只需要两步:然而,第一步是最难的一步。

结束了五一国庆的八天假期后,便开始着手为微信小程序《代码协作》制作一个图片识别代码的功能。这个需求的主要来源是,在有的公司、组织、团队上,代码是不能直接拷贝出来的。但是,拍照是允许的。为了协作方便,一般会拍照在微信群里讨论。对于我而言,因此这样一个真实需求的存在,我便想试试能不能做这样的一个功能。

对于图片识别功能来说,只需要两步:

  1. 上传图片到 AWS S3 上
  2. 找到一个合适的图片识别服务,来识别这张图片

然而,第一步是最难的一步。

Serverless 上传图片

按理来说,我们只需要在 Serverless 应用里,接受这个数据,然后再存储到 AWS S3 就可以了。

微信小程序上传图片时,采用的 ContentType 是 multipart/form-data ,这就意味着上传的图片不是 base64 形式的。在 AWS Gateway 里,接受到的数据变成了:

{ fieldname: 'file',
  originalname: 'tmp_41852593e221427e029327f987f3d588.png',
  encoding: '7bit',
  mimetype: 'image/png',
  buffer: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 03 e8 00 00 02 80 08 06 00 00 00 0f 73 52 67 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 40 00 ... >,
  size: 870857 }

最开始的时候,我以为是微信小程序上传了。于是,我开始用 curl 来测试上传图片:

curl -v -F file=@test.jpg https://code.wdsm.io/upload

然后对比了本地 readFileSync 的 Buffer 数据,发现图片的编码变了。

然后,我测试了文本上传:

curl -v -F file=@hello.txt https://code.wdsm.io/upload

发现文本的编码结果是不变的。在 Google 了一番之后,发现是因为 AWS Gateway 是能识别文本编码的。

在我尝试了 N 次之后,并在本地构建了个类似的环境。发现了 AWS Gateway 做了一个神奇的转换: Buffer.from(imageData, 'utf8').toString('utf8') 。理论上,经过这样的转换,数据应该是变回原来的格式。然而,这个图片并不是 utf8 编码,所以这个数据无法转换回去。

在继续 Google 了一番之后,发现了一个 Serverless Framework 的插件:serverless-apigw-binary。它可以将图片转换为二进制形式的,而 AWS Gateway 不会对二进制的内容进行特殊编码。其配置如下所示:

custom:
  apigwBinary:
    types:
      - 'image/jpeg'
      - 'image/png'
      - 'text/html'
      - 'multipart/form-data'

上面配置中,最重要的其实是 'multipart/form-data' ,它会将我们的请求转换为二进制形式的。

正在我以为要大功告成的时候,我发现直接用 AWS Lambda 解析出来还是有问题。在尝试了多次之后,结合了一下 express 里的 multer 来解析这个数据,然后它工作了:

const express = require("express");
const multer = require('multer');

const multerupload = multer();
const app = express();

app.post('/upload', multerupload.any(), function (req, res) {
  let file = req.files[0];
  ...
});

果然,编码是要靠猜的。

Serverless 图片识别

在开始这部分之前,需要先了解一下 AWS Rekognition。

Amazon Rekognition 让您能够轻松地为应用程序添加图像和视频分析功能。您只需向 Rekognition API 提供图像或视频,然后此服务就能识别对象、人员、文字、场景和活动,以及检测任何不适宜的内容。

由于,我们的《代码协作》应用整个是基于 AWS 的,因此我们也就继续使用 AWS 的服务来识别文本。先将图片放到 AWS S3 上,然后才是识别:

s3.putObject({
  Body: file.buffer,
  Bucket: bucketName,
  Key: file.originalname,
  ContentType: file.mimetype
}, function (err, data) {
  const s3Config = {
    bucket: bucketName,
    imageName: file.originalname,
  };

  return ImageAnalyser
    .getImageText(s3Config)
    .then((text) => {
      console.log(JSON.stringify(text, null, '\t'));
      res.status(200).send(text)
    })
    ...
})

识别部分代码如下:

const rek = new AWS.Rekognition();

class ImageAnalyser {
  static getImageText(s3Config) {
    ...

    return new Promise((resolve, reject) => {
      rek.detectText(params, (err, data) => {
        if (err) {
          console.log(params, err);
          return reject(new Error(err));
        }
        return resolve(data);
      });
    });
  }
}

对应的返回结果:

{"TextDetections":[{"DetectedText":"test","Type":"LINE","Id":0,"Confidence":94.28083038330078,"Geometry":{"BoundingBox":{"Width":1.0391244888305664,"Height":1.0596693754196167,"Left":-0.023785971105098724,"Top":0.0029582083225250244},"Polygon":[{"X":-0.023785971105098724,"Y":0.0029582083225250244},{"X":1.0153385400772095,"Y":-0.012681752443313599},{"X":1.018007755279541,"Y":1.046987533569336},{"X":-0.021116789430379868,"Y":1.0626275539398193}]}},{"DetectedText":"test","Type":"WORD","Id":1,"ParentId":0,"Confidence":94.28083038330078,"Geometry":{"BoundingBox":{"Width":1.0354670286178589,"Height":1.058911919593811,"Left":-0.02123582363128662,"Top":-0.0029199719429016113},"Polygon":[{"X":-0.023785971105098724,"Y":0.0029582083225250244},{"X":1.0153385400772095,"Y":-0.012681752443313599},{"X":1.018007755279541,"Y":1.046987533569336},{"X":-0.021116789430379868,"Y":1.0626275539398193}]}}]}

微信小程序展示

于是在小程序端,我们只需要处理对应的结果即可:

wx.uploadFile({
  url: 'https://code.wdsm.io/upload',
  filePath: path,
  name: 'file',
  success: function (res) {
    let textDetections = JSON.parse(res.data)['TextDetections'];
    let code = '';

    for (let i = 0; i < textDetections.length; i++) {
      let textDetection = textDetections[i];
      if (textDetection.Type === 'LINE') {
        code = code + textDetection.DetectedText + '\n';
      }
    }

    that.setData({
      code: code,
      isUploading: false
    });
  },
  ...
})

然后,在页面上显示即可:

<view class="ai">
  <button type="default" class="btn" bindtap="chooseImage">上传图片</button>
  <view wx:if="{{code}}" class="weui-cells__title" size="mini">(点击复制文本)</view>
  <view wx:if="{{code}}" bindtap="copyCode">
     {{code}}
  </view>
</view>

<loading hidden="{{!isUploading}}">
  上传中...
</loading>

不过,这里有一个问题,这个 loading 好像有问题。

代码: https://github.com/phodal/code


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

CSS世界

CSS世界

张鑫旭 / 人民邮电出版社 / 2017-12 / CNY 69.00

本书从前端开发人员的需求出发,以“流”为线索,从结构、内容到美化装饰等方面,全面且深入地讲解前端开发人员必须了解和掌握的大量的CSS知识点。同时,作者结合多年的从业经验,通过大量的实战案例,详尽解析CSS的相关知识与常见问题。作者还为本书开发了专门的配套网站,进行实例展示、问题答疑。 作为一本CSS深度学习的书,书中介绍大量许多前端开发人员都不知道的CSS知识点。通过阅读本书,读者会对CSS......一起来看看 《CSS世界》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具