文字認識ライブラリ okrabyte を使ってS3にPUTされた画像をAWS Lambdaで文字認識する
このエントリはAWS Lambda Advent Calendar 2014 - Qiitaの(本当は9日目の)記事です。
(ちょっとAWS Lambdaのアカウント取得に手間取ってしまって遅刻してしまいました。。すいません。。)
AWS Lambda とは
AWS LambdaはAmazonが作った新サービスであり、S3の変更やDynamoDBの変更をフックしてNode.jsの関数を実行するという仕組みになっています。これを使うと、例えばデータが変更された後にPush Notificationを出したり、S3にアップロードされた画像のサムネイル画像を作成したりといったことが可能になります。
今回はこのAWS Lambdaを使ってS3でPUTされた画像から文字認識をしてみようという試みです。文字認識した結果をDynamoDBとかに置いて検索に利用すれば、画像内に書かれた文字で検索できるようになったりしてハッピー。
okrabyte
okrabyteはAWS Lambdaで文字認識するために僕が書いたライブラリです。
C++で書かれた文字認識ライブラリをemscriptenによってJS化されたocrad.jsを内部的に利用しています。ocrad.jsがcanvasを内部的に使っていたんですが、そこをcanvasじゃなくても文字認識できるようにアダプターを書いてnode.jsっぽく非同期に呼べるように加工したものです。*1
Getting Started okrabyte
こんな感じにインストールして、
$ npm install okrabyte -S
こういう画像を用意して、
以下のようにAPIを呼び出せばOK!
var okrabyte = require("okrabyte"); okrabyte.decodeFile("test/fixture/hello_world.png", function(error, data){ console.log(data); // Hello World! });
okrabyteの詳細はまた今度書きます。
ではこのokrabyteを使ってAWS Lambdaで画像認識をしてみましょう。
S3でPUTされた画像をAWS Lambda から取得して文字認識する
S3から画像をGETして画像認識させるために以下のようなファイルを書きます。
var aws = require('aws-sdk'); var s3 = new aws.S3({apiVersion: '2006-03-01'}); var okrabyte = require('okrabyte'); exports.handler = function(event, context) { var bucket = event.Records[0].s3.bucket.name; var key = event.Records[0].s3.object.key; s3.getObject({Bucket:bucket, Key:key}, function(err,data) { if (err) { console.log('error getting object ' + key + ' from bucket ' + bucket + '. Make sure they exist and your bucket is in the same region as this function.'); context.done('error','error getting file'+err); } else { // 今のところ、okrabyteがpng以外をサポートしてないので一旦エラーにする if (data.ContentType !== "image/png") context.done('error', 'support png only.'); // ここで、okrabyteを使って文字認識させる okrabyte.decodeBuffer(data.Body, function(err, data){ if (err) context.done('error', '' + err); // 一旦stdoutに出力させる、ここをDynamoDBへのinsertに変えるとかすれば、画像内の文字で画像を検索できるようになって捗りそう。 console.log(data); context.done(null,''); }); } } ); };
Execution Role
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:*" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::*" ] } ] }
Invoke Role
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Resource": [ "*" ], "Action": [ "lambda:InvokeFunction" ] } ] }
Demo
動かしてみましょう。
S3から画像をPUTする。
S3コンソールからUploadボタンを押して、先ほどの画像をUploadします。
Noderから見るAWS Lambda
AWS LambdaはNode.jsの可能性の一つであり、イベント駆動でサービスを構築できる非常に面白い機能です。これまで、Node.jsでタブーとされてきたイベントループを止めるようなCPUを使った処理が、AWS Lambda経由で実行されることで自分のサービス内のプロセスのイベントループを止める事無く実現できます。つまり、Node.jsが苦手と言われてきたCPUを使ったイベントループを止めるような処理をAWS Lambda側に逃がして非同期で処理させることができるようになります。
AWS Lambdaへの要望
文字認識ライブラリとして代表的なのはtesseractなんですが、こういう任意のコマンドが事前にビルドできると嬉しいなと思いました。
(まぁtesseractがなかったので、okrabyteみたいなpure JSのOCRライブラリができたので、それはそれで副次的な効果を産んで良いとは思いますが。)
まとめ
- okrabyteっていう文字認識ライブラリを作りました。
- AWS LambdaでS3にPUTされた画像を使って文字認識をしてみました。
今回使ったコード一式は以下のリポジトリに上げました。
そんなAWS Lambdaですが、今日は初のmeetupが開催されるようです。
AWS Lambda Meetup #0 - connpass
僕は補欠で応募中ですが、既に30人以上の補欠がいるので、ちょっと厳しいかも。またなにか作ったらお知らせします!