2022年9月14日水曜日

AWS Rekognition (5) : カスタムラベルの利用

物体抽出したい画像が集まったら、オリジナルの学習モデルをカスタムラベルで作成します。

(1) Custom Labelsのプロジェクトを作成

Amazon RekognitionからCustom Labels -> Use Custom Labels -> Get Started -> S3バケットの作成をしていきます。このS3バケットに画像を入れて学習をしていきます。



ProjectsからCreate Projectをして作成していきます。
プロジェクト名を指定して、プロジェクトを作成します。

(2) 学習用データセットを作成
プロジェクトが作成されると下の図のように、順番に何をするかが示されます。最初はデータセットを作成していきます。

1のcreate datasetをクリックします。
いくつかの選択肢がありますが、今回は
Start with a single dataset」:学習データ、テストデータには自動で分割
Import images from S3 bucket」:S3にアップロードしたデータを利用
の2つを選んで実施します。

いったんここでS3に移動して、画像をアップロードします。
今回は imageフォルダの中の3つのフォルダに入っている画像30枚を利用します。Custom Labelで強制的に作られたS3バケットの中にimageフォルダをアップロードしておきます。
アップロードが終わると、下記の画面が見えます。

右上にある「Copy S3 URI」でリンクをコピーします。
コピーしたら、もう一度Custom Labelsに戻ります。
S3 URIをコピーし、「Automatically assign image-level labels to images based on the folder name」にチェックを入れます。これでフォルダ名がラベル名となります。

ここまでできたら、Create Datasetをクリックします。画像が取り込まれると、ラベルのついた画像があることがわかります。

注意:AWS Academyで上記を実行すると、Network エラーになるかもしれません。なった場合は、S3からの同期ではなく、自分のPCからアップロードを選択して、一つひとつやってみて下さい。

(3) 学習の実行
「3. Train model」でボタンを押し実行します。

trainが始まり、進行中だと表示されます。数時間、学習に時間がかかります。
表示が変わり、精度など確認できれば学習完了です。


(4) 学習モデルの利用
作成した学習モデルを使っていきます。学習済みのプロジェクトから上のメニューで「Use Model」を選択します。下の API Code でPythonを選択すると、pythonコードが出てきます。

ソースコードには、Start Model、Analyze Image、Stop Modelがあります。Start、Stopはプロジェクトのボタンでもできます。Startは時間がかかります。Stopはすぐにできます。利用しないときはStopしましょう。ここではAnalyze Imageを見ていきます。PythonコードをSageMakerで実行していくので、SageMakerを開きます。
!pip install boto3
でライブラリをインストールしておきます。モデルをStartした後、以下を実行します。AWS Academyの場合はセッション情報も必要です。

import boto3
import io
from PIL import Image, ImageDraw, ExifTags, ImageColor, ImageFont
def display_image(bucket,photo,response):
# Load image from S3 bucket
s3_connection = boto3.resource(
's3',
aws_access_key_id='xxxxxxxx',
aws_secret_access_key='xxxxxx',
region_name='xxxxxx'
)
s3_object = s3_connection.Object(bucket,photo)
s3_response = s3_object.get()
stream = io.BytesIO(s3_response['Body'].read())
image=Image.open(stream)
# Ready image to draw bounding boxes on it.
imgWidth, imgHeight = image.size
draw = ImageDraw.Draw(image)
# calculate and display bounding boxes for each detected custom label
print('Detected custom labels for ' + photo)
for customLabel in response['CustomLabels']:
print('Label ' + str(customLabel['Name']))
print('Confidence ' + str(customLabel['Confidence']))
if 'Geometry' in customLabel:
box = customLabel['Geometry']['BoundingBox']
left = imgWidth * box['Left']
top = imgHeight * box['Top']
width = imgWidth * box['Width']
height = imgHeight * box['Height']
fnt = ImageFont.truetype('/Library/Fonts/Arial.ttf', 50)
draw.text((left,top), customLabel['Name'], fill='#00d400', font=fnt)
print('Left: ' + '{0:.0f}'.format(left))
print('Top: ' + '{0:.0f}'.format(top))
print('Label Width: ' + "{0:.0f}".format(width))
print('Label Height: ' + "{0:.0f}".format(height))
points = (
(left,top),
(left + width, top),
(left + width, top + height),
(left , top + height),
(left, top))
draw.line(points, fill='#00d400', width=5)
image.show()
def show_custom_labels(model,bucket,photo, min_confidence):
client=boto3.client(
'rekognition',
aws_access_key_id='xxxxxxxxxxxx',
aws_secret_access_key='xxxxxxxxx',
region_name='xxxxxxxxxxxxxxxx'
)
#Call DetectCustomLabels
response = client.detect_custom_labels(Image={'S3Object': {'Bucket': bucket, 'Name': photo}},
MinConfidence=min_confidence,
ProjectVersionArn=model)
# For object detection use case, uncomment below code to display image.
display_image(bucket,photo,response)
return len(response['CustomLabels'])
def main():
bucket='mzn-publicproperty'
photo='img/カーブミラー/49685365707_9c29a8c40a_z.jpg'
model='arn:aws:rekognition............'
min_confidence=95
label_count=show_custom_labels(model,bucket,photo, min_confidence)
print("Custom labels detected: " + str(label_count))
if __name__ == "__main__":
main()
view raw Analyze_Image hosted with ❤ by GitHub
図のように検出ができればOKです。

