中小ーーーーーー!企業ーーーーーーーーー!!!
(この記事は ちゅらデータ Advent Calendar 2021 15日目 の記事となります)
ネタすぎるのでQiitaに書くことじゃないって怒られたら個人ブログに移動します
そういえば今年はこんなLTしました
酒飲みすぎて 忘れてました
無事フラグ回収しました
思い出しながら書いていきます(今 2021/12/15 午前5:17)
Label Studioってなんですか?
Label Studioは、OSSのデータラベリングツールです。Webアプリケーションとして利用することが可能です。個人的にはよくあるのは画像メインだなって思いますが、こちらは音や時系列、テキストデータにもラベリングすることができます。
使ってみてとても便利だなって思ったのは、DockerやPython使ってたら導入が楽なのと、Web画面でサクサク動くのもそうなんですが、フロントがJavaScriptフレームワーク(React)で組まれていて、バックエンドがAPI(Python)で開発されています。また、APIとやり取りするためにtoken発行することができます。なので、Web画面でできないことは、ユーザー側で開発したコードをAPI経由で連携することができるので良いなって思いました。
とても良いおもちゃありがとうございます これでデータ収集が無限にはかどりますね!
クラウドサービスにも似たようなのあるよ?
わかります、SageMakerのツールとか複数人で対応するとか便利そうでした。が、高いんです。企業はよくても個人はちょっときついなと。
Label Studioにいるこいつはなんですか?
たぬきです
たぬきと思ってたけどたぬきじゃないかも
Label Studio、ぼ・・・ぼくにできるかなぁ?
ノープロブレム、トムの勝ちデース DockerやPython使っている人は瞬殺です。
# Install the package
$ pip install -U label-studio
# Launch it!
$ label-studio
# Run latest Docker version
$ docker run -it -p 8080:8080 -v `pwd`/mydata:/label-studio/data heartexlabs/label-studio:latest
# Now visit http://localhost:8080/
Label Studio使って何やりたいんですか?
死ぬまでにゴジラをAIで表現したいなって思っています。そのための準備です。
本題が迷子になっていますよ?
アッハイ。本題です。
(本題) 利用のためにアクセスキーは必須なの?
レースキュー!ソールジャー!!もっと速くーーーーーー!!!!!(思い出している)
危険なバトルつきぬけてゆくーーーー\ゴーゴファイブ/(思い出している)
レースキュー!ソールジャー!!もっと強くーーーーーー!!!!!(思い出している)
かがやく勇気をいま!とーがーらーせーーーてーーーーーー!!!!!(思い出している)
思い出した。
AWS上で検証しました。
EC2起動してDocker install後、Label Studioを起動してProjectを作成します。Object Detectionで作成しました。
また、S3に画像をおいて、Syncできるようにします。IAMでEC2にS3 Full Accessを付与すれば今回はおkとします。(本当は絞ったほうがいい)
適当にアノテーション付与して、YOLOのデータセットをexportしようとすると。。。
画像は空っぽで、labelだけ落ちてきます。なぜ???
最悪S3から落とせばいいのですが、紐付けるのが面倒なのでできればLabel Studioからまとめて落としたいです。
そこでなぜ失敗するのか調査したところ、Docker側でエラーが出力されていることに気が付きました。
[2021-12-14 21:38:21,497] [label_studio_converter.converter::convert_to_yolo::580] [ERROR] Unable to download s3://${aipa-images}/input/f81eab74-1750-11ec-bfb8-916757824fb9_2002_0_480_640.jpg. The item {'id': 1, 'input': {'image': 's3://${aipa-images}/input/f81eab74-1750-11ec-bfb8-916757824fb9_2002_0_480_640.jpg'}, 'output': defaultdict(<class 'list'>, {'label': [{'x': 6.406250000000003, 'y': 13.124999999999995, 'width': 77.49999999999997, 'height': 86.87499999999982, 'rotation': 0, 'rectanglelabels': ['Godzilla'], 'type': 'RectangleLabels', 'original_width': 640, 'original_height': 480}]}), 'completed_by': 1, 'annotation_id': 1, 'created_at': '2021-12-14T21:17:45.591190Z', 'updated_at': '2021-12-14T21:17:45.591222Z', 'lead_time': 15.235} will be skipped
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/label_studio_converter/converter.py", line 576, in convert_to_yolo
image_path = download(image_path, output_image_dir, project_dir=self.project_dir,
File "/usr/local/lib/python3.8/dist-packages/label_studio_converter/utils.py", line 129, in download
r = requests.get(url)
File "/usr/local/lib/python3.8/dist-packages/requests/api.py", line 75, in get
return request('get', url, params=params, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/requests/api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 542, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 649, in send
adapter = self.get_adapter(url=request.url)
File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 742, in get_adapter
raise InvalidSchema("No connection adapters were found for {!r}".format(url))
requests.exceptions.InvalidSchema: No connection adapters were found for 's3://${aipa-images}/input/f81eab74-1750-11ec-bfb8-916757824fb9_2002_0_480_640.jpg'
Pythonのrequestsモジュールがだいたい締めていますが、スタックトレースの上部分を確認すると、エラーの元はこちらのようです。
File "/usr/local/lib/python3.8/dist-packages/label_studio_converter/converter.py", line 576, in convert_to_yolo
image_path = download(image_path, output_image_dir, project_dir=self.project_dir,
File "/usr/local/lib/python3.8/dist-packages/label_studio_converter/utils.py", line 129, in download
r = requests.get(url)
Label StudioはOSSでGithubで公開されているので、該当のコードを見に行きます。
なるほど???
よくわかりませんが、s3に対してrequests moduleでGETを投げているようですね。
はて???そもそもできるんだっけ?通常はboto3を使いそうですが、なぜだろう???
当時、Web画面からでしか状況を確認してなかったので、アクセスキーが足りないからだ!って思っていたのですが、LT直前になって動かないから、コードみてみると???となったことを思い出しました。そうだ。そうだった。
話し戻ります。何かしら設定違いがあって、分岐に失敗しているのかしら?とboto3を検索キーワードにして、リポジトリを検索するのですが、boto3が使われていない。なるほど?
とりあえず、コンテナ上からboto3でs3からダウンロードできそうか試してみます。
ubuntu@ip-1-1-1-1:~$ docker exec -it ${container_id} /bin/bash
root@aaa:/label-studio# pip3 install boto3
Requirement already satisfied: boto3 in /usr/local/lib/python3.8/dist-packages (1.16.28)
なるほど?
root@aaa:/label-studio# python3
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import boto3
>>>
なるほど。インストールされているようです。はて?
時間がないので、とりあえず直接書き換えてみます。
root@aaa:/label-studio# vim /usr/local/lib/python3.8/dist-packages/label_studio_converter/utils.py
bash: vim: command not found
vimがインストールされていない重大な問題がでたのでインストールします。
root@aaa:/label-studio# apt update -y && apt install -y vim
root@aaa:/label-studio# vim /usr/local/lib/python3.8/dist-packages/label_studio_converter/utils.py
書き込めるようになったので、こんな感じで書き換えます。
128 if download_resources:
129 if url.find('s3') > -1:
130 import boto3
131 client = boto3.client('s3')
132 a = url.split('/')
133 bucket = a[2]
134 key = '/'.join(a[3:])
135 res = client.get_object(Bucket=bucket, Key=key)
136 r = res['Body'].read()
137 with io.open(filepath, mode='wb') as fout:
138 fout.write(r)
139 else:
140 r = requests.get(url) # 元のコード
141 r.raise_for_status()
142 with io.open(filepath, mode='wb') as fout:
143 fout.write(r.content)
で、サーバを再起動したいですが。。。再起動の手順がない・・・?なるほど?
コード読んでいるとどうやらDjangoで動いているようです。Djangoあんまり詳しくないけど、hot reloadみたいなことができたような。。。
まじかー、めんどい。
よくわからないですが、コンテナ内でserverプロセス殺しても死ななかったので、一旦諦めてリポジトリをcloneしてきます。
# コンテナ停止後
$ sudo apt install python3-pip
$ git clone https://github.com/heartexlabs/label-studio.git
# 起動後、初期設定からスタートしてしまうので、設定済みのデータは移動
$ sudo mv mydata label-studio/
$ cd label-studio/
$ vim deploy/requirements.txt
label-studio-converterを書き換えたいのですが、こいつは外部モジュールとして分離されていたので requirements.txt
ではコメントアウトして、こいつも持ってきます。
# label-studio-converter==0.0.36
$ git clone https://github.com/heartexlabs/label-studio-converter.git
$ cd label-studio-converter/
$ vim label_studio_converter/utils.py
さっきと同じように書き換える。書き換えたら、pipを叩く。
$ pip3 install -e .
$ cd ../
$ pip3 install -e .
# あとでエラーになるので事前対応
$ pip3 uninstall attr
# あとはlabel-studioのdocumentに沿って起動する
$ python3 label_studio/manage.py migrate
# migrationしたけど、パスがhomeディレクトリになっている。。。
# そして、パスの指定方法がわからなかった。。。
# ので、権限変更して上書きすることにする
$ ls /home/ubuntu/.local/share/label-studio/
export label_studio.sqlite3 media
$ sudo chown ubuntu:ubuntu -R mydata/
$ cp -rf mydata/* /home/ubuntu/.local/share/label-studio/
$ python3 label_studio/manage.py runserver 0.0.0.0:8080
起動したらブラウザから、再度エクスポートしてみる。
わーいできた。疲れた。
そのまま使えないと思うのと、メンテナになぜこんな事になっているの?と聞く必要がありますが、皆様PRチャンスです。(僕がやれ?アッハイ)
(本題) 結局どうやってAPIと連携したの?
TODO: 疲れたので、今年中にあげる。
以上です。
子供が起きたので以上とさせていただきます。ありがとうございました。
ちゅらデータ Advent Calendar 2021 16日目 は aipa さんによる 「Python VS Anaconda VS ちゅらデータ 65535(1GB) ~呪われたプロジェクトの仕様変更~ 」(たぶん)です!来週もまたみてね。