Lambda, Amazon Textractを利用してS3に保存した画像からテキストを抽出する(Golang)

# はじめに

S3に画像を追加すると、自動的にその画像内のテキストを抽出し、テキストファイルとして保存する、というシステムを[Lambda](https://aws.amazon.com/jp/lambda/)・[Amazon Textract](https://aws.amazon.com/jp/textract/)・Golangを利用して作りました。

作成手順を共有します。

### 完成イメージ

![ocr.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/80ef8a6e-a645-99ad-8d4e-ab1f62fb8046.png)


### Textractとは

[Amazon Textract](https://aws.amazon.com/jp/textract/)はAWSが提供するクラウドOCRサービスです。詳しくは以下の記事を参照してください。

https://qiita.com/windows222/items/07c3683c052d6e2bb6a4

#### 料金

利用料金は[こちらのページ](https://aws.amazon.com/jp/textract/pricing/)にまとまっています。無料枠で使用可能です。

#### 注意点

- 日本リージョンに対応していない
- 日本語には対応していない

#### ブラウザで試す

[こちらのページ](https://console.aws.amazon.com/textract/home?region=us-east-1#/)でかんたんに試すことができます。

# 実装手順

## S3バケットを作成する

手順は割愛しますが、入力用のバケットと出力用のバケットを作成します。
参考: https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/create-bucket-overview.html

## Lambdaを作成する

入力用のバケットへの画像ファイル(今回はpngファイルのみとします)書き込みをトリガーとするLambdaを作成します。
今回はランタイムにGolangを指定しました。

![lambda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/2da51c81-7676-d77b-ac44-0884f3bf3ad2.png)

実行ロールには以下の権限を持つものを指定してください。

- 入力用のS3バケットの読み込み権限
- 出力用のS3バケットの書き込み権限
- TextractのAPIへのアクセス権限(AmazonTextractFullAccess?)

### トリガーを設定

![trigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/de8336fb-ad5a-3e54-93f1-67e1496a2150.png)


### コード

コードは以下です。

```go
package main

import (
	"context"
	"strings"
	"time"

	"github.com/aws/aws-lambda-go/lambda"

	"github.com/aws/aws-sdk-go/service/s3/s3manager"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/textract"
)

func lambdaHandler(ctx context.Context, event events.S3Event) {
	// S3から画像オブジェクト取得
	sess := session.Must(session.NewSession(&aws.Config{
		Region: aws.String("us-east-1"),
	}))
	inputBucket := event.Records[0].S3.Bucket.Name
	inputKey := event.Records[0].S3.Object.Key

	// Textract API呼び出し
	textractSession := textract.New(sess)
	input := &textract.DetectDocumentTextInput{
		Document: &textract.Document{
			S3Object: &textract.S3Object{
				Bucket: aws.String(inputBucket),
				Name:   aws.String(inputKey),
			},
		},
	}
	resp, err := textractSession.DetectDocumentText(input)
	if err != nil {
		panic(err)
	}

	// レスポンスからテキストデータを抽出
	var output string
	for _, w := range resp.Blocks {
		if *w.BlockType == "LINE" { // PAGE, WORD, LINEから指定できる
			output += *w.Text
			output += "\n"
		}
	}

	// S3に書き込み
	outputBucket := // 出力用バケット名
	outputObjectKey := inputKey + time.Now().String() + ".txt"
	uploader := s3manager.NewUploader(sess)
	_, err = uploader.Upload(&s3manager.UploadInput{
		Bucket: aws.String(outputBucket),
		Key:    aws.String(outputObjectKey),
		Body:   strings.NewReader(output),
	})
	if err != nil {
		panic(err)
	}
}

func main() {
	lambda.Start(lambdaHandler)
}
```

### コードをアップロード

ビルドしてzipファイルを作成します。

```sh
% GOOS=linux go build -o lambda
% zip lambda.zip lambda 
```

zipファイルを作成したらアップロードします。
![zip-upload.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/5eabda9f-5c92-38c1-0ec3-0e717dadf158.png)


# 動かしてみる

以下の画像で試してみます([参考](https://raw.githubusercontent.com/aws-samples/amazon-textract-code-samples/master/python/simple-document-image.jpg))。
![textract-test.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/cf4009cf-2414-49a5-ce25-117df1b2a7ad.jpeg)

上記の画像を入力用のバケットに保存します。
![s3-upload.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/ce61a706-4cd4-110f-288e-2fd788bd5354.png)


すると出力用のバケットにテキストファイルが保存されます。
![s3-output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/e24f7093-4595-9838-98de-ab863f3224a1.png)


出力されたテキストファイルの中身は以下。

```text
Amazon.com, Inc. is located in Seattle, WA
It was founded July 5th, 1994 by Jeff Bezos
Amazon.com allows customers to buy everything from books to blenders
Seattle is north of Portland and south of Vancouver, BC.
```

# 上記をすべてコードで定義する

(まだやってないのでやり次第追記します)

# おわりに
今回は抽出したテキストをテキストファイルとして保存しましたが、CSVファイルとして出力する等、様々な方法で活用することが可能です。
間違い等あればご指摘お願いいたします。

# 参考文献
- [S3](https://aws.amazon.com/jp/s3/)
- [Lambda](https://aws.amazon.com/jp/lambda/)
- [Amazon Textract](https://aws.amazon.com/jp/textract/)
- [TextractのAPIドキュメント](https://docs.aws.amazon.com/textract/latest/dg/API_Reference.html)
- [LambdaとCloud Vision APIで日本語の文字抽出をしてみた](https://dev.classmethod.jp/articles/lambda_google-cloud-vision/)