CSV ファイルからの分類マニフェストファイルの作成 - Amazon Lookout for Vision

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

CSV ファイルからの分類マニフェストファイルの作成

この Python スクリプトの例では、カンマ区切り値 (CSV) ファイルを使用して画像にラベルを付けることで、分類マニフェストファイルの作成を簡単にしています。CSV ファイルを作成します。

マニフェストファイルには、モデルのトレーニングに使用される画像が記述されています。マニフェストファイルは JSON line で構成されます。JSON の各行には 1 つの画像が記述されています。詳細については、「画像分類のための JSON line の定義」を参照してください。

CSV ファイルは、テキストファイル内の複数の行にわたる表形式のデータを表します。行のフィールドはカンマで区切ります。詳細については、カンマで区切られた値を参照してください。このスクリプトでは、CSV ファイルの各行に、画像の S3 位置と画像の異常分類 (normalまたはanomaly) が含まれます。各行はマニフェストファイルの JSON 行にマップされます。

たとえば、次の CSV ファイルには、サンプル画像の一部の画像が記述されています

s3://s3bucket/circuitboard/train/anomaly/train-anomaly_1.jpg,anomaly s3://s3bucket/circuitboard/train/anomaly/train-anomaly_10.jpg,anomaly s3://s3bucket/circuitboard/train/anomaly/train-anomaly_11.jpg,anomaly s3://s3bucket/circuitboard/train/normal/train-normal_1.jpg,normal s3://s3bucket/circuitboard/train/normal/train-normal_10.jpg,normal s3://s3bucket/circuitboard/train/normal/train-normal_11.jpg,normal

