

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

# Amazon Rekognition と Lambda を使用して Amazon S3 バケットのアセットにタグを付ける
<a name="images-lambda-s3-tutorial"></a>

このチュートリアルでは、Amazon S3 バケットにあるデジタルアセットに自動的にタグ付けする AWS Lambda関数を作成します。Lambda 関数は、指定された Amazon S3 バケット内のすべてのオブジェクトを読み取ります。バケット内の各オブジェクトについて、イメージを Amazon Rekognition サービスに渡して、一連のラベルを生成します。各ラベルは、イメージに適用されるタグを作成するために使用されます。Lambda 関数を実行すると、指定された Amazon S3 バケット内のすべてのイメージに基づいてタグが自動的に作成され、イメージに適用されます。

例えば、Lambda 関数を実行し、このイメージが Amazon S3 バケット内にあると仮定します。

![曇り空を背景に噴火中の火山。溶岩が山側面を流れ落ちている。](http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/images/v2-image-tutorial-picture.png)


その後、アプリケーションは自動的にタグを作成し、イメージにそれらを適用します。

![Nature、Volcano、Eruption、Lava、Mountain、Outdoors などストレージコストの追跡用タグおよび数値を示す表。](http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/images/v2-image-tutorial-results.png)


**注記**  
このチュートリアルで使用するサービスは、 AWS無料利用枠の一部です。チュートリアルが終了したら、課金されないように、チュートリアル中に作成したリソースをすべて終了することをお勧めします。

このチュートリアルでは、 AWSSDK for Java バージョン 2 を使用します。追加の Java V2 チュートリアルについては、[AWS ドキュメント SDK の例 GitHub リポジトリ](https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/usecases) を参照してください。

