构建用于图像标签检测的无服务器应用程序
支持亚马逊云科技免费套餐
本教程中使用的示例代码来自 GitHub
Amazon Rekognition 这项服务可让您在应用程序中分析图像和视频。您可以识别对象、人物、文本、场景和活动,并检测不适当的内容。您还可以为用户验证和公共安全等各种不同使用场景进行面部分析、面部比较和面部搜索。Amazon Rekognition 基于深度学习技术构建,无需机器学习专业知识即可使用。它提供易于使用的 API,可以分析存储在 Amazon S3 中的任何图像或视频文件。
在本教程中,您将学习如何使用 Amazon Rekognition、Amazon Lambda 和 Go 编程语言构建用于图像标签检测的无服务器解决方案。标签是指以下任何一项:物体(花、树或桌子)、事件(婚礼、毕业典礼或生日派对)、概念(风景、夜晚和自然)或活动(下车)。例如,热带海滩上的人物照片可能包含棕榈树(对象)、海滩(场景)、跑步(动作)和户外(概念)等标签。
Rekognition 中的标签检测也适用于视频内容。但是,本教程重点介绍图像标签检测。
我们将介绍如何:
- 使用 Amazon CloudFormation 部署解决方案。
- 验证解决方案。
我们将使用以下 Go 库:
- 适用于 Go 的 Amazon Lambda。
- Amazon Go SDK,专门用于 Amazon Rekognition。
- Amazon CDK 的 Go 绑定,用于实现整个解决方案的“基础设施即代码”(IaC),并使用 Amazon Cloud Development Kit (CDK) CLI 进行部署。
应用程序概览
点击图片放大以下是该应用程序的工作原理:
- 上传至 Amazon S3 的图像会触发 Lambda 函数。
- Lambda 函数提取标签列表(包括其名称、类别和置信度)并将其保存至 Amazon DynamoDB 表中。
前提条件
在开始本教程之前,需要满足以下条件:
- 亚马逊云科技账户(如果您还没有,可以创建一个并在此处设置您的环境)。
- Go 编程语言(v1.18 或更高版本)。
- Amazon CDK。
- Amazon CLI。
- Git。
使用 Amazon CDK 来部署解决方案
克隆项目并切换到正确的目录:
git clone https://github.com/build-on-aws/amazon-rekognition-lambda-golang-example
cd amazon-rekognition-lambda-golang-example
Amazon Cloud Development Kit (Amazon CDK)是一个框架,可让您使用其支持的编程语言之一将云基础设施定义为代码,并通过 Amazon CloudFormation 进行预配。
要开始部署,只需调用 cdk deploy 并稍事等待。您会看到将要创建的资源列表,您确认之后流程才能继续。
cd cdk
cdk deploy
# output
Bundling asset RekognitionLabelDetectionGolangStack/rekognition-function/Code/Stage...
✨ Synthesis time: 5.44
//.... omitted
Do you wish to deploy these changes (y/n)? y
输入 y 开始创建应用程序所需的亚马逊云科技资源。
如果您想查看将在后台使用的 Amazon CloudFormation 模板,请运行 cdk synth 并检查 cdk.out 文件夹
您可以在终端中跟踪堆栈创建进度,也可以导航至亚马逊云科技控制台:CloudFormation > Stacks > RekognitionLabelDetectionGolangStack。
创建的资源:
- 一个 S3 存储桶 - 用于上传图像的源存储桶。
- 一个 Amazon Lambda 函数,用于使用 Amazon Rekognition 提取图像标签。
- 一张 DynamoDB 表,用于存储每个图像的标签数据。
- 以及其他一些资源(如 IAM 角色等)
您还将在终端中看到以下输出(您看到的资源名称将有所不同)。在本例中,以下是 CDK 创建的 S3 存储桶的名称:
✅ RekognitionLabelDetectionGolangStack
✨ Deployment time: 119.56s
Outputs:
RekognitionLabelDetectionGolangStack.abeldetectionoutputtablename = rekognitionlabeldetectio-labeldetectioninputbucke-v3vn9o06q3kb_labels_output
RekognitionLabelDetectionGolangStack.labeldetectioninputbucketname = rekognitionlabeldetectio-labeldetectioninputbucke-v3vn9o06q3kb
现在,您已准备好验证解决方案。
从图像中提取标签
验证该解决方案时,可以使用自己的图像,也可以使用 GitHub 存储库中提供的示例文件。我将使用 Amazon CLI 上传文件,但您也可以使用亚马逊云科技控制台。
export SOURCE_BUCKET=<enter source S3 bucket name - check the CDK output>
aws s3 cp ./car.png s3://$SOURCE_BUCKET
# verify that the file was uploaded
aws s3 ls s3://$SOURCE_BUCKET
此 Lambda 函数将从图像中提取标签并将其存储在 DynamoDB 表中。
再上传一个文件:
export SOURCE_BUCKET=<enter source S3 bucket name - check the CDK output>
aws s3 cp ./skate.png s3://$SOURCE_BUCKET
在亚马逊云科技控制台中查看 DynamoDB 表 - 您应该会看到两个图像的标签检测结果。
DynamoDB 按照表的设计,source_file(源文件名)为分区键,而(检测到的)label_name(标签名称)为排序键。所以我们可以有以下的查询模式:
- 您可以获取给定图像的所有标签。
- 您可以查询给定源图像及其标签的元数据(类别和置信度)。
您可以使用 Amazon CLI 查询 DynamoDB 表:
aws dynamodb scan --table-name <enter table name - check the CDK output>
您已经验证了端到端解决方案,现在可以清除资源,探索 Lambda 函数逻辑。
清理资源
完成后,只需使用以下命令删除所有服务:
cdk destroy
#output prompt (choose 'y' to continue)
Are you sure you want to delete: RekognitionLabelDetectionGolangStack (y/n)?
Lambda 函数代码详细讲解
这是对 Lambda 函数逻辑的概述。请注意,为了简洁起见,此处省略了一些代码(错误处理、日志记录等),因为我们只想关注重要的部分。
func handler(ctx context.Context, s3Event events.S3Event) {
for _, record := range s3Event.Records {
sourceBucketName := record.S3.Bucket.Name
fileName := record.S3.Object.Key
err := labelDetection(sourceBucketName, fileName)
}
}
Lambda 函数触发的条件是有新图像上传至源存储桶。该函数遍历文件列表,并为每个图像调用 labelDetection 函数。
我们来仔细研究一下 labelDetection 函数。
func labelDetection(sourceBucketName, fileName string) error {
resp, err := rekognitionClient.DetectLabels(context.Background(), &rekognition.DetectLabelsInput{
Image: &types.Image{
S3Object: &types.S3Object{
Bucket: aws.String(sourceBucketName),
Name: aws.String(fileName),
},
},
})
for _, label := range resp.Labels {
item := make(map[string]ddbTypes.AttributeValue)
item["source_file"] = &ddbTypes.AttributeValueMemberS{Value: fileName}
item["label_name"] = &ddbTypes.AttributeValueMemberS{Value: *label.Name}
item["label_category"] = &ddbTypes.AttributeValueMemberS{Value: *label.Categories[0].Name}
item["label_confidence"] = &ddbTypes.AttributeValueMemberN{Value: fmt.Sprintf("%v", aws.ToFloat32(label.Confidence))}
_, err := dynamodbClient.PutItem(context.Background(), &dynamodb.PutItemInput{
TableName: aws.String(table),
Item: item,
})
}
return nil
}
- labelDetection 函数使用 Amazon Rekognition DetectLabels API 返回标签列表。
- 然后,该函数遍历每个标签,并将标签名称、类别和置信度分数存储在 DynamoDB 表中。