このスクリプトは、行ごとに JSON 行を生成します。たとえば、以下は最初の行 (s3://s3bucket/circuitboard/train/anomaly/train-anomaly_1.jpg,anomaly) の JSON 行です。

{"source-ref": "s3://s3bucket/csv_test/train_anomaly_1.jpg","anomaly-label": 1,"anomaly-label-metadata": {"confidence": 1,"job-name": "labeling-job/anomaly-classification","class-name": "anomaly","human-annotated": "yes","creation-date": "2022-02-04T22:47:07","type": "groundtruth/image-classification"}}

CSV ファイルにイメージの Amazon S3 パスが含まれていない場合は、--s3-pathコマンドライン引数を使用してイメージへの Amazon S3 パスを指定します。

マニフェストファイルを作成する前に、スクリプトは CSV ファイル内の重複画像と、normalまたは以外の画像分類を確認しますanomaly。重複する画像または画像分類エラーが見つかると、スクリプトは次の処理を行います。

  • すべての画像の最初の有効な画像エントリを、重複排除された CSV ファイルに記録します。

  • 画像の重複箇所をエラーファイルに記録します。

  • エラーファイルに含まれていない、normalanomalyまたはエラーファイルに含まれていない画像分類を記録します。

  • マニフェストファイルを作成しません。

エラーファイルには、入力 CSV ファイル内の重複画像または分類エラーが見つかった行番号が含まれます。エラー CSV ファイルを使用して入力 CSV ファイルを更新し、スクリプトを再実行します。または、エラー CSV ファイルを使用して、重複排除された CSV ファイルを更新します。このファイルには、固有の画像エントリと画像分類エラーのない画像のみが含まれます。更新された重複排除された CSV ファイルを使用してスクリプトを再実行します。

入力 CSV ファイルに重複やエラーが見つからなかった場合、スクリプトは重複排除された画像 CSV ファイルとエラーファイルを空のまま削除します。

この手順では、CSV ファイルを作成し、Python スクリプトを実行してマニフェストファイルを作成します。スクリプトは Python バージョン 3.7 でテストされています。

CSV ファイルからマニフェストファイルを作成する
  1. 各行に次のフィールドを含む CSV ファイルを作成します (画像ごとに 1 行)。CSV ファイルにはヘッダー行を追加しないでください。

    フィールド 1 フィールド 2

    イメージ名またはイメージの Amazon S3 パス。例: s3://s3bucket/circuitboard/train/anomaly/train-anomaly_10.jpg。Amazon S3 パスのある画像とないイメージを混在させることはできません。

    画像の異常分類 (normalまたはanomaly)。

    たとえば、s3://s3bucket/circuitboard/train/anomaly/image_10.jpg,anomalyまたはimage_11.jpg,normal

  2. CSV ファイルを保存します。

  3. 以下の Python スクリプトを実行します。以下の引数を指定します。

    • csv_file— ステップ 1 で作成した CSV ファイル。

    • (オプション)--s3-path s3://path_to_folder/ — イメージファイル名に追加する Amazon S3 パス (フィールド 1)。フィールド 1 の画像にまだ S3--s3-path パスが含まれていない場合に使用します。

    # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """ Purpose Shows how to create an Amazon Lookout for Vision manifest file from a CSV file. The CSV file format is image location,anomaly classification (normal or anomaly) For example: s3://s3bucket/circuitboard/train/anomaly/train_11.jpg,anomaly s3://s3bucket/circuitboard/train/normal/train_1.jpg,normal If necessary, use the bucket argument to specify the Amazon S3 bucket folder for the images. """ from datetime import datetime, timezone import argparse import logging import csv import os import json logger = logging.getLogger(__name__) def check_errors(csv_file): """ Checks for duplicate images and incorrect classifications in a CSV file. If duplicate images or invalid anomaly assignments are found, an errors CSV file and deduplicated CSV file are created. Only the first occurrence of a duplicate is recorded. Other duplicates are recorded in the errors file. :param csv_file: The source CSV file :return: True if errors or duplicates are found, otherwise false. """ logger.info("Checking %s.", csv_file) errors_found = False errors_file = f"{os.path.splitext(csv_file)[0]}_errors.csv" deduplicated_file = f"{os.path.splitext(csv_file)[0]}_deduplicated.csv" with open(csv_file, 'r', encoding="UTF-8") as input_file,\ open(deduplicated_file, 'w', encoding="UTF-8") as dedup,\ open(errors_file, 'w', encoding="UTF-8") as errors: reader = csv.reader(input_file, delimiter=',') dedup_writer = csv.writer(dedup) error_writer = csv.writer(errors) line = 1 entries = set() for row in reader: # Skip empty lines. if not ''.join(row).strip(): continue # Record any incorrect classifications. if not row[1].lower() == "normal" and not row[1].lower() == "anomaly": error_writer.writerow( [line, row[0], row[1], "INVALID_CLASSIFICATION"]) errors_found = True # Write first image entry to dedup file and record duplicates. key = row[0] if key not in entries: dedup_writer.writerow(row) entries.add(key) else: error_writer.writerow([line, row[0], row[1], "DUPLICATE"]) errors_found = True line += 1 if errors_found: logger.info("Errors found check %s.", errors_file) else: os.remove(errors_file) os.remove(deduplicated_file) return errors_found def create_manifest_file(csv_file, manifest_file, s3_path): """ Read a CSV file and create an Amazon Lookout for Vision 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 Amazon S3 path to the folder that contains the images. """ logger.info("Processing CSV file %s.", csv_file) image_count = 0 anomalous_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 the CSV file. for row in image_classifications: # Skip empty lines. if not ''.join(row).strip(): continue source_ref = str(s3_path) + row[0] classification = 0 if row[1].lower() == 'anomaly': classification = 1 anomalous_count += 1 # Create the JSON line. json_line = {} json_line['source-ref'] = source_ref json_line['anomaly-label'] = str(classification) metadata = {} metadata['confidence'] = 1 metadata['job-name'] = "labeling-job/anomaly-classification" metadata['class-name'] = row[1] 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['anomaly-label-metadata'] = metadata output_file.write(json.dumps(json_line)) output_file.write('\n') image_count += 1 logger.info("Finished creating manifest file %s.\n" "Images: %s\nAnomalous: %s", manifest_file, image_count, anomalous_count) return image_count, anomalous_count def add_arguments(parser): """ Add 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 Amazon S3 bucket and folder path for the images." " If not supplied, column 1 is assumed to include the Amazon 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 = "" csv_file = args.csv_file csv_file_no_extension = os.path.splitext(csv_file)[0] manifest_file = csv_file_no_extension + '.manifest' # Create manifest file if there are no duplicate images. if check_errors(csv_file): print(f"Issues found. Use {csv_file_no_extension}_errors.csv "\ "to view duplicates and errors.") print(f"{csv_file}_deduplicated.csv contains the first"\ "occurrence of a duplicate.\n" "Update as necessary with the correct information.") print(f"Re-run the script with {csv_file_no_extension}_deduplicated.csv") else: print('No duplicates found. Creating manifest file.') image_count, anomalous_count = create_manifest_file(csv_file, manifest_file, s3_path) print(f"Finished creating manifest file: {manifest_file} \n") normal_count = image_count-anomalous_count print(f"Images processed: {image_count}") print(f"Normal: {normal_count}") print(f"Anomalous: {anomalous_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()
  4. 画像が重複したり、分類エラーが発生したりする場合:

    1. エラーファイルを使用して、重複排除された CSV ファイルまたは入力 CSV ファイルを更新します。

    2. 更新された重複排除された CSV ファイルまたは更新された入力 CSV ファイルを使用してスクリプトを再実行します。

  5. テストデータセットを使用する場合は、ステップ 1 ~ 4 を繰り返してテストデータセットのマニフェストファイルを作成します。

  6. 必要に応じて、CSV ファイルの列 1 で指定した (--s3-pathまたはコマンドラインで指定した) Amazon S3 バケットパスにコンピューターからイメージをコピーします。画像をコピーするには、コマンドプロンプトで次のコマンドを入力します。

    aws s3 cp --recursive your-local-folder/ s3://your-target-S3-location/
  7. の手順に従ってマニフェストファイルを使用したデータセットの作成 (コンソール)、データセットを作成します。AWSSDK を使用している場合は、を参照してくださいマニフェストファイル (SDK) を使用したデータセットの作成