AWS Rekognitionで画像解析（2）

　こんにちは。前回はAWS Rekognition custom labelをGUIで操作して、独自に画像に付与したラベルを分類する方法を書きました。

https://qiita.com/ken340/items/a1afd3a8ddd11b85ca06

利点はAIの知識をほとんど知らなくてもモデルの学習とテストを実行できることかと思います。ただ、単に分類するだけでなく機能を追加したい場合や他のサービスと組み合わせたい場合などはGUI操作だけでは使いにくいと思います。また、データの数が多くなると、ひたすらマウスクリックしなければならず、地味に手が疲れます。ここでは前回やったことをpythonのプログラムの中でAPI経由で実行する方法を書きたいと思います。

# 操作の流れ

順序は以下の通りです。
step1: S3にトレーニング用及びテスト用の画像データをアップロードする。
step2: マニフェストファイルを用意する。
step3: APIを使って学習とテストを実行するpythonプログラムを書く。
step4: プログラムを実行しする。
step5: 結果を確認する。

この順番で説明します。

# step1: S3にトレーニング用及びテスト用の画像データをアップロードする。

GUIを使ってS3に画像データをアップロードします。

![2024-12-23 10.15のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961907/79700b49-e3ed-593f-9e3b-182b947820f5.jpeg)

 S3に本実験用に「escrap-test2」というバケットを作成しました。そのバケットの中に、「data」「manifest」「output」というフォルダを作成しました。

![2024-12-23 10.20のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961907/e3104841-cdca-1824-a6f8-140db6e24848.jpeg)

 このあたりはお好みかもしれませんが、dataフォルダの中にさらに「2」「3」「4」というフォルダを作りました。前回、画像データにラベルを「2」「3」「4」のいずれかを付与しました。画像データを分けて保存するために「2」「3」「4」フォルダを作りました。（実際には、これはMUSTではありません、なぜならば、後でマニフェストファイルの中でどの画像にどのラベルを付けるかを指定するので、全ての画像データをごっちゃに一つのフォルダに入れておいても問題ないと思われます。ただ、メンテナンスしにくくなりそうなので、分けた方が無難かと思います。）

![2024-12-23 11.28のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961907/19c943a4-5d91-40d5-cb10-53bc324b28de.jpeg)

　フォルダ「2」に、画像ファイルを160枚アップロードしたところです。前回の記事でRekognitionに直接ファイルをアップロードする最大数は30に制限されていましたが、S3には特に上限は無いようです。ファイル数が多い場合は便利です。
　同様にして、フォルダ「3」「4」にも画像ファイルをアップロードしておきます。
 
# step2: マニフェストファイルを用意する。

　マニフェストファイルは、各データのメタデータを設定するファイルで、学習データ用とテストデータ用の２つのファイルを用意する必要があります。以下の項目を記述する必要があります。
+ source-ref：画像ファイルのS3のバケット内のパスを書きます。
+ label：画像に付与するラベルを書きます。
+ label-metadata：以下の情報を記述します。
-- confidence：ラベルがどれだけ正確であるかを示す信頼度を表します。値は0から1の範囲で、1に近いほど信頼度が高いことを意味します。
-- class-name：これは画像に付けられたラベルのクラス名です。
-- human-annotated：ラベルが人間によって注釈されたかどうかを示します。「yes」の場合、人間が画像を見てラベルを付けたことを意味します。「no」の場合、ラベルは自動化されたプロセスによって付けられた可能性があります。
-- creation-date：ラベルが作成された日時を示します。ISO 8601形式で書きます。
-- type：このフィールドは、ラベルのタイプを示します。`groundtruth/image-classification`は、画像分類のための正解データであることを意味します。これは、機械学習モデルのトレーニングや評価に使用されるデータです。

　以下に一例を示します。

``` json

{"source-ref":"s3://escrap-test2/data/2/2-1.jpg","label":"2","label-metadata":{"confidence":1,"class-name":"2","human-annotated":"yes","creation-date":"2024-12-01T12:00:00.000","type":"groundtruth/image-classification"}}

```

　この例では、上記ステップでS3に画像データ2-1.jpgをアップロードしましたが、これにラベル「2」を付けています。これを全てのデータに対して記述します。大変そうだと思うかもしれませんが、コピペしてファイル名とラベルだけ変更すれば良いので、前回のようにひたすらクリックするよりは楽です。書き方は上記の通り同じファイルを二つ用意します、ここでは、manifest-escrap-training1.jsonとmanifest-escrap-testing1.jsonというファイル名にしました。それぞれ学習用ファイルとテスト用ファイルです。

