本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
演示模板:使用 crowd-bounding-box
的映像注释
当您在 Amazon G SageMaker round Truth 控制台中选择使用自定义模板作为任务类型时,您将进入自定义标签任务面板。在该面板中,您可以从多个基本模板中进行选择。模板表示一些最常见的任务,并在您创建自定义标注任务的模板时提供样本。如果您没有使用控制台,或者作为其他补救措施,请参阅 Amazon SageMaker AI Ground Truth 示例任务 UIs
此演示适用于BoundingBox模板。该演示还适用于在任务之前和之后处理数据所需的 AWS Lambda 函数。在上面的 Github 存储库中,要查找与 AWS Lambda 函数配合使用的模板,请在模板{{ task.input.
中查找。<property
name>
}}
入门边界框自定义模板
这是所提供的入门边界框模板。
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script> <crowd-form> <crowd-bounding-box name="boundingBox" src="{{ task.input.taskObject | grant_read_access }}" header="{{ task.input.header }}" labels="{{ task.input.labels | to_json | escape }}" > <!-- The <full-instructions> tag is where you will define the full instructions of your task. --> <full-instructions header="Bounding Box Instructions" > <p>Use the bounding box tool to draw boxes around the requested target of interest:</p> <ol> <li>Draw a rectangle using your mouse over each instance of the target.</li> <li>Make sure the box does not cut into the target, leave a 2 - 3 pixel margin</li> <li> When targets are overlapping, draw a box around each object, include all contiguous parts of the target in the box. Do not include parts that are completely overlapped by another object. </li> <li> Do not include parts of the target that cannot be seen, even though you think you can interpolate the whole shape of the target. </li> <li>Avoid shadows, they're not considered as a part of the target.</li> <li>If the target goes off the screen, label up to the edge of the image.</li> </ol> </full-instructions> <!-- The <short-instructions> tag allows you to specify instructions that are displayed in the left hand side of the task interface. It is a best practice to provide good and bad examples in this section for quick reference. --> <short-instructions> Use the bounding box tool to draw boxes around the requested target of interest. </short-instructions> </crowd-bounding-box> </crowd-form>
此自定义模板使用 Liquid 模板语言taskInput
并且可以像在模板{{
task.input.<property name> }}
中一样访问该对象的属性。
您自己的边界框自定义模板
举例来说,假设您有大量的动物照片,您可以通过之前的图像分类作业知道图像中的动物种类。现在,您希望在其周围绘制一个边界框。
在入门示例中,有三个变量:taskObject
、header
和 labels
。
其中每个变量都表示在边界框的不同部分中。
taskObject
是要注释的照片的 HTTP(S) URL 或 S3 URI。添加的| grant_read_access
是一种筛选器,可将 S3 URI 转换为具有对该资源的短暂访问权限的 HTTPS URL。如果您使用的是 HTTP(S) URL,则不需要该筛选器。header
是照片上方要标注的文本,如“在照片中的鸟周围画一个框”。labels
是一个数组,表示为['item1', 'item2', ...]
。这些标签可以由工作人员分配给他们绘制的不同边界框。您可以有一个或多个标签。
每个变量的名称都来自于注释前 Lambda 响应中的 JSON 对象,上述名称只是建议性的,请使用任何对您有意义的变量名,这样可以提高团队的代码可读性。
仅在必要时才使用变量
如果某个字段不会改变,可以从模板中删除该变量并用该文本替换,否则就必须在清单中的每个对象中重复该文本作为值,或者将其编码到注释前 Lambda 函数中。
例 :最终的自定义边界框模板
为简单起见,此模板将具有一个变量、一个标签和非常基本的说明。假设您的清单中每个数据对象都有一个“animal”属性,那么这个值就可以在模板的两个部分中重复使用。
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script> <crowd-form> <crowd-bounding-box name="boundingBox" labels="[ '{{ task.input.animal }}' ]" src="{{ task.input.source-ref | grant_read_access }}" header="Draw a box around the {{ task.input.animal }}." > <full-instructions header="Bounding Box Instructions" > <p>Draw a bounding box around the {{ task.input.animal }} in the image. If there is more than one {{ task.input.animal }} per image, draw a bounding box around the largest one.</p> <p>The box should be tight around the {{ task.input.animal }} with no more than a couple of pixels of buffer around the edges.</p> <p>If the image does not contain a {{ task.input.animal }}, check the <strong> Nothing to label</strong> box. </full-instructions> <short-instructions> <p>Draw a bounding box around the {{ task.input.animal }} in each image. If there is more than one {{ task.input.animal }} per image, draw a bounding box around the largest one.</p> </short-instructions> </crowd-bounding-box> </crowd-form>
注意在整个模板中重复使用 {{ task.input.animal }}
。如果您的清单中所有动物名称都以大写字母开头,您可以使用 {{ task.input.animal | downcase }}
,在需要小写的句子中加入 Liquid 的内置筛选器之一。
您的清单文件
您的清单文件应提供您在模板中使用的变量值。您可以在注释前 Lambda 中对清单数据进行一些转换,但如果您不需要这样做,就可以保持较低的出错风险,而且 Lambda 运行速度也会更快。下面是模板的清单文件示例。
{"source-ref": "<S3 image URI>", "animal": "horse"} {"source-ref": "<S3 image URI>", "animal" : "bird"} {"source-ref": "<S3 image URI>", "animal" : "dog"} {"source-ref": "<S3 image URI>", "animal" : "cat"}
注释前 Lambda 函数
作为任务设置的一部分,请提供一个 AWS Lambda 函数的 ARN,该函数可用于处理清单条目并将其传递给模板引擎。
命名 Lambda 函数
命名函数的最佳实践是使用以下四个字符串之一作为函数名称的一部分:SageMaker
、Sagemaker
、sagemaker
或 LabelingFunction
。这同时适用于注释前函数和注释后函数。
使用控制台时,如果您的账户拥有的 AWS Lambda 函数,则系统将提供符合命名要求的函数下拉列表供您选择。
在这个非常基本的示例中,您只是传递来自清单的信息,而不对其进行任何额外的处理。这个注释前函数示例是为 Python 3.7 编写的。
import json def lambda_handler(event, context): return { "taskInput": event['dataObject'] }
来自清单的 JSON 对象将作为 event
对象的子对象提供。taskInput
对象内部的属性将作为变量提供给模板,因此只需将 taskInput
的值设置为 event['dataObject']
即可将清单对象中的所有值传递给模板,而无需单独复制它们。如果您希望向模板发送更多的值,可以将这些值添加到 taskInput
对象中。
注释后 Lambda 函数
作为作业设置的一部分,提供一个 AWS Lambda 函数的 ARN,当工作人员完成任务时,可以调用该函数来处理表单数据。这可以很简单,也可以很复杂。如果您想对收到的答案进行合并和评分,您可以应用自己选择的评分和/或合并算法。如果您想要存储原始数据以进行脱机处理,则这是一个选项。
提供对注释后 Lambda 的权限
注释数据将位于一个文件中,该文件由 payload
对象中的 s3Uri
字符串指定。要处理传入的注释,即使是简单的传递函数,也需要为 Lambda 分配 S3ReadOnly
访问权限,以使其能够读取注释文件。
在创建 Lambda 的控制台页面中,滚动到执行角色面板。选择从一个或多个模板中创建新角色。指定角色的名称。从策略模板下拉列表中,选择 Amazon S3 对象只读权限。保存 Lambda,将保存并选择该角色。
下面是 Python 2.7 中的示例。
import json import boto3 from urlparse import urlparse def lambda_handler(event, context): consolidated_labels = [] parsed_url = urlparse(event['payload']['s3Uri']); s3 = boto3.client('s3') textFile = s3.get_object(Bucket = parsed_url.netloc, Key = parsed_url.path[1:]) filecont = textFile['Body'].read() annotations = json.loads(filecont); for dataset in annotations: for annotation in dataset['annotations']: new_annotation = json.loads(annotation['annotationData']['content']) label = { 'datasetObjectId': dataset['datasetObjectId'], 'consolidatedAnnotation' : { 'content': { event['labelAttributeName']: { 'workerId': annotation['workerId'], 'boxesInfo': new_annotation, 'imageSource': dataset['dataObject'] } } } } consolidated_labels.append(label) return consolidated_labels
注释后 Lambda 通常会在事件对象中接收成批的任务结果。该批次将是 Lambda 应该遍历的 payload
对象。您发回的将是一个符合 API 合约的对象。
标注作业的输出
您将在指定的目标 S3 存储桶中以标注作业命名的文件夹中找到作业的输出。它将位于名为 manifests
的子文件夹中。
对于边界框任务,您在输出清单找到的输出将有点类似于下面的演示。该示例已清理以供打印。实际输出将是每条记录一行。
例 :输出清单中的 JSON
{ "source-ref":"<URL>", "<
label attribute name
>": { "workerId":"<URL>", "imageSource":"<image URL>", "boxesInfo":"{\"boundingBox\":{\"boundingBoxes\":[{\"height\":878, \"label\":\"bird\", \"left\":208, \"top\":6, \"width\":809}], \"inputImageProperties\":{\"height\":924, \"width\":1280}}}"}, "<label attribute name
>-metadata": { "type":"groundTruth/custom", "job_name":"<Labeling job name>", "human-annotated":"yes" }, "animal" : "bird" }
请注意原始清单中的 animal
附加属性是如何与 source-ref
和标注数据同级传递到输出清单的。输入清单中的任何属性,无论是否在模板中使用,都将传递到输出清单中。