Modelo de demonstração: anotação de imagens com crowd-bounding-box - Amazon SageMaker

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Modelo de demonstração: anotação de imagens com crowd-bounding-box

Ao escolher usar um modelo personalizado como seu tipo de tarefa no console do Amazon SageMaker Ground Truth, você acessa o painel de tarefas de rotulagem personalizada. Ali, você pode escolher entre vários modelos básicos. Os modelos representam algumas das tarefas mais comuns e fornecem uma amostra a partir da qual você cria o modelo da tarefa de rotulagem personalizado. Se você não estiver usando o console ou como um recurso adicional, consulte Amazon SageMaker Ground Truth Sample Task UIs para obter um repositório de modelos de demonstração para uma variedade de tipos de tarefas de rotulagem.

Essa demonstração funciona com o BoundingBoxmodelo. A demonstração também funciona com as AWS Lambda funções necessárias para processar seus dados antes e depois da tarefa. No repositório do Github acima, para encontrar modelos que funcionem com AWS Lambda funções, procure {{ task.input.<property name> }} no modelo.

Modelo personalizado de caixa delimitadora inicial

Este é o modelo de caixa delimitadora inicial fornecido.

<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>

Os modelos personalizados usam a Linguagem de modelo Liquid, e cada um dos itens entre chaves duplas é uma variável. A AWS Lambda função de pré-anotação deve fornecer um objeto chamado taskInput e as propriedades desse objeto podem ser acessadas como {{ task.input.<property name> }} em seu modelo.

Seu próprio modelo personalizado de caixa delimitadora

Por exemplo, suponha que você tenha uma grande coleção de fotos de animais em que você conhece o tipo de animais na imagem por meio de um trabalho anterior de classificação de imagem. Agora você quer ter uma caixa delimitadora desenhada em torno dela.

Na amostra inicial, existem três variáveis: taskObject, header e labels.

Cada um deles seria representado em diferentes partes da caixa delimitadora.

  • taskObject é um URL HTTP(S) ou URI do S3 para a foto a ser anotada. O | grant_read_access adicionado é um filtro que converterá um URI do S3 em um HTTPS URL com acesso de curta duração a esse recurso. Se você estiver usando um URL HTTP(S), ele não será necessário.

  • header é o texto acima da foto a ser rotulado, algo como "Desenhe uma caixa ao redor do pássaro na foto".

  • labels é uma matriz, representada como ['item1', 'item2', ...]. Esses são rótulos que podem ser atribuídos pelo trabalhador às diferentes caixas que eles desenham. Você pode ter um ou muitos.

Cada um dos nomes de variáveis vem do objeto JSON na resposta do seu Lambda de pré-anotação. Os nomes acima são meramente sugeridos. Use qualquer nome de variável que faça sentido para você e favoreça a legibilidade do código na sua equipe.

Use apenas variáveis quando necessário

Se um campo não for alterado, você poderá remover essa variável do modelo e substituí-la por esse texto. Caso contrário, será necessário repetir esse texto como um valor em cada objeto no manifesto ou codificá-lo na função Lambda de pré-anotação.

exemplo : Modelo final de caixa delimitadora personalizada

Para manter as coisas simples, esse modelo terá uma variável, um rótulo e instruções muito básicas. Supondo que seu manifesto tenha uma propriedade "animal" em cada objeto de dados, esse valor pode ser reutilizado em duas partes do modelo.

<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>

Observe a reutilização de {{ task.input.animal }} em todo o modelo. Se o seu manifesto tivesse todos os nomes de animais começando com letra maiúscula, você poderia usar {{ task.input.animal | downcase }}, incorporando um dos filtros integrados do Liquid em frases que precisavam ser apresentadas em minúsculas.

Seu arquivo de manifesto