![2024-12-24 15.41のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961907/8b94353b-0538-537c-ab88-c738850452d9.jpeg)

　S3のmanifestフォルダの中に二つのファイルをアップロードしました。
 
# step3: APIを使って学習とテストを実行するpythonプログラムを書く。

## 準備

 まずは、GUI操作で新しいプロジェクトを作成しておきましょう。

 ![2024-12-24 15.59のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961907/e358e29f-5383-b599-865d-5614c368e06e.jpeg)

　escrap-test2というプロジェクトを作成しました。次に、shellで

 ``` shell
% aws rekognition describe-projects
 ```
　を実行します。

 ```
        {
            "ProjectArn": "arn:aws:rekognition:us-west-2:xxx:project/escrap-test2/yyy",
            "CreationTimestamp": "2024-12-24T15:53:58.891000+09:00",
            "Status": "CREATED",
            "Datasets": []
        },
 ```

　このような結果が得られます。実際には、xxxとyyyには具体的な数字が入ります。ProjectArnをコピーしておいてください。ProjectArnとは、プロジェクトを一意に識別するためのAmazon Resource Name (ARN) です。

 ```
 arn:aws:rekognition:region:account-id:project/project-name/version/version-name/timestamp
 ```

 という意味になっています。
 
## プログラム本体の作成
 
 事前準備ができたので、次に、プログラム本体を作ります。

``` python
import boto3
```
 
　まず、boto3というpythonのライブラリをインポートします。これはAWSのSDKです。

``` python
client = boto3.client('rekognition')
```

次に、Rekognitionサービスのクライアントオブジェクトを作成します。

``` python
    ProjectArn='arn:aws:rekognition:us-west-2:xxx:project/escrap-test2/yyy',
    VersionName='v1',
```

ProjectArnは上記でコピーしておいた情報を入れます。VersionNameは一番最初なので'v1'としました。学習を実行するたびにバージョン番号を変えないとエラーになります。

``` python
    OutputConfig={
        'S3Bucket': 'escrap-test2',
        'S3KeyPrefix': 'output'
    },
```

学習とテストの実行結果を出力するバケットとフォルダを指定します。

``` python
    TrainingData={
        'Assets': [
            {
                'GroundTruthManifest': {
                    'S3Object': {
                        'Bucket': 'escrap-test2',
                        'Name': 'manifests/manifest-escrap-training1.json'
                    }
                }
            }
        ]
    },
```

　学習データを保存しているバケットと学習用のマニフェストファイルを指定します。

 ``` python
     TestingData={
        'Assets': [
            {
                'GroundTruthManifest': {
                    'S3Object': {
                        'Bucket': 'escrap-test2',
                        'Name': 'manifests/manifest-escrap-testing1.json'
                    }
                }
            }
        ]
    }
 ```

　テストデータを保存しているバケットとテスト用のマニフェストファイルを指定します。

``` python:escrap-test2.py
import boto3

client = boto3.client('rekognition')

training_dataset_response = client.create_project_version(
    ProjectArn='arn:aws:rekognition:us-west-2:xxx:project/escrap-test2/yyy',
    VersionName='v1',
    OutputConfig={
        'S3Bucket': 'escrap-test2',
        'S3KeyPrefix': 'output'
    },
    TrainingData={
        'Assets': [
            {
                'GroundTruthManifest': {
                    'S3Object': {
                        'Bucket': 'escrap-test2',
                        'Name': 'manifest/manifest-escrap-training1.json'
                    }
                }
            }
        ]
    },
    TestingData={
        'Assets': [
            {
                'GroundTruthManifest': {
                    'S3Object': {
                        'Bucket': 'escrap-test2',
                        'Name': 'manifest/manifest-escrap-testing1.json'
                    }
                }
            }
        ]
    }
)
print(training_dataset_response)
```

 全部を合わせてescrap-test2.pyの完成です。

# step4: プログラムを実行しする。

``` shell
% python3 escrap-test2.py
```

 実行します。

 # step5: 結果を確認する。

![2024-12-24 21.31のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3961907/ac40ee87-e7cc-edee-a15a-2493d86883d9.jpeg)

　結果を確認します。F1値は0.802でした。前回より良い値です。その理由の一つは、学習データは前回は一つのラベルあたり１０個だけでしたが今回は３０個に増やした事が挙げられます。

 # まとめ

 　前回はGUIだけで操作しましたがデータ数が増えると地味に大変です。今回はマニフェストファイルを編集するだけでデータを簡単に増やせます。また、プログラム中に他の操作や他のサービスとの連携を記述することで簡単に拡張が可能です。

終わり。