全网最全阿里云图像识别API接入教程

1,430 阅读8分钟

全网最详细阿里云图像识别API接入流程

​ -----来自蜗哩技术团队

引言

在开发APP时,需要接入阿里云图像识别功能,由于阿里云官方文档总体比较乱,在此整理一下整个过程。

1.初识阿里云图像识别

进入阿里云视觉智能开放平台,我们首先以图像识别中的颜色识别为例,来作为切入口。

可以看到,图像识别拥有众多API,而进入颜色识别窗口,就可以看到清晰的请求参数配置示例(并不清晰)

image-20211120213807910.png

image-20211120213532095.png

是的,从官方文档提供的参数看来,似乎只要携带三个参数即可返回相应检测结果,实际上远不如此...

2.完成阿里云相关配置

首先,当然是开通一条账号,并且申请属于自己的OSS(对象存储空间),可以理解为这是阿里云提供的临时数据存储空间。

创建bucket

image-20211120214252574.png

image-20211120213943533.png

在OSS系统中,阿里云采用了一种Bucket的说法,简单来说,它就是一个个数据分组。便于相关技术人员进行管理。

我们配置bucket时,最好选择地域为华东上海(便于后续调用图像识别功能)。我在测试功能时选择了区域为华北北京,导致调用API时需要进行URL中转,这本身并不难,但是涉及到性能问题,后续会提到。

创建Access Key

现在我们应该为我们的账户创建一个独一无二的标识符——Access Key,点击右上角的头像即可看到管理选项,记住申请了Access Key后一定要将id和secret妥善保存!

image-20211120214817864.png

在搜索栏中直接搜索RAM访问控制台即可创建用户角色以及子用户的Access Key,并为之分配相应的权限,这就类似于数据库分配权限到角色上,这样可以产生多个用户角色(例如技术总管分配给不同的开发者)根据对应权限来调用相应的服务。

3.调用服务

开通对应服务

在调用服务前,先确保我们已经开通了对应的服务,可以看到目前图像识别只能通过华东上海的服务器进行调用

image-20211120215227790.png

业务逻辑

根据文档,要顺利调用该服务,整体流程应该是:

  • 上传本地图片或者网络图片URL到账户下的OSS中,此时OSS服务会返回对应的拥有阿里云服务器标识的新URL。
  • 将该URL作为参数和其他参数一起发送到图像识别服务器,得到结果。

遇到的麻烦

获取STS凭证

然而实际操作下来,发现事情没有这么简单:

首先,用户想将图片上传到OSS中,就需要获取云端发配的临时访问凭证。

因为要在不同客户端之间调用相应的图像识别功能,自然需要经过鉴权才能安全有效的执行(不然钱就亏光了,谁都可以调用服务)。阿里云提供了一种叫做STS的授权服务,好在也提供了各种语言的SDK,方便了广大技术栈的开发者(Node.js狂喜)

sts

获取STS凭证之前主账户的准备

要为账号开通STS服务,需要进行以下授权行为,前文提到过,我们可以创建不同的用户角色,给其分配不同的权限和对应的Access Key,接下来要做的就是为OSS服务创建一个用户,使其拥有颁发访问OSS的STS凭证的权限。

步骤一:创建RAM用户

  1. 登录RAM控制台
  2. 在左侧导航栏的身份管理菜单下,单击用户
  3. 单击创建用户
  4. 输入登录名称显示名称
  5. 访问方式区域下,选择Open API 调用访问,然后单击确定
  6. 单击复制,保存访问密钥(AccessKey ID 和 AccessKey Secret)。

步骤二:为RAM用户授予请求AssumeRole的权限

  1. 单击已创建RAM用户右侧对应的添加权限
  2. 添加权限页面,选择AliyunSTSAssumeRoleAccess权限。policy
  3. 单击确定

步骤三:创建用于获取临时访问凭证的角色

  1. 在左侧导航栏的身份管理菜单下,单击角色
  2. 单击创建角色,选择可信实体类型为阿里云账号,单击下一步
  3. 角色名称填写为RamOssTest,选择云账号当前云账号
  4. 单击完成。角色创建完成后,单击关闭
  5. RAM角色管理页面,搜索框输入角色名称RamOssTest。
  6. 单击复制,保存角色的ARN。arn

步骤四:为角色授予上传文件的权限

  1. 创建上传文件的自定义权限策略。

    1. 在左侧导航栏的权限管理菜单下,单击权限策略管理

    2. 单击创建权限策略

    3. 在新建自定义权限策略页面,填写策略名称为RamTestPolicy,配置模式选择脚本配置,并在策略内容中赋予角色向目标存储空间examplebucket下的目录exampledir上传文件的权限。警告:以下示例仅供参考。您需要根据实际需求配置更细粒度的授权策略,防止出现权限过大的风险。关于更细粒度的授权策略配置详情,请参见通过RAM或STS服务向其他用户授权

      {
          "Version": "1",
          "Statement": [
           {
                 "Effect": "Allow",
                 "Action": [
                   "oss:PutObject"
                 ],
                 "Resource": [
                   "acs:oss:*:*:examplebucket/exampledir",
                   "acs:oss:*:*:examplebucket/exampledir/*"
                 ]
           }
          ]
      }
      
    4. 单击确定

  2. 为RAM角色RamOssTest授予自定义权限策略。

    1. 在左侧导航栏的身份管理菜单下,单击角色
    2. 角色页面,找到目标RAM角色RamOssTest。
    3. 单击RAM角色RamOssTest右侧的添加权限
    4. 添加权限页面下的自定义策略页签,选择已创建的自定义权限策略RamTestPolicy。
    5. 单击确定