色々書きましたが、AWS RekognitionにあるTutorialの動画4本がわかりやすいので、そちらを参照して下さい。

2022年9月9日金曜日

AWS Rekognition (4) : 教師画像の収集

 自分がターゲットにしたい対象物を認識させるためには、その対象物の教師画像を用意して学習させなければなりません。今回はFlickrという画像収集サイトのAPIを使って、まとめて画像を取得してきます。どのようなpython環境(Google Colab)でもできますが、ここではSageMakerで実施していきます。

(1) Flickr APIの用意

Flickrでは様々な画像を取得できますが、一度に取得するためには、APIを使った方が便利です。詳しいページもたくさんあるので、下記を参考にしてFlickr APIキーを取得して下さい。

https://worktoolsmith.com/flickr-api-key/


http://kwski.net/api/807/

(2) ライブラリのインストール

最初にFlickr APIを使うためのライブラリをインストールしておきます。Jupyterファイルを用意して、ファイル名を付けて保存しておきます。そのファイルに下記2つのコマンドを書き、インストールします。

!pip install flickrapi

!pip install retry

(3) プログラムの実行

最初に画像を格納するフォルダを作成します。今回は「image」とします。これをjupyterファイルと同じ階層に用意します。imageの中にキーワードをフォルダ名として作成し、そのキーワードフォルダの中に画像を10枚程度保存していきます。以下のプログラムを実行します。

import os
import time
import traceback
import flickrapi
from urllib.request import urlretrieve
import sys
from retry import retry
import sys
flickr_api_key = "xxxxxxxxxxxxxxxxxxxx"
secret_key = "xxxxxxxxxxxxxxxxxxxxxxx"
keyword = '富士山'
@retry()
def get_photos(url, filepath):
urlretrieve(url, filepath)
time.sleep(1)
if __name__ == '__main__':
flicker = flickrapi.FlickrAPI(flickr_api_key, secret_key, format='parsed-json')
response = flicker.photos.search(
text=keyword,
per_page=10,
media='photos',
sort='relevance',
safe_search=1,
extras='url_q,license'
)
photos = response['photos']
try:
if not os.path.exists('./image/' + keyword):
os.mkdir('./image/' + keyword)
for photo in photos['photo']:
url_q = photo['url_q']
filepath = './image/' + keyword + '/' + photo['id'] + '.jpg'
get_photos(url_q, filepath)
except Exception as e:
traceback.print_exc()
view raw flickr hosted with ❤ by GitHub

プログラムをキーワードを富士山として実行すると、./image/富士山/ フォルダができ、その中に画像が格納されます。

他のキーワードでも検索を行うと、フォルダが作成され画像が格納されます。

このような形で教師画像を取得することができました。

(4) 取得画像のダウンロード

S3にプログラムで転送してもいいのですが、ちょっと面倒なのでここでは、手元にダウンロードしてから、改めてS3にアップロードします。jupyterファイルに次を追加します。jupyterファイルと同じディレクトリにあるimageフォルダの中身を全てzip化します。

!zip -r image.zip ./image/*

zipファイルが作成されますので、ダウンロードして中身を確認して下さい。

これでS3にアップする準備ができました。