

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将其他数据集格式转换为清单文件
<a name="md-converting-to-sm-format"></a>

您可以使用以下信息从各种源数据集格式创建 SageMaker Amazon AI 格式的清单文件。创建清单文件后，即可使用它来创建数据集。有关更多信息，请参阅 [使用清单文件导入图像](md-create-dataset-ground-truth.md)。

**Topics**
+ [将 COCO 数据集转换为清单文件格式](md-transform-coco.md)
+ [转换多标签 SageMaker AI Ground Truth 清单文件](md-gt-cl-transform.md)
+ [从 CSV 文件创建清单文件](ex-csv-manifest.md)

# 将 COCO 数据集转换为清单文件格式
<a name="md-transform-coco"></a>

[COCO](http://cocodataset.org/#home) 是一种用于指定大规模物体检测、分段和字幕数据集的格式。此 Python [示例](md-coco-transform-example.md)说明了如何将 COCO 物体检测格式的数据集转换为 Amazon Rekognition Custom Labels [边界框格式的清单文件](md-create-manifest-file-object-detection.md)。本部分还提供了可用于编写自己的代码的信息。

COCO 格式的 JSON 文件由五个部分组成，提供了*整个数据集*的信息。有关更多信息，请参阅 [COCO 数据集格式](md-coco-overview.md)。
+ `info`：有关数据集的一般信息。
+ `licenses `：数据集中图像的许可信息。
+ [`images`](md-coco-overview.md#md-coco-images)：数据集中图像的列表。
+ [`annotations`](md-coco-overview.md#md-coco-annotations)：数据集中所有图像中存在的注释（包括边界框）的列表。
+ [`categories`](md-coco-overview.md#md-coco-categories)：标签类别列表。

您需要来自 `images`、`annotations` 和 `categories` 列表的信息，才能创建 Amazon Rekognition Custom Labels 清单文件。

Amazon Rekognition Custom Labels 清单文件采用 JSON 行格式，其中每行都包含了*一张图像上*的一个或多个物体的边界框和标签信息。有关更多信息，请参阅 [清单文件中的物体定位](md-create-manifest-file-object-detection.md)。

## 将 COCO 对象映射到自定义标签 JSON 行
<a name="md-mapping-coco"></a>

要转换 COCO 格式的数据集，需要将 COCO 数据集映射到 Amazon Rekognition Custom Labels 清单文件以进行物体定位。有关更多信息，请参阅 [清单文件中的物体定位](md-create-manifest-file-object-detection.md)。要为每张图片构建 JSON 行，清单文件需要映射 COCO 数据集`image`和`category`对象字段 IDs。`annotation`

下面是一个 COCO 清单文件示例。有关更多信息，请参阅 [COCO 数据集格式](md-coco-overview.md)。

```
{
    "info": {
        "description": "COCO 2017 Dataset","url": "http://cocodataset.org","version": "1.0","year": 2017,"contributor": "COCO Consortium","date_created": "2017/09/01"
    },
    "licenses": [
        {"url": "http://creativecommons.org/licenses/by/2.0/","id": 4,"name": "Attribution License"}
    ],
    "images": [
        {"id": 242287, "license": 4, "coco_url": "http://images.cocodataset.org/val2017/xxxxxxxxxxxx.jpg", "flickr_url": "http://farm3.staticflickr.com/2626/xxxxxxxxxxxx.jpg", "width": 426, "height": 640, "file_name": "xxxxxxxxx.jpg", "date_captured": "2013-11-15 02:41:42"},
        {"id": 245915, "license": 4, "coco_url": "http://images.cocodataset.org/val2017/nnnnnnnnnnnn.jpg", "flickr_url": "http://farm1.staticflickr.com/88/xxxxxxxxxxxx.jpg", "width": 640, "height": 480, "file_name": "nnnnnnnnnn.jpg", "date_captured": "2013-11-18 02:53:27"}
    ],
    "annotations": [
        {"id": 125686, "category_id": 0, "iscrowd": 0, "segmentation": [[164.81, 417.51,......167.55, 410.64]], "image_id": 242287, "area": 42061.80340000001, "bbox": [19.23, 383.18, 314.5, 244.46]},
        {"id": 1409619, "category_id": 0, "iscrowd": 0, "segmentation": [[376.81, 238.8,........382.74, 241.17]], "image_id": 245915, "area": 3556.2197000000015, "bbox": [399, 251, 155, 101]},
        {"id": 1410165, "category_id": 1, "iscrowd": 0, "segmentation": [[486.34, 239.01,..........495.95, 244.39]], "image_id": 245915, "area": 1775.8932499999994, "bbox": [86, 65, 220, 334]}
    ],
    "categories": [
        {"supercategory": "speaker","id": 0,"name": "echo"},
        {"supercategory": "speaker","id": 1,"name": "echo dot"}
    ]
}
```

下图显示了*数据集*的 COCO 数据集列表如何映射到图像的 Amazon Rekognition Custom Labels JSON 行。图像的每个 JSON 行都有一个 source-ref、作业和作业元数据字段。匹配的颜色表示单张图像的信息。请注意，在清单中，一张图像可能有多个注释和元数据/类别。

![\[图中显示 COCO 清单的结构，其中包含图像、注释和类别。\]](http://docs.aws.amazon.com/zh_cn/rekognition/latest/customlabels-dg/images/coco-transform.png)


**获取单个 JSON 行的 COCO 对象**

1. 对于图像列表中的每张图像，从注释列表中获取注释，其中注释字段 `image_id` 的值与图像 `id` 字段匹配。

1. 对于步骤 1 中匹配的每个注释，请通读 `categories` 列表并获取 `category` 字段 `id` 的值与 `annotation` 对象 `category_id` 字段匹配的每个 `category`。

1. 使用匹配的 `image`、`annotation` 和 `category` 对象为图像创建 JSON 行。要映射字段，请参阅[将 COCO 对象字段映射到自定义标签 JSON 行对象字段](#md-mapping-fields-coco)。

1. 重复步骤 1-3，直到为 `image` 列表中的每个 `images` 对象创建 JSON 行。

有关示例代码，请参阅[转换 COCO 数据集](md-coco-transform-example.md)。

## 将 COCO 对象字段映射到自定义标签 JSON 行对象字段
<a name="md-mapping-fields-coco"></a>

确定 Amazon Rekognition Custom Labels JSON 行的 COCO 对象后，需要将 COCO 对象字段映射到相应的 Amazon Rekognition Custom Labels JSON 行对象字段。以下示例 Amazon Rekognition Custom Labels JSON 行将一张图像 (`id`=`000000245915`) 映射到上面的 COCO JSON 示例。请注意以下信息。
+ `source-ref` 是图像在 Amazon S3 存储桶中的位置。如果 COCO 图像不是存储在 Amazon S3 存储桶中，则需要将它们移到 Amazon S3 存储桶中。
+ `annotations` 列表中包含了图像上每个物体的 `annotation` 对象。`annotation` 对象包含边界框信息（`top`、`left`、`width`、`height`）和标签标识符 (`class_id`)。
+ 标签标识符 (`class_id`) 映射到元数据中的 `class-map` 列表。该列表会列出图像上使用的标签。

```
{
	"source-ref": "s3://custom-labels-bucket/images/000000245915.jpg",
	"bounding-box": {
		"image_size": {
			"width": 640,
			"height": 480,
			"depth": 3
		},
		"annotations": [{
			"class_id": 0,
			"top": 251,
			"left": 399,
			"width": 155,
			"height": 101
		}, {
			"class_id": 1,
			"top": 65,
			"left": 86,
			"width": 220,
			"height": 334
		}]
	},
	"bounding-box-metadata": {
		"objects": [{
			"confidence": 1
		}, {
			"confidence": 1
		}],
		"class-map": {
			"0": "Echo",
			"1": "Echo Dot"
		},
		"type": "groundtruth/object-detection",
		"human-annotated": "yes",
		"creation-date": "2018-10-18T22:18:13.527256",
		"job-name": "my job"
	}
}
```

按照以下信息将 Amazon Rekognition Custom Labels 清单文件字段映射到 COCO 数据集 JSON 字段。

### source-ref
<a name="md-source-ref-coco"></a>

图像位置的 S3 格式 URL。该图像必须存储在 S3 存储桶中。有关更多信息，请参阅 [source-ref](md-create-manifest-file-object-detection.md#cd-manifest-source-ref)。如果 `coco_url` COCO 字段指向 S3 存储桶位置，则可以使用 `coco_url` 的值作为 `source-ref` 的值。或者，也可以将 `source-ref` 映射到 `file_name` (COCO) 字段，然后在转换代码中将所需的 S3 路径添加到图像的存储位置。

### *bounding-box*
<a name="md-label-attribute-id-coco"></a>

您选择的标签属性名称。有关更多信息，请参阅 [*bounding-box*](md-create-manifest-file-object-detection.md#md-manifest-source-bounding-box)。

#### image\$1size
<a name="md-image-size-coco"></a>

图像大小（以像素为单位）。映射到 [images](md-coco-overview.md#md-coco-images) 列表中的 `image` 对象。
+ `height`-> `image.height`
+ `width`-> `image.width`
+ `depth`：Amazon Rekognition Custom Labels 未使用该属性，但必须为其提供一个值。

#### annotations
<a name="md-annotations-coco"></a>

`annotation` 对象的列表。图像上的每个物体都有一个 `annotation`。

#### annotation
<a name="md-annotation-coco"></a>

包含图像上物体的一个实例的边界框信息。
+ `class_id`：映射到自定义标签的 `class-map` 列表的数字 ID。
+ `top` -> `bbox[1]`
+ `left` -> `bbox[0]`
+ `width` -> `bbox[2]`
+ `height` -> `bbox[3]`

### *bounding-box*-元数据
<a name="md-metadata-coco"></a>

标签属性的元数据。包含标签和标签标识符。有关更多信息，请参阅 [*bounding-box*-元数据](md-create-manifest-file-object-detection.md#md-manifest-source-bounding-box-metadata)。

#### Objects
<a name="cd-metadata-objects-coco"></a>

图像中的物体数组。按索引映射到 `annotations` 列表。

##### Object
<a name="cd-metadata-object-coco"></a>
+ Amazon Rekognition Custom Labels 未使用该属性，但必须为其指定值 (1)。

#### class-map
<a name="md-metadata-class-map-coco"></a>

适用于图像中检测到的物体的标签（类别）映射。映射到 [categories](md-coco-overview.md#md-coco-categories) 列表中的 category 对象。
+ `id` -> `category.id`
+ `id value` -> `category.name`

#### 类型
<a name="md-type-coco"></a>

必须是 `groundtruth/object-detection`

#### human-annotated
<a name="md-human-annotated-coco"></a>

指定 `yes` 或 `no`。有关更多信息，请参阅 [*bounding-box*-元数据](md-create-manifest-file-object-detection.md#md-manifest-source-bounding-box-metadata)。

#### creation-date -> [image](md-coco-overview.md#md-coco-images).date\$1captured
<a name="md-creation-date-coco"></a>

图像的创建日期和时间。映射到 COCO 图像列表中的图像的 [image](md-coco-overview.md#md-coco-images).date\$1captured 字段。Amazon Rekognition Custom Labels 期望的 `creation-date` 格式为 *Y-M-DTH:M:S*。

#### job-name
<a name="md-job-name-coco"></a>

您选择的作业名称。

# COCO 数据集格式
<a name="md-coco-overview"></a>

COCO 数据集由五个信息部分组成，提供了整个数据集的信息。COCO 物体检测数据集的格式记录在 [COCO 数据格式](http://cocodataset.org/#format-data)中。
+ info：有关数据集的一般信息。
+ licenses：数据集中图像的许可信息。
+ [images](#md-coco-images)：数据集中图像的列表。
+ [annotations](#md-coco-annotations)：数据集中所有图像中存在的注释（包括边界框）的列表。
+ [categories](#md-coco-categories)：标签类别列表。

要创建自定义标签清单，需要使用 COCO 清单文件中的 `images`、`annotations` 和 `categories` 列表。其他两个部分（`info`、`licences`）不是必需的。下面是一个 COCO 清单文件示例。

```
{
    "info": {
        "description": "COCO 2017 Dataset","url": "http://cocodataset.org","version": "1.0","year": 2017,"contributor": "COCO Consortium","date_created": "2017/09/01"
    },
    "licenses": [
        {"url": "http://creativecommons.org/licenses/by/2.0/","id": 4,"name": "Attribution License"}
    ],
    "images": [
        {"id": 242287, "license": 4, "coco_url": "http://images.cocodataset.org/val2017/xxxxxxxxxxxx.jpg", "flickr_url": "http://farm3.staticflickr.com/2626/xxxxxxxxxxxx.jpg", "width": 426, "height": 640, "file_name": "xxxxxxxxx.jpg", "date_captured": "2013-11-15 02:41:42"},
        {"id": 245915, "license": 4, "coco_url": "http://images.cocodataset.org/val2017/nnnnnnnnnnnn.jpg", "flickr_url": "http://farm1.staticflickr.com/88/xxxxxxxxxxxx.jpg", "width": 640, "height": 480, "file_name": "nnnnnnnnnn.jpg", "date_captured": "2013-11-18 02:53:27"}
    ],
    "annotations": [
        {"id": 125686, "category_id": 0, "iscrowd": 0, "segmentation": [[164.81, 417.51,......167.55, 410.64]], "image_id": 242287, "area": 42061.80340000001, "bbox": [19.23, 383.18, 314.5, 244.46]},
        {"id": 1409619, "category_id": 0, "iscrowd": 0, "segmentation": [[376.81, 238.8,........382.74, 241.17]], "image_id": 245915, "area": 3556.2197000000015, "bbox": [399, 251, 155, 101]},
        {"id": 1410165, "category_id": 1, "iscrowd": 0, "segmentation": [[486.34, 239.01,..........495.95, 244.39]], "image_id": 245915, "area": 1775.8932499999994, "bbox": [86, 65, 220, 334]}
    ],
    "categories": [
        {"supercategory": "speaker","id": 0,"name": "echo"},
        {"supercategory": "speaker","id": 1,"name": "echo dot"}
    ]
}
```

## 图像列表
<a name="md-coco-images"></a>

COCO 数据集引用的图像列在图像数组中。每个图像对象都包含了有关该图像的信息，例如图像文件名。在以下示例图像对象中，请注意以下信息以及创建 Amazon Rekognition Custom Labels 清单文件需要哪些字段。
+ `id`：（必需）图像的唯一标识符。`id` 字段映射到注释数组（存储边界框信息的地方）中的 `id` 字段。
+ `license`：（非必需）映射到许可证数组。
+ `coco_url`：（可选）图像的位置。
+ `flickr_url`：（非必需）图像在 Flickr 上的位置。
+ `width`：（必需）图像的宽度。
+ `height`：（必需）图像的高度。
+ `file_name`：（必需）图像文件名。在本示例中，`file_name` 与 `id` 匹配，但 COCO 数据集对此不作要求。
+ `date_captured`：（必需）图像拍摄的日期和时间。

```
{
    "id": 245915,
    "license": 4,
    "coco_url": "http://images.cocodataset.org/val2017/nnnnnnnnnnnn.jpg",
    "flickr_url": "http://farm1.staticflickr.com/88/nnnnnnnnnnnnnnnnnnn.jpg",
    "width": 640,
    "height": 480,
    "file_name": "000000245915.jpg",
    "date_captured": "2013-11-18 02:53:27"
}
```

## 注释（边界框）列表
<a name="md-coco-annotations"></a>

所有图像上的所有物体的边界框信息都存储在注释列表中。单个注释对象包含单个物体的边界框信息以及该物体在图像上的标签。图像上物体的每个实例都有一个注释对象。

在以下示例中，请注意以下信息以及创建 Amazon Rekognition Custom Labels 清单文件需要哪些字段。
+ `id`：（非必需）注释的标识符。
+ `image_id`：（必需）对应于图像数组中的图像 `id`。
+ `category_id`：（必需）用于标识边界框内物体的标签的标识符。它映射到类别数组的 `id` 字段。
+ `iscrowd`：（非必需）指定图像中是否包含物体群。
+ `segmentation`：（非必需）图像中物体的分段信息。Amazon Rekognition Custom Labels 不支持分段。
+ `area`：（非必需）注释的区域。
+ `bbox`：（必需）包含图像中物体的边界框的坐标（以像素为单位）。

```
{
    "id": 1409619,
    "category_id": 1,
    "iscrowd": 0,
    "segmentation": [
        [86.0, 238.8,..........382.74, 241.17]
    ],
    "image_id": 245915,
    "area": 3556.2197000000015,
    "bbox": [86, 65, 220, 334]
}
```

## 类别列表
<a name="md-coco-categories"></a>

标签信息存储在类别数组中。在以下示例类别对象中，请注意以下信息以及创建 Amazon Rekognition Custom Labels 清单文件需要哪些字段。
+ `supercategory`：（非必需）标签的父类别。
+ `id`：（必需）标签标识符。`id` 字段映射到 `annotation` 对象中的 `category_id` 字段。在以下示例中，echo dot 的标识符为 2。
+ `name`：（必需）标签名称。

```
        {"supercategory": "speaker","id": 2,"name": "echo dot"}
```

# 转换 COCO 数据集
<a name="md-coco-transform-example"></a>

使用以下 Python 示例将边界框信息从 COCO 格式的数据集转换为 Amazon Rekognition Custom Labels 清单文件。该代码会将创建的清单文件上载到您的 Amazon S3 存储桶。该代码还提供了一个 AWS CLI 命令，您可以使用该命令上传您的图像。

**转换 COCO 数据集 (SDK)**

1. 如果您尚未执行以下操作，请：

   1. 确保您具有 `AmazonS3FullAccess` 权限。有关更多信息，请参阅 [设置 SDK 权限](su-sdk-permissions.md)。

   1. 安装并配置 AWS CLI 和 AWS SDKs。有关更多信息，请参阅 [步骤 4：设置 AWS CLI 和 AWS SDKs](su-awscli-sdk.md)。

1. 使用以下 Python 代码转换 COCO 数据集。设置以下值。
   + `s3_bucket`：要在其中存储图像和 Amazon Rekognition Custom Labels 清单文件的 S3 存储桶的名称。
   + `s3_key_path_images`：S3 存储桶 (`s3_bucket`) 中将要放置图像的位置的路径。
   + `s3_key_path_manifest_file`：S3 存储桶 (`s3_bucket`) 中将要放置自定义标签清单文件的位置的路径。
   + `local_path`：示例打开输入 COCO 数据集并保存新的自定义标签清单文件的位置的本地路径。
   + `local_images_path`：要用于训练的图像的本地路径。
   + `coco_manifest`：输入 COCO 数据集的文件名。
   + `cl_manifest_file`：该示例创建的清单文件的名称。该文件保存在 `local_path` 指定的位置。按照惯例，该文件具有扩展名 `.manifest`，但这不是必需要求的。
   + `job_name`：自定义标签作业的名称。

   ```
   import json
   import os
   import random
   import shutil
   import datetime
   import botocore
   import boto3
   import PIL.Image as Image
   import io
   
   #S3 location for images
   s3_bucket = 'bucket'
   s3_key_path_manifest_file = 'path to custom labels manifest file/'
   s3_key_path_images = 'path to images/'
   s3_path='s3://' + s3_bucket  + '/' + s3_key_path_images
   s3 = boto3.resource('s3')
   
   #Local file information
   local_path='path to input COCO dataset and output Custom Labels manifest/'
   local_images_path='path to COCO images/'
   coco_manifest = 'COCO dataset JSON file name'
   coco_json_file = local_path + coco_manifest
   job_name='Custom Labels job name'
   cl_manifest_file = 'custom_labels.manifest'
   
   label_attribute ='bounding-box'
   
   open(local_path + cl_manifest_file, 'w').close()
   
   # class representing a Custom Label JSON line for an image
   class cl_json_line:  
       def __init__(self,job, img):  
   
           #Get image info. Annotations are dealt with seperately
           sizes=[]
           image_size={}
           image_size["width"] = img["width"]
           image_size["depth"] = 3
           image_size["height"] = img["height"]
           sizes.append(image_size)
   
           bounding_box={}
           bounding_box["annotations"] = []
           bounding_box["image_size"] = sizes
   
           self.__dict__["source-ref"] = s3_path + img['file_name']
           self.__dict__[job] = bounding_box
   
           #get metadata
           metadata = {}
           metadata['job-name'] = job_name
           metadata['class-map'] = {}
           metadata['human-annotated']='yes'
           metadata['objects'] = [] 
           date_time_obj = datetime.datetime.strptime(img['date_captured'], '%Y-%m-%d %H:%M:%S')
           metadata['creation-date']= date_time_obj.strftime('%Y-%m-%dT%H:%M:%S') 
           metadata['type']='groundtruth/object-detection'
           
           self.__dict__[job + '-metadata'] = metadata
   
   
   print("Getting image, annotations, and categories from COCO file...")
   
   with open(coco_json_file) as f:
   
       #Get custom label compatible info    
       js = json.load(f)
       images = js['images']
       categories = js['categories']
       annotations = js['annotations']
   
       print('Images: ' + str(len(images)))
       print('annotations: ' + str(len(annotations)))
       print('categories: ' + str(len (categories)))
   
   
   print("Creating CL JSON lines...")
       
   images_dict = {image['id']: cl_json_line(label_attribute, image) for image in images}
   
   print('Parsing annotations...')
   for annotation in annotations:
   
       image=images_dict[annotation['image_id']]
   
       cl_annotation = {}
       cl_class_map={}
   
       # get bounding box information
       cl_bounding_box={}
       cl_bounding_box['left'] = annotation['bbox'][0]
       cl_bounding_box['top'] = annotation['bbox'][1]
    
       cl_bounding_box['width'] = annotation['bbox'][2]
       cl_bounding_box['height'] = annotation['bbox'][3]
       cl_bounding_box['class_id'] = annotation['category_id']
   
       getattr(image, label_attribute)['annotations'].append(cl_bounding_box)
   
   
       for category in categories:
            if annotation['category_id'] == category['id']:
               getattr(image, label_attribute + '-metadata')['class-map'][category['id']]=category['name']
           
       
       cl_object={}
       cl_object['confidence'] = int(1)  #not currently used by Custom Labels
       getattr(image, label_attribute + '-metadata')['objects'].append(cl_object)
   
   print('Done parsing annotations')
   
   # Create manifest file.
   print('Writing Custom Labels manifest...')
   
   for im in images_dict.values():
   
       with open(local_path+cl_manifest_file, 'a+') as outfile:
               json.dump(im.__dict__,outfile)
               outfile.write('\n')
               outfile.close()
   
   # Upload manifest file to S3 bucket.
   print ('Uploading Custom Labels manifest file to S3 bucket')
   print('Uploading'  + local_path + cl_manifest_file + ' to ' + s3_key_path_manifest_file)
   print(s3_bucket)
   s3 = boto3.resource('s3')
   s3.Bucket(s3_bucket).upload_file(local_path + cl_manifest_file, s3_key_path_manifest_file + cl_manifest_file)
   
   # Print S3 URL to manifest file,
   print ('S3 URL Path to manifest file. ')
   print('\033[1m s3://' + s3_bucket + '/' + s3_key_path_manifest_file + cl_manifest_file + '\033[0m') 
   
   # Display aws s3 sync command.
   print ('\nAWS CLI s3 sync command to upload your images to S3 bucket. ')
   print ('\033[1m aws s3 sync ' + local_images_path + ' ' + s3_path + '\033[0m')
   ```

1. 运行该代码。

1. 在程序输出中，记下 `s3 sync` 命令。您在下一个步骤中需要用到它。

1. 在命令提示符处，运行 `s3 sync` 命令。您的图像将上传到 S3 存储桶。如果该命令在上传过程中失败，请再次运行它，直到您的本地图像与 S3 存储桶同步为止。

1. 在程序输出中，记下清单文件的 S3 URL 路径。您在下一个步骤中需要用到它。

1. 按照[使用 SageMaker AI Ground Truth 清单文件创建数据集（控制台）](md-create-dataset-ground-truth.md#md-create-dataset-ground-truth-console)中的说明，使用上传的清单文件创建数据集。对于步骤 8，在 **.manifest 文件位置**中，输入您在上一步中记下的 Amazon S3 URL。如果使用的是 AWS SDK，请执行[使用 SageMaker AI Ground Truth 清单文件 (SDK) 创建数据集](md-create-dataset-ground-truth.md#md-create-dataset-ground-truth-sdk)。

# 转换多标签 SageMaker AI Ground Truth 清单文件
<a name="md-gt-cl-transform"></a>

本主题向您展示如何将多标签 Amazon A SageMaker I Ground Truth 清单文件转换为亚马逊 Rekognition 自定义标签格式的清单文件。

SageMaker 多标签作业的 AI Ground Truth 清单文件的格式与 Amazon Rekognition 自定义标签格式清单文件的格式不同。多标签分类是指将一个图像分类为一组类别，但可能同时属于多个类别。在这种情况下，该图像可能会有多个标签（多标签），例如 *football* 和 *ball*。

有关多标签 SageMaker AI Ground Truth 作业的信息，请参阅[图像分类（多标签](https://docs.aws.amazon.com/sagemaker/latest/dg/sms-image-classification-multilabel.html)）。有关多标签格式的 Amazon Rekognition Custom Labels 清单文件的信息，请参阅[为图像添加多个图像级标签](md-create-manifest-file-classification.md#md-dataset-purpose-classification-multiple-labels)。

## 获取 A SageMaker I Ground Truth 任务的清单文件
<a name="md-get-gt-manifest"></a>

以下过程向您展示了如何获取 Amazon A SageMaker I Ground Truth 任务的输出清单文件 (`output.manifest`)。您可以将 `output.manifest` 用作下一过程的输入。

**下载 A SageMaker I Ground Truth 任务清单文件**

1. 打开 [https://console.aws.amazon.com/sagemaker/](https://console.aws.amazon.com/sagemaker/)。

1. 在导航窗格中，选择 **Ground Truth**，然后选择**标注作业**。

1. 选择包含要使用的清单文件的标注作业。

1. 在详细信息页面上，选择**输出数据集位置**下的链接。Amazon S3 控制台将在数据集所在位置打开。

1. 依次选择 `Manifests`、`output` 和 `output.manifest`。

1. 选择**对象操作**，然后选择**下载**，下载清单文件。

## 转换多标签 SageMaker AI 清单文件
<a name="md-transform-ml-gt"></a>

以下过程根据现有的多标签格式 AI 清单文件创建多标签格式 Amazon Rekognition 自定义标签清单文件。 SageMaker GroundTruth

**注意**  
要运行此代码，您需要使用 Python 版本 3 或更高版本。<a name="md-procedure-multi-label-transform"></a>

**转换多标签 SageMaker AI 清单文件**

1. 运行以下 Python 代码。提供您在[获取 A SageMaker I Ground Truth 任务的清单文件](#md-get-gt-manifest)中创建的清单文件名称作为命令行参数。

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier:  Apache-2.0
   """
   Purpose
   Shows how to create and Amazon Rekognition Custom Labels format
   manifest file from an Amazon SageMaker Ground Truth Image
   Classification (Multi-label) format manifest file.
   """
   import json
   import logging
   import argparse
   import os.path
   
   logger = logging.getLogger(__name__)
   
   def create_manifest_file(ground_truth_manifest_file):
       """
       Creates an Amazon Rekognition Custom Labels format manifest file from
       an Amazon SageMaker Ground Truth Image Classification (Multi-label) format
       manifest file.
       :param: ground_truth_manifest_file: The name of the Ground Truth manifest file,
       including the relative path.
       :return: The name of the new Custom Labels manifest file.
       """
   
       logger.info('Creating manifest file from %s', ground_truth_manifest_file)
       new_manifest_file = f'custom_labels_{os.path.basename(ground_truth_manifest_file)}'
   
       # Read the SageMaker Ground Truth manifest file into memory.
       with open(ground_truth_manifest_file) as gt_file:
           lines = gt_file.readlines()
   
       #Iterate through the lines one at a time to generate the
       #new lines for the Custom Labels manifest file.
       with open(new_manifest_file, 'w') as the_new_file:
           for line in lines:
               #job_name - The of the Amazon Sagemaker Ground Truth job.
               job_name = ''
               # Load in the old json item from the Ground Truth manifest file
               old_json = json.loads(line)
   
               # Get the job name
               keys = old_json.keys()
               for key in keys:
                   if 'source-ref' not in key and '-metadata' not in key:
                       job_name = key
   
               new_json = {}
               # Set the location of the image
               new_json['source-ref'] = old_json['source-ref']
   
               # Temporarily store the list of labels
               labels = old_json[job_name]
   
               # Iterate through the labels and reformat to Custom Labels format
               for index, label in enumerate(labels):
                   new_json[f'{job_name}{index}'] = index
                   metadata = {}
                   metadata['class-name'] = old_json[f'{job_name}-metadata']['class-map'][str(label)]
                   metadata['confidence'] = old_json[f'{job_name}-metadata']['confidence-map'][str(label)]
                   metadata['type'] = 'groundtruth/image-classification'
                   metadata['job-name'] = old_json[f'{job_name}-metadata']['job-name']
                   metadata['human-annotated'] = old_json[f'{job_name}-metadata']['human-annotated']
                   metadata['creation-date'] = old_json[f'{job_name}-metadata']['creation-date']
                   # Add the metadata to new json line
                   new_json[f'{job_name}{index}-metadata'] = metadata
               # Write the current line to the json file
               the_new_file.write(json.dumps(new_json))
               the_new_file.write('\n')
   
       logger.info('Created %s', new_manifest_file)
       return  new_manifest_file
   
   def add_arguments(parser):
       """
       Adds command line arguments to the parser.
       :param parser: The command line parser.
       """
   
       parser.add_argument(
           "manifest_file", help="The Amazon SageMaker Ground Truth manifest file"
           "that you want to use."
       )
   
   
   def main():
       logging.basicConfig(level=logging.INFO,
                           format="%(levelname)s: %(message)s")
       try:
           # get command line arguments
           parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
           add_arguments(parser)
           args = parser.parse_args()
           # Create the manifest file
           manifest_file = create_manifest_file(args.manifest_file)
           print(f'Manifest file created: {manifest_file}')
       except FileNotFoundError as err:
           logger.exception('File not found: %s', err)
           print(f'File not found: {err}. Check your manifest file.')
   
   if __name__ == "__main__":
       main()
   ```

1. 记下脚本显示的新清单文件的名称。您将在下一个步骤中使用它。

1. [上传清单文件](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html)至要用于存储清单文件的 Amazon S3 存储桶。
**注意**  
确保 Amazon Rekognition Custom Labels 可以访问清单文件 JSON 行的 `source-ref` 字段中引用的 Amazon S3 存储桶。有关更多信息，请参阅 [访问外部 Amazon S3 存储桶](su-console-policy.md#su-external-buckets)。如果 Ground Truth 作业将图像存储在 Amazon Rekognition Custom Labels 控制台存储桶中，则无需添加权限。

1. 按照[使用 SageMaker AI Ground Truth 清单文件创建数据集（控制台）](md-create-dataset-ground-truth.md#md-create-dataset-ground-truth-console)中的说明，使用上传的清单文件创建数据集。对于步骤 8，在 **.manifest 文件位置**中，请输入清单文件位置的 Amazon S3 URL。如果使用的是 AWS SDK，请执行[使用 SageMaker AI Ground Truth 清单文件 (SDK) 创建数据集](md-create-dataset-ground-truth.md#md-create-dataset-ground-truth-sdk)。

# 从 CSV 文件创建清单文件
<a name="ex-csv-manifest"></a>

此示例 Python 脚本使用逗号分隔值 (CSV) 文件来标注图像，从而简化了清单文件的创建工作。您需要创建 CSV 文件。该清单文件适用于[多标签图像分类](getting-started.md#gs-multi-label-image-classification-example)或[多标签图像分类](getting-started.md#gs-multi-label-image-classification-example)。有关更多信息，请参阅 [查找物体、场景和概念](understanding-custom-labels.md#tm-classification)。

**注意**  
此脚本无法创建适用于查找[物体位置](understanding-custom-labels.md#tm-object-localization)或[品牌位置](understanding-custom-labels.md#tm-brand-detection-localization)的清单文件。

清单文件描述了用于训练模型的图像。例如，图像位置和分配给图像的标签。清单文件由一个或多个 JSON 行组成。每个 JSON 行都描述了一张图像。有关更多信息，请参阅 [在清单文件中导入图像级标签](md-create-manifest-file-classification.md)。

CSV 文件代表文本文件中多行的表格数据。一行中的各个字段用逗号分隔。有关更多信息，请参阅[逗号分隔的值](https://en.wikipedia.org/wiki/Comma-separated_values)。对于此脚本，CSV 文件中的每一行都代表一张图像，并映射到清单文件中的一个 JSON 行。要为支持[多标签图像分类](getting-started.md#gs-multi-label-image-classification-example)的清单文件创建 CSV 文件，您需要向每行添加一个或多个图像级标签。要创建适用于[图像分类](getting-started.md#gs-image-classification-example)的清单文件，请在每行中添加一个图像级标签。

例如，以下 CSV 文件描述了[多标签图像分类](getting-started.md#gs-multi-label-image-classification-example) (Flowers) *入门*项目中的图像。

```
camellia1.jpg,camellia,with_leaves
camellia2.jpg,camellia,with_leaves
camellia3.jpg,camellia,without_leaves
helleborus1.jpg,helleborus,without_leaves,not_fully_grown
helleborus2.jpg,helleborus,with_leaves,fully_grown
helleborus3.jpg,helleborus,with_leaves,fully_grown
jonquil1.jpg,jonquil,with_leaves
jonquil2.jpg,jonquil,with_leaves
jonquil3.jpg,jonquil,with_leaves
jonquil4.jpg,jonquil,without_leaves
mauve_honey_myrtle1.jpg,mauve_honey_myrtle,without_leaves
mauve_honey_myrtle2.jpg,mauve_honey_myrtle,with_leaves
mauve_honey_myrtle3.jpg,mauve_honey_myrtle,with_leaves
mediterranean_spurge1.jpg,mediterranean_spurge,with_leaves
mediterranean_spurge2.jpg,mediterranean_spurge,without_leaves
```

该脚本会为每一行生成 JSON 行。例如，以下是第一行 (`camellia1.jpg,camellia,with_leaves`) 的 JSON 行。

```
{"source-ref": "s3://bucket/flowers/train/camellia1.jpg","camellia": 1,"camellia-metadata":{"confidence": 1,"job-name": "labeling-job/camellia","class-name": "camellia","human-annotated": "yes","creation-date": "2022-01-21T14:21:05","type": "groundtruth/image-classification"},"with_leaves": 1,"with_leaves-metadata":{"confidence": 1,"job-name": "labeling-job/with_leaves","class-name": "with_leaves","human-annotated": "yes","creation-date": "2022-01-21T14:21:05","type": "groundtruth/image-classification"}}
```

在示例 CSV 中，没有图像的 Amazon S3 路径。如果您的 CSV 文件不包含图像的 Amazon S3 路径，请使用 `--s3_path` 命令行参数指定图像的 Amazon S3 路径。

该脚本会在去重图像 CSV 文件中记录每张图像的第一个条目。去重图像 CSV 文件包含在输入 CSV 文件中找到的每张图像的单个实例。输入 CSV 文件中存在的图像的其他实例将记录在重复图像 CSV 文件中。如果脚本发现重复的图像，便会检查重复图像 CSV 文件并根据需要更新去重图像 CSV 文件。使用去重文件，重新运行该脚本。如果在输入 CSV 文件中未找到重复项，则脚本会删除经过重复数据删除的图像 CSV 文件和重复的图像 CSVfile，因为它们为空。

 在此过程中，您将创建 CSV 文件并运行 Python 脚本以创建清单文件。

**通过 CSV 文件创建清单文件**

1. 创建一个 CSV 文件，并且在每一行中包含以下字段（每张图像占一行）。请勿在 CSV 文件中添加标题行。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/rekognition/latest/customlabels-dg/ex-csv-manifest.html)

   例如，`camellia1.jpg,camellia,with_leaves` 或 `s3://my-bucket/flowers/train/camellia1.jpg,camellia,with_leaves` 

1. 保存 CSV 文件。

1. 运行以下 Python 脚本。提供以下参数：
   + `csv_file`：您在步骤 1 中创建的 CSV 文件。
   + `manifest_file`：您要创建的清单文件的名称。
   + （可选）`--s3_path s3://path_to_folder/`：要添加到图像文件名（字段 1）的 Amazon S3 路径。如果字段 1 中的图像不包含 S3 路径，则使用 `--s3_path`。

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier:  Apache-2.0
   
   from datetime import datetime, timezone
   import argparse
   import logging
   import csv
   import os
   import json
   
   """
   Purpose
   Amazon Rekognition Custom Labels model example used in the service documentation.
   Shows how to create an image-level (classification) manifest file from a CSV file.
   You can specify multiple image level labels per image.
   CSV file format is
   image,label,label,..
   If necessary, use the bucket argument to specify the S3 bucket folder for the images.
   https://docs.aws.amazon.com/rekognition/latest/customlabels-dg/md-gt-cl-transform.html
   """
   
   logger = logging.getLogger(__name__)
   
   
   def check_duplicates(csv_file, deduplicated_file, duplicates_file):
       """
       Checks for duplicate images in a CSV file. If duplicate images
       are found, deduplicated_file is the deduplicated CSV file - only the first
       occurence of a duplicate is recorded. Other duplicates are recorded in duplicates_file.
       :param csv_file: The source CSV file.
       :param deduplicated_file: The deduplicated CSV file to create. If no duplicates are found
       this file is removed.
       :param duplicates_file: The duplicate images CSV file to create. If no duplicates are found
       this file is removed.
       :return: True if duplicates are found, otherwise false.
       """
   
       logger.info("Deduplicating %s", csv_file)
   
       duplicates_found = False
   
       # Find duplicates.
       with open(csv_file, 'r', newline='', encoding="UTF-8") as f,\
               open(deduplicated_file, 'w', encoding="UTF-8") as dedup,\
               open(duplicates_file, 'w', encoding="UTF-8") as duplicates:
   
           reader = csv.reader(f, delimiter=',')
           dedup_writer = csv.writer(dedup)
           duplicates_writer = csv.writer(duplicates)
   
           entries = set()
           for row in reader:
               # Skip empty lines.
               if not ''.join(row).strip():
                   continue
   
               key = row[0]
               if key not in entries:
                   dedup_writer.writerow(row)
                   entries.add(key)
               else:
                   duplicates_writer.writerow(row)
                   duplicates_found = True
   
       if duplicates_found:
           logger.info("Duplicates found check %s", duplicates_file)
   
       else:
           os.remove(duplicates_file)
           os.remove(deduplicated_file)
   
       return duplicates_found
   
   
   def create_manifest_file(csv_file, manifest_file, s3_path):
       """
       Reads a CSV file and creates a Custom Labels classification manifest file.
       :param csv_file: The source CSV file.
       :param manifest_file: The name of the manifest file to create.
       :param s3_path: The S3 path to the folder that contains the images.
       """
       logger.info("Processing CSV file %s", csv_file)
   
       image_count = 0
       label_count = 0
   
       with open(csv_file, newline='', encoding="UTF-8") as csvfile,\
               open(manifest_file, "w", encoding="UTF-8") as output_file:
   
           image_classifications = csv.reader(
               csvfile, delimiter=',', quotechar='|')
   
           # Process each row (image) in CSV file.
           for row in image_classifications:
               source_ref = str(s3_path)+row[0]
   
               image_count += 1
   
               # Create JSON for image source ref.
               json_line = {}
               json_line['source-ref'] = source_ref
   
               # Process each image level label.
               for index in range(1, len(row)):
                   image_level_label = row[index]
   
                   # Skip empty columns.
                   if image_level_label == '':
                       continue
                   label_count += 1
   
                  # Create the JSON line metadata.
                   json_line[image_level_label] = 1
                   metadata = {}
                   metadata['confidence'] = 1
                   metadata['job-name'] = 'labeling-job/' + image_level_label
                   metadata['class-name'] = image_level_label
                   metadata['human-annotated'] = "yes"
                   metadata['creation-date'] = \
                       datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.%f')
                   metadata['type'] = "groundtruth/image-classification"
   
                   json_line[f'{image_level_label}-metadata'] = metadata
   
                   # Write the image JSON Line.
               output_file.write(json.dumps(json_line))
               output_file.write('\n')
   
       output_file.close()
       logger.info("Finished creating manifest file %s\nImages: %s\nLabels: %s",
                   manifest_file, image_count, label_count)
   
       return image_count, label_count
   
   
   def add_arguments(parser):
       """
       Adds command line arguments to the parser.
       :param parser: The command line parser.
       """
   
       parser.add_argument(
           "csv_file", help="The CSV file that you want to process."
       )
   
       parser.add_argument(
           "--s3_path", help="The S3 bucket and folder path for the images."
           " If not supplied, column 1 is assumed to include the S3 path.", required=False
       )
   
   
   def main():
   
       logging.basicConfig(level=logging.INFO,
                           format="%(levelname)s: %(message)s")
   
       try:
   
           # Get command line arguments
           parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
           add_arguments(parser)
           args = parser.parse_args()
   
           s3_path = args.s3_path
           if s3_path is None:
               s3_path = ''
   
           # Create file names.
           csv_file = args.csv_file
           file_name = os.path.splitext(csv_file)[0]
           manifest_file = f'{file_name}.manifest'
           duplicates_file = f'{file_name}-duplicates.csv'
           deduplicated_file = f'{file_name}-deduplicated.csv'
   
           # Create manifest file, if there are no duplicate images.
           if check_duplicates(csv_file, deduplicated_file, duplicates_file):
               print(f"Duplicates found. Use {duplicates_file} to view duplicates "
                     f"and then update {deduplicated_file}. ")
               print(f"{deduplicated_file} contains the first occurence of a duplicate. "
                     "Update as necessary with the correct label information.")
               print(f"Re-run the script with {deduplicated_file}")
           else:
               print("No duplicates found. Creating manifest file.")
   
               image_count, label_count = create_manifest_file(csv_file,
                                                               manifest_file,
                                                               s3_path)
   
               print(f"Finished creating manifest file: {manifest_file} \n"
                     f"Images: {image_count}\nLabels: {label_count}")
   
       except FileNotFoundError as err:
           logger.exception("File not found: %s", err)
           print(f"File not found: {err}. Check your input CSV file.")
   
   
   if __name__ == "__main__":
       main()
   ```

1. 如果您计划使用测试数据集，请重复步骤 1-3，以便为测试数据集创建清单文件。

1. 如有必要，请将图像复制到您在 CSV 文件第 1 列中指定的（或在 `--s3_path` 命令行中指定的）Amazon S3 存储桶路径。您可使用以下 AWS S3 命令。

   ```
   aws s3 cp --recursive your-local-folder s3://your-target-S3-location
   ```

1. [上传清单文件](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html)至要用于存储清单文件的 Amazon S3 存储桶。
**注意**  
确保 Amazon Rekognition Custom Labels 可以访问清单文件 JSON 行的 `source-ref` 字段中引用的 Amazon S3 存储桶。有关更多信息，请参阅 [访问外部 Amazon S3 存储桶](su-console-policy.md#su-external-buckets)。如果 Ground Truth 作业将图像存储在 Amazon Rekognition Custom Labels 控制台存储桶中，则无需添加权限。

1. 按照[使用 SageMaker AI Ground Truth 清单文件创建数据集（控制台）](md-create-dataset-ground-truth.md#md-create-dataset-ground-truth-console)中的说明，使用上传的清单文件创建数据集。对于步骤 8，在 **.manifest 文件位置**中，请输入清单文件位置的 Amazon S3 URL。如果使用的是 AWS SDK，请执行[使用 SageMaker AI Ground Truth 清单文件 (SDK) 创建数据集](md-create-dataset-ground-truth.md#md-create-dataset-ground-truth-sdk)。