

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Lambda 和 Python 偵測影像中的標籤
<a name="lambda-s3-tutorial-python"></a>

 AWS Lambda 是一種運算服務，您可以用來執行程式碼，而無需佈建或管理伺服器。您可以從 Lambda 函數中呼叫 Rekognition API 作業。下列指示展示如何在 Python 建立 Lambda 函數，可以呼叫 `DetectLabels`。

Lambda 函數中呼叫 `DetectLabels`，傳回影像中偵測到的一系列標籤，以及偵測所依據的可信度層級。

這些指示包括範例 Python 程式碼，其中示範如何呼叫 Lambda 函數，並提供來自 Amazon S3 儲存貯體或本機電腦的映像檔。

請確認您選擇的影像符合 Rekognition 的限制。如需有關影像檔案類型和大小限制的資訊，請參閱 Rekognition 中的[準則和配額](https://docs.aws.amazon.com/rekognition/latest/dg/limits.html)和 [DetectLabels API 參考](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_DetectLabels.html)。

## 建立 Lambda 函數 (主控台)
<a name="lambda-s3-tutorial-python-create"></a>

在此步驟中，您會建立空白的 Lambda 函數和 IAM 執行角色，讓 Lambda 函數呼叫 `DetectLabels` 操作。在稍後的步驟中，您可以新增原始程式碼，並選擇性地將圖層新增至 Lambda 函數。

如果您使用存放於 Amazon S3 儲存貯體中的文件，此步驟也會示範如何授與存放文件之儲存貯體的存取權。

**建立 AWS Lambda 函數 （主控台）**

1. 登入 AWS 管理主控台 並在 https：//[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 開啟 AWS Lambda 主控台。

1. 選擇**建立函數** 。如需詳細資訊，請參閱[使用主控台建立 Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html)。

1. 選擇下列選項：
   + 選擇**從頭開始撰寫**。
   + 輸入**函數的名稱**。
   + 若為**執行期**，請選擇最新版本的 Python。
   + 對於 **Architecture** (架構)，選擇 **x86\$164**。

1. 選擇**建立函數**來建立 AWS Lambda 函數。

1. 在函數頁面上，選擇**組態**標籤。

1. 在**許可**窗格上，**執行角色**下，選擇要在 IAM 主控台中開啟角色的角色名稱。

1. 在**許可**標籤中，選擇**新增許可** ，然後**建立內嵌政策**。

1. 選擇 **JSON** 標籤，並預設文字取代為下列內容：

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Action": "rekognition:DetectLabels",
               "Resource": "*",
               "Effect": "Allow",
               "Sid": "DetectLabels"
           }
       ]
   }
   ```

------

1. 選擇**檢閱政策**。

1. 輸入原則的名稱，例如 * DetectLabels 存取 *。

1. 選擇**建立政策**。

1. 如果您要將文件存放於 Amazon S3 儲存貯體中進行分析，則必須新增 Amazon S3 存取政策。若要這麼做，請在 AWS Lambda 主控台中重複步驟 7 到 11，然後進行下列變更。

   1. 對於步驟 8，請使用下列原則。將儲存*貯體/資料夾路徑*取代為您要分析之文件的 Amazon S3 儲存貯體和資料夾路徑。

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Sid": "S3Access",
                  "Effect": "Allow",
                  "Action": "s3:GetObject",
                  "Resource": "arn:aws:s3:::bucket/folder path/*"
              }
          ]
      }
      ```

------

   1. 對於步驟 10，請選擇不同的原則名稱，例如 *S3Bucket-access*。

## (可選) 建立圖層 (主控台)
<a name="lambda-s3-tutorial-python-layer"></a>

您不需要執行此步驟即可使用 Lambda 函數並呼叫 `DetectLabels`。

`DetectLabels` 操作包含在預設的 Lambda Python 環境中，作為適用於 Python (Boto3) 的 AWS SDK 的一部分。

如果 Lambda 函數的其他部分需要不在預設 Lambda Python 環境中的最新 AWS 服務更新，則可以執行此步驟，將最新的 Boto3 SDK 版本作為 layer 新增至函數。

若要將 SDK 新增為圖層，您必須先建立包含 Boto3 SDK 的壓縮檔案歸檔。然後，建立一個圖層並將 zip 檔案存檔新增到圖層中。如需詳細資訊，請參閱[搭配使用圖層和 Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-using)。

**建立並新增圖層（主控台）**

1. 開啟命令提示字元並輸入下列命令，以使用最新版本的 AWS SDK 建立部署套件。

   ```
   pip install boto3 --target python/.
   zip boto3-layer.zip -r python/
   ```