Seu arquivo de manifesto deve fornecer os valores das variáveis que você está usando em seu modelo. Você pode fazer uma certa transformação dos seus dados de manifesto no seu Lambda de pré-anotação, mas, se não precisar, mantenha um menor risco de erros e seu Lambda será executado mais rapidamente. Veja a seguir um exemplo de arquivo de manifesto para o modelo.

{"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"}

Sua função Lambda de pré-anotação

Como parte da configuração do trabalho, forneça o ARN de uma AWS Lambda função que pode ser chamada para processar suas entradas de manifesto e passá-las para o mecanismo de modelos.

Redação de sua função do Lambda

A melhor prática ao nomear sua função é usar um das quatro strings a seguir como parte do nome da função: SageMaker, Sagemaker, sagemaker, ou LabelingFunction. Isso se aplica às funções de pré-anotação e pós-anotação.

Ao usar o console, se você tiver funções do AWS Lambda pertencentes à sua conta, uma lista suspensa de funções que atendem aos requisitos de nomenclatura será fornecida para escolher uma.

Neste exemplo muito básico, você está apenas passando as informações do manifesto sem fazer nenhum processamento adicional nele. Esta função de pré-anotação de amostra é escrita para o Python 3.7.

import json def lambda_handler(event, context): return { "taskInput": event['dataObject'] }

O objeto JSON do seu manifesto será fornecido como filho do objeto event. As propriedades dentro do objeto taskInput estarão disponíveis como variáveis para o seu modelo, portanto, basta configurar o valor de taskInput para event['dataObject'] para passar todos os valores do seu objeto do manifesto para o seu modelo sem precisar copiá-los individualmente. Se você quiser enviar mais valores para o modelo, você pode adicioná-los ao objeto taskInput.

Sua função Lambda de pós-anotação

Como parte da configuração do trabalho, forneça o ARN de uma AWS Lambda função que pode ser chamada para processar os dados do formulário quando um trabalhador conclui uma tarefa. Isso pode ser tão simples ou complexo quanto você quiser. Se você quiser fazer uma consolidação de resposta e uma pontuação conforme a chegada, poderá aplicar os algoritmos de escore e/ou consolidação de sua escolha. Se quiser armazenar os dados brutos para processamento offline, essa é uma opção.

Fornecer permissões ao seu Lambda de pós-anotação

Os dados de anotação estarão em um arquivo designado pela string s3Uri no objeto payload. Para processar as anotações assim que elas chegarem, mesmo para uma simples função de repasse, você precisa atribuir ao S3ReadOnly acesso ao seu Lambda para que ele possa ler os arquivos de anotação.

Na página Console para a criação do seu Lambda, role até o painel Perfil de execução. Selecione Criar uma nova função a partir de um ou mais modelos. Dê um nome à função. Na lista suspensa Policy templates (Modelos de política), escolha Amazon S3 object read-only permissions (Permissões somente leitura do objeto Amazon S3). Salve o Lambda, e a função será salva e selecionada.

O exemplo a seguir está em 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

O Lambda de pós-anotação geralmente recebe lotes de resultados de tarefas no objeto de evento. Esse lote será o objeto payload que o Lambda deve percorrer. O que você retornará será um objeto que atende ao contrato de API.

A saída do seu trabalho de rotulagem

Você encontrará a saída da tarefa em uma pasta com o nome da sua tarefa de rotulagem no bucket do S3 de destino especificado. Ele estará em uma subpasta chamada manifests.

Para uma tarefa de caixa delimitadora, a saída que você encontrará no manifesto de saída será um pouco parecida com a demonstração abaixo. O exemplo foi limpo para impressão. A saída real será uma única linha por registro.

exemplo : JSON no manifesto de saída
{ "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" }

Observe como o atributo animal adicional do manifesto original é passado para o manifesto de saída no mesmo nível de source-ref e dos dados de rotulagem. Quaisquer propriedades de seu manifesto de entrada, usadas no seu modelo ou não, serão passadas para o manifesto de saída.