步骤五:获取临时访问凭证

调用提供的各语言SDK即可。

步骤六:使用临时访问凭证上传文件至OSS

在上传文件的所有SDK中,我们自然选择了Browser.js,这是阿里云唯一提供给web端(客户端)使用的SDK,至于为什么不选择Java或者Node.js,理由很简单,没有人想把图片资源先发送给后端(应用服务器),然后由后端再转发给阿里云的OSS存储。这意味着两倍的数据转发量和请求次数。造成的性能损失是不必要的。

image-20211120215907958.png

public static void main(String[] args) {
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-hangzhou.aliyuncs.com";
// 填写步骤五获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
// 填写步骤五获取的安全令牌SecurityToken。
String securityToken = "<yourSecurityToken>";

主要的四个参数如上。

至于如何获取返回的URL,文档已有详细说明,不再赘述。

image-20211120222022617.png

万事俱备?

现在我们也有了上传的图片的URL,是不是可以调用服务了呢?

错!!!

image-20211120222215006.png

查看API请求参数说明,发现只支持上海地域的OSS链接,而我创建的bucket是北京的,因此根据提示我们需要进行图片URL中转

image-20211120222419428.png

根据提示我们需要再次获取对应的SDK,这里我使用了Node.js的SDK进行URL中转,要特别注意SDK使用的语言是TypeScript而非JS,因此我们要在本地使用npm安装TypeScript和tsnode用于启动服务,正好学习一下TypeScript。

import ViapiUtil from '@alicloud/viapi-utils'
import axios from 'axios'
export default class Client {
 static async main(): Promise<string> {
  // 您的AccessKeyID
  let accessKeyId: string = 'LTAI5t76uKWM94qDWY3pjjXC'
  // 您的AccessKeySecret
  let accessKeySecret: string = 'WeXNHzPqApxLEdA3LMMM7WwLyTOujn'
  // 要上传的文件路径,url 或 filePath
  let fileUrl: string = 'https://gtms02.alicdn.com/tfs/TB1eYC7wi_1gK0jSZFqXXcpaXXa-2169-1074.png'
  //上传成功后,返回上传后的文件地址
  let fileLoadAddress: string = await ViapiUtil.upload(accessKeyId, accessKeySecret, fileUrl)
  // console.log(fileLoadAddress);
  return fileLoadAddress
 }
}

image-20211120222910385.png

最终我们成功获取到中转URL,很明显上面有了shanghai.aliyuncs的字样,说明成功了。

只欠东风?

回到最开始,我们也有了有效的图片URL,现在可以去调用服务了吧!

image-20211120223104659.png

根据预设的三个参数,使用GET请求,尝试获取数据:

无奈还是一直报错 invalidVersion

查阅错误集合文档和只能诊断,都无济于事。最后偶然看到了公共请求参数这一栏!!!

image-20211120223318454.png

原来是因为并不是只携带三个参数即可!实际上需要带上很多很多的和鉴权相关的参数,并且只能使用GET请求将参数作为查询字符串(也就是包裹在URL中)进行发送。

image-20211120223418391.png

最后通过后端同学调用生成签名和签名唯一随机数的SDK,生成各个配置必需的参数,最终才成功的发出了请求。

这个过程也拖累了我们前后端同学很久,最主要的原因是生成签名的时候需要传入调用服务的特定信息(如调用颜色识别需要传入对应的图片URL和colorCount作为生成签名的参数),如果遗漏了这一步,则会导致一直一直报HttpMethod错误。一定要避开!

附上最终完成调用获取到的参数(喜极而泣)

`{`
  `"RequestId": "8A4364B5-E0A9-56C8-8954-A553528462D2",`
  `"Data": {`
    `"ColorTemplateList": [`
      `{`
        `"Percentage": "0.237723",`
        `"Color": "E8C0B5",`
        `"Label": "red"`
      `},`
      `{`
        `"Percentage": "0.232763",`
        `"Color": "FBEEEC",`
        `"Label": "white"`
      `},`
      `{`
        `"Percentage": "0.207093",`
        `"Color": "8E6256",`
        `"Label": "red"`
      `},`
      `{`
        `"Percentage": "0.187128",`
        `"Color": "432929",`
        `"Label": "red"`
      `},`
      `{`
        `"Percentage": "0.135293",`
        `"Color": "EA897B",`
        `"Label": "red"`
      `}`
    `]`
  `}`
`}`