1. 請注意您在此程序的步驟 8 中使用的壓縮檔案 (boto3-layer.zip) 的名稱。

1. 在 https：//[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 開啟 AWS Lambda 主控台。

1. 在導覽視窗中，選擇 **圖層**。

1. 選擇 **建立圖層**。

1. 輸入 **名稱** 和 **描述** 的值。

1. 針對**程式碼項目類型**，選擇**上傳 .zip 檔案**並選取**上傳**。

1. 在對話方塊中，選擇您在此程序的步驟 1 中建立的壓縮檔案封存 (boto3-layer.zip)。

1. 對於 ** 相容的執行期 **，請選擇最新版本的 Python。

1. 選擇**建立**，以建立資料表。

1. 選擇導覽視窗選單圖示。

1. 在導覽視窗中，選擇**函數**。

1. 在資源清單中，選擇您先前在 [](#lambda-s3-tutorial-python-create) 中建立的函數。

1. 選取**程式碼**標籤。

1. 在 **圖層** 部份，選擇 **新增圖層**。

1. 選擇 **自訂圖層**。

1. 在**自訂圖層**中，選擇您在步驟 6 中輸入的圖層名稱。

1. 在 **版本**中，選擇圖層版本,該版本應為 1。

1. 選擇 **新增**。

## 新增 Python 程式碼 (主控台)
<a name="lambda-s3-tutorial-python-console-code"></a>

在此步驟中，您可以透過 Lambda 主控台程式碼編輯器將 Python 程式碼新增至 Lambda 函數。程式碼會使用 `DetectLabels` 作業偵測影像中的標籤。其傳回在映像中偵測到的標籤的數組，以及偵測到的標籤的可信度水平。

您提供給 `DetectLabels` 作業的文件可以位於 Amazon S3 儲存貯體或本機電腦中。

**若要新增 Python 程式碼 (主控台)**

1. 瀏覽至**程式碼**標籤。

1. 在程式碼編輯器中，以下列程式碼取代 **lambda\$1function.py** 中的程式碼：

   ```
   import boto3
   import logging
   from botocore.exceptions import ClientError
   import json
   import base64
   
   # Instantiate logger
   logger = logging.getLogger(__name__)
   
   # connect to the Rekognition client
   rekognition = boto3.client('rekognition')
   
   def lambda_handler(event, context):
   
       try:
           image = None
           if 'S3Bucket' in event and 'S3Object' in event:
               s3 = boto3.resource('s3')
               s3_object = s3.Object(event['S3Bucket'], event['S3Object'])
               image = s3_object.get()['Body'].read()
   
           elif 'image' in event:
               image_bytes = event['image'].encode('utf-8')
               img_b64decoded = base64.b64decode(image_bytes)
               image = img_b64decoded
   
   
           elif image is None:
               raise ValueError('Missing image, check image or bucket path.')
   
           else:
               raise ValueError("Only base 64 encoded image bytes or S3Object are supported.")
   
           response = rekognition.detect_labels(Image={'Bytes': image})
           lambda_response = {
               "statusCode": 200,
               "body": json.dumps(response)
           }
           labels = [label['Name'] for label in response['Labels']]
           print("Labels found:")
           print(labels)
   
       except ClientError as client_err:
   
          error_message = "Couldn't analyze image: " + client_err.response['Error']['Message']
   
          lambda_response = {
              'statusCode': 400,
              'body': {
                  "Error": client_err.response['Error']['Code'],
                  "ErrorMessage": error_message
              }
          }
          logger.error("Error function %s: %s",
                       context.invoked_function_arn, error_message)
   
   
       except ValueError as val_error:
   
           lambda_response = {
               'statusCode': 400,
               'body': {
                   "Error": "ValueError",
                   "ErrorMessage": format(val_error)
               }
           }
           logger.error("Error function %s: %s",
                        context.invoked_function_arn, format(val_error))
   
       return lambda_response
   ```

1. 若要部署您的 Lambda 函數，請選擇**部署**。

## 若要新增 Python 程式碼 (主控台)
<a name="lambda-s3-tutorial-python-invoke"></a>

現在您已經建立 Lambda 函數，可以叫用該函數，以偵測影像中的標籤。

在此步驟中，您可以在電腦上執行 Python 程式碼，該程式碼會將本機映像或 Amazon S3 儲存貯體中的映像傳遞至 Lambda 函數。

請務必在 AWS 建立 Lambda 函數的相同區域中執行程式碼。您可以在 AWS Lambda 主控台函數詳細資訊頁面的導覽列中檢視 Lambda 函數的區域。

如果 Lambda 函數傳回逾時錯誤，請延長 Lambda 函數的逾時期間。如需詳細資訊，請參閱[設定函數逾時 (主控台)](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html#configuration-timeout-console)。

如需從程式碼調用 Lambda 函數的更多資訊，請參閱 [ 調用 AWS Lambda 函數 ](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html)。

**部署 Lambda 函數**

1. 如果您尚未執行以下操作，請現在執行：

   1. 請確定使用者具有 `lambda:InvokeFunction` 權限。您可以使用下列專案：

      您可以從 [Lambda 主控台](https://console.aws.amazon.com/lambda/)的函數概觀取得 Lambda 函數的 ARN。

      若要提供存取權，請新增權限至您的使用者、群組或角色：
      + 中的使用者和群組 AWS IAM Identity Center：

        建立權限合集。請按照《*AWS IAM Identity Center 使用者指南*》中的[建立權限合集](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html)說明進行操作。
      + 透過身分提供者在 IAM 中管理的使用者：

        建立聯合身分的角色。遵循《*IAM 使用者指南*》的[為第三方身分提供者 (聯合) 建立角色](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html)中的指示。
      + IAM 使用者：
        + 建立您的使用者可擔任的角色。請按照《*IAM 使用者指南*》的[為 IAM 使用者建立角色](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html)中的指示。
        + (不建議) 將政策直接附加至使用者，或將使用者新增至使用者群組。請遵循《*IAM 使用者指南*》的[新增許可到使用者 (主控台)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console) 中的指示。

   1. 安裝和設定適用於 Python 的 AWS SDK。如需詳細資訊，請參閱[步驟 2：設定 AWS CLI 和 AWS SDKs](setup-awscli-sdk.md)。

1. 將下列程式碼複製到名為 `client.py` 的檔案。

   ```
   import boto3
   import json
   import base64
   import pprint
   
   # Replace with the name of your S3 bucket and image object key
   bucket_name = "name of bucket"
   object_key = "name of file in s3 bucket"
   # If using a local file, supply the file name as the value of image_path below
   image_path = ""
   
   # Create session and establish connection to client['
   session = boto3.Session(profile_name='developer-role')
   s3 = session.client('s3', region_name="us-east-1")
   lambda_client = session.client('lambda',  region_name="us-east-1")
   
   # Replace with the name of your Lambda function
   function_name = 'RekDetectLabels'
   
   def analyze_image_local(img_path):
   
       print("Analyzing local image:")
   
       with open(img_path, 'rb') as image_file:
           image_bytes = image_file.read()
           data = base64.b64encode(image_bytes).decode("utf8")
   
           lambda_payload = {"image": data}
   
           # Invoke the Lambda function with the event payload
           response = lambda_client.invoke(
               FunctionName=function_name,
               Payload=(json.dumps(lambda_payload))
           )
   
           decoded = json.loads(response['Payload'].read().decode())
           pprint.pprint(decoded)
   
   def analyze_image_s3(bucket_name, object_key):
   
       print("Analyzing image in S3 bucket:")
   
       # Load the image data from S3 into memory
       response = s3.get_object(Bucket=bucket_name, Key=object_key)
       image_data = response['Body'].read()
       image_data = base64.b64encode(image_data).decode("utf8")
   
        # Create the Lambda event payload
       event = {
           'S3Bucket': bucket_name,
           'S3Object': object_key,
           'ImageBytes': image_data
       }
   
       # Invoke the Lambda function with the event payload
       response = lambda_client.invoke(
               FunctionName=function_name,
               InvocationType='RequestResponse',
               Payload=json.dumps(event),
               )
   
       decoded = json.loads(response['Payload'].read().decode())
       pprint.pprint(decoded)
   
   def main(path_to_image, name_s3_bucket, obj_key):
   
       if str(path_to_image) != "":
           analyze_image_local(path_to_image)
       else:
           analyze_image_s3(name_s3_bucket, obj_key)
   
   if __name__ == "__main__":
       main(image_path, bucket_name, object_key)
   ```

1. 執行程式碼。如果文件位於 Amazon S3 儲存貯體中，請確定该文件是與之前在 [](#lambda-s3-tutorial-python-create) 的步驟 12 中指定的相同儲存貯體。

   如果成功，您的程式碼會針對文件中偵測到的每個區塊類型傳回部分 JSON 回應。