**Topics**
+ [前提条件](#lambda-s3-tutorial-prerequisites)
+ [IAM Lambda ロールを設定する](#lambda-s3-tutorial-lambda-role)
+ [プロジェクトの作成](#lambda-s3-tutorial-pom)
+ [コードを書き込む](#lambda-s3-tutorial-code)
+ [プロジェクトをパッケージ化する](#lambda-s3-tutorial-package)
+ [Lambda 関数をデプロイします。](#lambda-s3-tutorial-deploy)
+ [Lambda メソッドをテストする](#lambda-s3-tutorial-test)

## 前提条件
<a name="lambda-s3-tutorial-prerequisites"></a>

開始する前に、[AWS「 SDK for Java のセットアップ](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup.html)」の手順を完了する必要があります。次に、以下があることを確認します。
+ Java 1.8 JDK。
+ Maven 3.6 以上
+ ネイチャーイメージが入った [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) バケット 5-7 これらのイメージは Lambda 関数によって読み取られます。

## IAM Lambda ロールを設定する
<a name="lambda-s3-tutorial-lambda-role"></a>

このチュートリアルでは、Amazon Rekognition および Amazon S3 サービスを使用します。Lambda 関数からこれらのサービスを呼び出すことを可能にするポリシーを持つために、**lambda-support** ロールを設定する。

**ロールを設定するには**

1. にサインインAWS マネジメントコンソールし、[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) で IAM コンソールを開きます。

1.  ナビゲーションペインで、**[Roles (ロール)]**、**[ロールの作成]** の順に選択します。

1. [**AWS サービス**]、[**Lambda**] の順に選択します。

1. **[アクセス許可]** タブを選択します。

1. **AWSLambdaBasicExecutionRole** を検索する。

1. [**次のタグ**] を選択します。

1. [**Review**] (レビュー) を選択します。

1. そのロールに **lambda-support** という名前を付けます。

1. [**ロールの作成**] を選択してください。

1. **lambda-support** を選択して、概要ページを表示します。

1. **ポリシーのアタッチ** を選択します。

1. ポリシーのリストから [*AmazonRekognitionFullAccess*] を選択します。

1. **ポリシーの添付** を選択します。

1. **AmazonS3FullAccess** を検索してから、**添付ポリシー** を選択します。

## プロジェクトの作成
<a name="lambda-s3-tutorial-pom"></a>

新しい Java プロジェクトを作成し、必要な設定と依存関係に必須の Maven pom.xml を構成します。pom.xml ファイルが次のようになっていることを確認します。

```
<?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>WorkflowTagAssets</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>java-basic-function</name>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.10.54</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
   <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-core</artifactId>
        <version>1.2.1</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.6</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.10.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j18-impl</artifactId>
        <version>2.13.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1.1</version>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3</artifactId>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>rekognition</artifactId>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.2</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
  </build>
 </project>
```

## コードを書き込む
<a name="lambda-s3-tutorial-code"></a>

AWS Lambdaランタイム Java API を使用して、Lambda 関数を定義する Java クラスを作成します。この例では、**ハンドラー** という名前の Lambda 関数用の Java クラスが 1 つあり、このユースケースには追加のクラスが必要です。次の図は、プロジェクトの Java クラスを示します。すべての Java クラスが、**com.example.tags** という名前のパッケージに配置されていることに注目してください。

![ワークフローのタグ付けアセットの Java クラスを示すプロジェクト構造。AnalyzePhotos、BucketItem、Handler、S3Service、WorkItem が表示されている。](http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/images/v2-image-tutorial-files.png)


コード用に次の Java クラスを作成します。
+ **ハンドラー**は Lambda Java ランタイム API を使用し、このAWSチュートリアルで説明されているユースケースを実行します。実行されるアプリケーションロジックは、handleRequest メソッドにあります。
+ **S3Service** は、Amazon S3 API を使用して S3 オペレーションを実行します。
+ **AnalyzePhotos** では、Amazon Rekognition API を使用してイメージを分析します。
+ **バケット項目** は、Amazon S3 バケット情報を格納するモデルを定義します。
+ **作業項目** は Amazon Rekognition データを格納するモデルを定義します。

### ハンドラークラス
<a name="w2aac52b9c25c11"></a>

この Java コードは、**Handler** のクラスを表します。そのクラスは、Lambda 関数に渡されるフラグを読み取ります。**s3Service.listBucketObjects** メソッドは、各要素がオブジェクトキーを表す文字列値である **リスト** オブジェクトを返します。フラグの値が true の場合、リストを繰り返し処理し、**s3Service.tagAssets** メソッドを呼び出して、タグを各オブジェクトに適用することで、タグが適用されます。フラグの値が false の場合、タグを削除する **s3Service.DeleteTagfromObject** のメソッドが呼び出されます。また、**LambdaLogger** オブジェクトを使用して、Amazon CloudWatch のログにメッセージを記録できることに注目してください。

**注記**  
バケット名を**bucketName** 変数に指定することを確認してください。

```
package com.example.tags;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class Handler implements RequestHandler<Map<String,String>, String> {

@Override
public String handleRequest(Map<String, String> event, Context context) {
    LambdaLogger logger = context.getLogger();
    String delFlag = event.get("flag");
    logger.log("FLAG IS: " + delFlag);
    S3Service s3Service = new S3Service();
    AnalyzePhotos photos = new AnalyzePhotos();

    String bucketName = "<Enter your bucket name>";
    List<String> myKeys = s3Service.listBucketObjects(bucketName);
    if (delFlag.compareTo("true") == 0) {

        // Create a List to store the data.
        List<ArrayList<WorkItem>> myList = new ArrayList<>();

        // loop through each element in the List and tag the assets.
        for (String key : myKeys) {

            byte[] keyData = s3Service.getObjectBytes(bucketName, key);

            // Analyze the photo and return a list where each element is a WorkItem.
            ArrayList<WorkItem> item = photos.detectLabels(keyData, key);
            myList.add(item);
        }

        s3Service.tagAssets(myList, bucketName);
        logger.log("All Assets in the bucket are tagged!");

    } else {

        // Delete all object tags.
        for (String key : myKeys) {
            s3Service.deleteTagFromObject(bucketName, key);
            logger.log("All Assets in the bucket are deleted!");
        }
     }
    return delFlag;
  }
 }
```

### S3 サービスクラス
<a name="w2aac52b9c25c13"></a>

次のクラスは、Amazon S3 API を使用して S3 オペレーションを実行します。例えば、**getObjectBytes** メソッドは、イメージを表すバイト配列を返します。同様に、**listBucketObjects** メソッドは、各要素がキー名を指定する文字列値である **リスト** オブジェクトを返します。

```
 package com.example.tags;

 import software.amazon.awssdk.core.ResponseBytes;
 import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.services.s3.S3Client;
 import software.amazon.awssdk.services.s3.model.GetObjectRequest;
 import software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest;
 import software.amazon.awssdk.services.s3.model.GetObjectResponse;
 import software.amazon.awssdk.services.s3.model.S3Exception;
 import software.amazon.awssdk.services.s3.model.ListObjectsResponse;
 import software.amazon.awssdk.services.s3.model.S3Object;
 import software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse;
 import software.amazon.awssdk.services.s3.model.ListObjectsRequest;
 import java.util.ArrayList;
 import java.util.List;
 import software.amazon.awssdk.services.s3.model.Tagging;
 import software.amazon.awssdk.services.s3.model.Tag;
 import software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest;
 import software.amazon.awssdk.services.s3.model.DeleteObjectTaggingRequest;

 public class S3Service {

 private S3Client getClient() {

    Region region = Region.US_WEST_2;
    return S3Client.builder()
            .region(region)
            .build();
 }

 public byte[] getObjectBytes(String bucketName, String keyName) {

    S3Client s3 = getClient();

    try {

        GetObjectRequest objectRequest = GetObjectRequest
                .builder()
                .key(keyName)
                .bucket(bucketName)
                .build();

        // Return the byte[] from this object.
        ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
        return objectBytes.asByteArray();

    } catch (S3Exception e) {
        System.err.println(e.awsErrorDetails().errorMessage());
        System.exit(1);
    }
    return null;
 }

 // Returns the names of all images in the given bucket.
 public List<String> listBucketObjects(String bucketName) {

    S3Client s3 = getClient();
    String keyName;

    List<String> keys = new ArrayList<>();

    try {
        ListObjectsRequest listObjects = ListObjectsRequest
                .builder()
                .bucket(bucketName)
                .build();

        ListObjectsResponse res = s3.listObjects(listObjects);
        List<S3Object> objects = res.contents();

        for (S3Object myValue: objects) {
            keyName = myValue.key();
            keys.add(keyName);
        }
        return keys;

    } catch (S3Exception e) {
        System.err.println(e.awsErrorDetails().errorMessage());
        System.exit(1);
    }
    return null;
 }

 // Tag assets with labels in the given list.
 public void tagAssets(List myList, String bucketName) {

    try {

        S3Client s3 = getClient();
        int len = myList.size();

        String assetName = "";
        String labelName = "";
        String labelValue = "";

        // Tag all the assets in the list.
        for (Object o : myList) {

            // Need to get the WorkItem from each list.
            List innerList = (List) o;
            for (Object value : innerList) {

                WorkItem workItem = (WorkItem) value;
                assetName = workItem.getKey();
                labelName = workItem.getName();
                labelValue = workItem.getConfidence();
                tagExistingObject(s3, bucketName, assetName, labelName, labelValue);
            }
        }

    } catch (S3Exception e) {
        System.err.println(e.awsErrorDetails().errorMessage());
        System.exit(1);
    }
 }

 // This method tags an existing object.
 private void tagExistingObject(S3Client s3, String bucketName, String key, String label, String LabelValue) {

    try {

        // First need to get existing tag set; otherwise the existing tags are overwritten.
        GetObjectTaggingRequest getObjectTaggingRequest = GetObjectTaggingRequest.builder()
                .bucket(bucketName)
                .key(key)
                .build();

        GetObjectTaggingResponse response = s3.getObjectTagging(getObjectTaggingRequest);

        // Get the existing immutable list - cannot modify this list.
        List<Tag> existingList = response.tagSet();
        ArrayList<Tag> newTagList = new ArrayList(new ArrayList<>(existingList));

        // Create a new tag.
        Tag myTag = Tag.builder()
                .key(label)
                .value(LabelValue)
                .build();

        // push new tag to list.
        newTagList.add(myTag);
        Tagging tagging = Tagging.builder()
                .tagSet(newTagList)
                .build();

        PutObjectTaggingRequest taggingRequest = PutObjectTaggingRequest.builder()
                .key(key)
                .bucket(bucketName)
                .tagging(tagging)
                .build();

        s3.putObjectTagging(taggingRequest);
        System.out.println(key + " was tagged with " + label);

    } catch (S3Exception e) {
        System.err.println(e.awsErrorDetails().errorMessage());
        System.exit(1);
    }
  }

 // Delete tags from the given object.
 public void deleteTagFromObject(String bucketName, String key) {

    try {

        DeleteObjectTaggingRequest deleteObjectTaggingRequest = DeleteObjectTaggingRequest.builder()
                .key(key)
                .bucket(bucketName)
                .build();

        S3Client s3 = getClient();
        s3.deleteObjectTagging(deleteObjectTaggingRequest);

    } catch (S3Exception e) {
        System.err.println(e.awsErrorDetails().errorMessage());
        System.exit(1);
    }
  }
}
```

### AnalyzePhotos クラス
<a name="w2aac52b9c25c15"></a>

次の Java コードは、**AnalyzePhotos** のクラスを表します。このクラスは Amazon Rekognition API を使用して、イメージを分析します。

```
package com.example.tags;

import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.rekognition.RekognitionClient;
import software.amazon.awssdk.services.rekognition.model.Image;
import software.amazon.awssdk.services.rekognition.model.DetectLabelsRequest;
import software.amazon.awssdk.services.rekognition.model.DetectLabelsResponse;
import software.amazon.awssdk.services.rekognition.model.Label;
import software.amazon.awssdk.services.rekognition.model.RekognitionException;
import java.util.ArrayList;
import java.util.List;

public class AnalyzePhotos {

 // Returns a list of WorkItem objects that contains labels.
 public ArrayList<WorkItem> detectLabels(byte[] bytes, String key) {

    Region region = Region.US_EAST_2;
    RekognitionClient rekClient = RekognitionClient.builder()
            .credentialsProvider(EnvironmentVariableCredentialsProvider.create())
            .region(region)
            .build();

    try {

        SdkBytes sourceBytes = SdkBytes.fromByteArray(bytes);

        // Create an Image object for the source image.
        Image souImage = Image.builder()
                .bytes(sourceBytes)
                .build();

        DetectLabelsRequest detectLabelsRequest = DetectLabelsRequest.builder()
                .image(souImage)
                .maxLabels(10)
                .build();

        DetectLabelsResponse labelsResponse = rekClient.detectLabels(detectLabelsRequest);

        // Write the results to a WorkItem instance.
        List<Label> labels = labelsResponse.labels();
        ArrayList<WorkItem> list = new ArrayList<>();
        WorkItem item ;
        for (Label label: labels) {
            item = new WorkItem();
            item.setKey(key); // identifies the photo.
            item.setConfidence(label.confidence().toString());
            item.setName(label.name());
            list.add(item);
        }
        return list;

    } catch (RekognitionException e) {
        System.out.println(e.getMessage());
        System.exit(1);
    }
    return null ;
  }
}
```

### バケット項目のクラス
<a name="w2aac52b9c25c17"></a>

次の Java コードは、Amazon S3 オブジェクトデータを格納する **バケット項目** のクラスを表します。

```
package com.example.tags;

public class BucketItem {

 private String key;
 private String owner;
 private String date ;
 private String size ;


 public void setSize(String size) {
    this.size = size ;
 }

 public String getSize() {
    return this.size ;
 }

 public void setDate(String date) {
    this.date = date ;
 }

 public String getDate() {
    return this.date ;
 }

 public void setOwner(String owner) {
    this.owner = owner ;
 }

 public String getOwner() {
    return this.owner ;
 }

 public void setKey(String key) {
    this.key = key ;
 }

 public String getKey() {
    return this.key ;
 }
}
```

### 作業項目のクラス
<a name="w2aac52b9c25c19"></a>

次の Java コードは、**作業項目** のクラスを表します。

```
 package com.example.tags;

 public class WorkItem {

 private String key;
 private String name;
 private String confidence ;

public void setKey (String key) {
    this.key = key;
}

public String getKey() {
    return this.key;
}

public void setName (String name) {
    this.name = name;
}

public String getName() {
    return this.name;
}

public void setConfidence (String confidence) {
    this.confidence = confidence;
}

public String getConfidence() {
    return this.confidence;
}

}
```

## プロジェクトをパッケージ化する
<a name="lambda-s3-tutorial-package"></a>

次の Maven コマンドを使用して、プロジェクトを.jar (JAR) ファイルにパッケージ化します。

```
mvn package
```

JAR ファイルは、**ターゲット** フォルダ (プロジェクトフォルダの子フォルダ) の中にあります。

![target フォルダを示すファイルエクスプローラーウィンドウ。WorkflowTagAssets-1.0-SNAPSHOT.jar などの JAR ファイルのほか、プロジェクトファイルおよびフォルダが表示されている。](http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/images/v2-image-tutorial-folder.png)


**注記**  
プロジェクトの POM ファイル内にある **maven-shade-plugin** の使用に注目してください。このプラグインは、必要な依存関係を含む JAR を作成する役割を担います。このプラグインなしでプロジェクトをパッケージ化しようとすると、必要な依存関係が JAR ファイル内に含まれず、**ClassNotFoundException** に直面します。

## Lambda 関数をデプロイします。
<a name="lambda-s3-tutorial-deploy"></a>

1. [Lambdaのコンソール](https://console.aws.amazon.com/lambda/home)を開きます。

1. **[関数を作成]** を選択します。

1. **Author from scratch** (製作者を最初から) を選択します。

1. **基本的な情報** セクションに、名前として **cron** と入力します。

1. [**Runtime**] で、[**Java 8**] を選択します。

1. **[Use an existing role (既存のロールの使用)] ** を選択し、**lambda-support** (作成した IAM ロール) を選択します。

1. **[関数を作成]** を選択します。

1. [**コードエントリタイプ**] で、[**.ZIP またはファイルをアップロード**] を選択します。

1. **アップロード** を選択し、作成した JAR ファイルを参照します。

1. **ハンドラー**を使用する場合、関数の完全修飾名を入力します。例えば、**com.example.tags.Handler:handleRequest** (**com.example.tags** はパッケージを指定し、**ハンドラー**は :: およびメソッド名が続くクラスです）。

1. **[保存]** を選択します。

## Lambda メソッドをテストする
<a name="lambda-s3-tutorial-test"></a>

チュートリアルのこの時点で、Lambda 関数をテストできます。

1. Lambda コンソールで、**Test** タブをクリックし、次の JSON を入力します。

   ```
                    {
   "flag": "true"
    }
   ```  
![フラグのキーと値のペアが表示されたテストイベント JSON エディタ。[削除] ボタン、[形式] ボタン、[呼び出し] ボタンがある。](http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/images/v2-image-tutorial-test.png)
**注記**  
**true** を送るとデジタルアセットにタグを付け、**false** を送るとタグを削除します。

1. [**呼び出し** ボタンを選択します。Lambda 関数が呼び出されると、成功したメッセージが表示されます。  
![オペレーションが成功したことを示す実行結果メッセージ。[詳細] ボタンがある。](http://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/images/v2-image-tutorial-success.png)

おめでとうございます。Amazon S3 バケットにあるディフィタルアセットにタグを自動的に適用する AWS Lambda関数を作成しました。このチュートリアルの冒頭で説明したように、必ずこのチュートリアルの実行中に作成したリソースをすべて終了し、課金されないようにしてください。

その他のAWSマルチサービスの例については、[AWS「Documentation SDK examples GitHub repository](https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/usecases)」を参照してください。