ディープラーニングでの画像認識の発展はすさまじいものです。その学習には大量の画像データに対してラベル(タグ)を付ける作業(=「アノテーション作業」)が必要になります。例えば、特定の物体を検出したいと思った場合、その物体が映り込んだ画像を大量に用意した上で、その画像に対して、領域を指定して、それが何なのかをラベル付けする作業が必要になります。
こうした作業を補助するツールはオープンソースソフトウェア、商用製品含めて色々とあります。非常に時間がかかる作業となるため、複数人で実施したいものですが、ネットで探してみると、なかなか情報が見つかりませんでした。
そこで、今回は、オープンソースソフトウェアであるVoTTを用いて、実際に複数人のチームで作業をする為に、VoTTの仕様を調査し、実施方法を考えました。また、その手順と、実際に実施してみた結果をご紹介します。
今回の記事の内容に関する実行環境:
-
-
- Windows
- VoTT ver 2.2.0
-
目次
1.VoTT概要
VoTTの公式ページ(https://github.com/microsoft/VoTT)によると、VoTTとは、画像およびビデオアセット用のオープンソースのアノテーションおよびラベル付けツールであり、次の機能があります。
- 画像またはビデオフレームにラベルを付ける
- ローカルまたはクラウドストレージプロバイダーから、データをインポートできる
- ラベル付きデータを、ローカルまたはクラウドストレージプロバイダーにエクスポートできる
この記事では、画像にラベルを付ける場合について説明します。
導入は公式ページからインストーラーをダウンロードし、実行するだけです。その後は下表のように6手順程で簡単にアノテーションすることが出来ます。
手順1: データソースの設定 |
利用するデータソースの設定として、事前に準備したファイルへのパスを設定します | |
手順2: プロジェクトを作成する |
利用するデータソースや、物体に付けるラベル(「タグ」と呼んでいる)を指定します | |
手順3: アクティブラーニング設定 |
既に作成されている物体検出の予測モデルを使ってアノテーションファイルの作成をサポートしてくれる機能があり、有効化/無効化は自身で設定できます | |
手順4: エクスポート設定 |
次のような設定を行います。
|
|
手順5: アノテーションの実施 |
対象物を囲い、☒が表示されている状態でラベルをクリックすると囲っている部分の色が変わり、ラベル付けが完了となります | (VoTT公式ページ(https://github.com/microsoft/VoTT)より画像を引用) |
手順6: アノテーションの実施結果を確認 |
★アノテーション結果の可視化もできます
|
2.VoTT構成ファイルの関係性
VoTTは前述のようにGUIで操作を行います。すると、操作結果が自動的にファイルとして作成されます。後述「複数人でアノテーション作業を実施する手順」の作業のため、それらファイルの関係性を理解しましょう。
構成ファイル -1:プロジェクトファイル「(プロジェクト名).vott」
プロジェクトを作成すると生成されるファイルであり、ファイル名はプロジェクト名となります。
例) プロジェクト名が「test_pj」であるとしたら、「test_pj.vott」
また、中身は次のようになっています。
test_pj.vott
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
{ "name": "test_pj", "securityToken": "test_pj Token", "sourceConnection": { "name": "test", "description": "動作確認", "providerType": "localFileSystemProxy", "providerOptions": { "encrypted": xxxxx }, "id": "abH1QlGet" }, "targetConnection": { "name": "test", "description": "動作確認", "providerType": "localFileSystemProxy", "providerOptions": { "encrypted": xxxxx }, "id": "abH1QlGet" }, "description": "動作確認", "videoSettings": { "frameExtractionRate": 15 }, "tags": [ { "name": "nomask", "color": "#e81123" }, { "name": "mask", "color": "#5db300" }, ], "id": "WlwMgHcl-", "activeLearningSettings": { "modelPathType": "coco", "autoDetect": true, "predictTag": false }, "exportFormat": { "providerType": "pascalVOC", "providerOptions": { "encrypted": xxxxx } }, "version": "2.2.0", "lastVisitedAssetId": "a97ef12bd985c457bfb51a6d30882ea0", "assets": { "1e08c316c99e814461224842f5b20f21": { "format": "jpg", "id": "1e08c316c99e814461224842f5b20f21", "name": "000002.jpg", "path": "file:C:/Project/test_pj/000002.jpg", "size": { "width": 500, "height": 332 }, "state": 2, "type": 1, "predicted": true }, "a97ef12bd985c457bfb51a6d30882ea0": { "format": "jpg", "id": "a97ef12bd985c457bfb51a6d30882ea0", "name": "000003.jpg", "path": "file:C:/Project/test_pj/000003.jpg", "size": { "width": 500, "height": 333 }, "state": 2, "type": 1, "predicted": true }, } } |
今後の作業に関わる50行目~77行目の「assets」の内容について、説明します。
- 「assets」に、画像ファイル毎に「id」が振られていることがわかります。 この「id」から、後述のアノテーション定義ファイル「(id)-asset.json」のファイル名が決まります。
「id」は、32文字の文字列で、次のようなPythonコードで生成できます。
Asset Id の取得方法
1 2 3 4 |
import hashlib source_asset_path = 'file:C:/Project/test_pj/000002.jpg' hashlib.md5(source_asset_path.encode('utf-8')).hexdigest() |
- 「name」は、画像ファイル名です。
- 「path」は、上記画像ファイルのフルパスです。
構成ファイル -2:アノテーション定義ファイル「(id)-asset.json」
アノテーション作業を行われた画像ファイル毎に生成されます。ファイル名に含まれる「id」は、前述の通り、プロジェクトファイル「(プロジェクト名).vott」の値(「assets」-「id」)と紐づいた文字列です。
また、ファイルの中身は次のようになっています。
(id)-asset.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
{ "asset": { "format": "jpg", "id": "1e08c316c99e814461224842f5b20f21", "name": "000002.jpg", "path": "file:C:/Project/test_pj/000002.jpg", "size": { "width": 500, "height": 335 }, "state": 2, "type": 1, "predicted": true }, "regions": [ { "id": "lR0j3fbqM", "type": "RECTANGLE", "tags": [ "nomask" ], "boundingBox": { "height": 32.54285714285714, "width": 34.43877551020408, "left": 247.6383131377551, "top": 121.87619047619047 }, "points": [ { "x": 247.6383131377551, "y": 121.87619047619047 }, { "x": 282.07708864795916, "y": 121.87619047619047 }, { "x": 282.07708864795916, "y": 154.4190476190476 }, { "x": 247.6383131377551, "y": 154.4190476190476 } ] }, { "id": "rn_HRhfSr", "type": "RECTANGLE", "tags": [ "nomask" ], "boundingBox": { "height": 59.980952380952374, "width": 72.70408163265306, "left": 425.57198660714283, "top": 8.933333333333334 }, "points": [ { "x": 425.57198660714283, "y": 8.933333333333334 }, { "x": 498.2760682397959, "y": 8.933333333333334 }, { "x": 498.2760682397959, "y": 68.91428571428571 }, { "x": 425.57198660714283, "y": 68.91428571428571 } ] }, { "id": "0UOTDqhHb", "type": "RECTANGLE", "tags": [ "nomask" ], "boundingBox": { "height": 24.885714285714283, "width": 24.23469387755102, "left": 130.92912946428572, "top": 196.53333333333333 }, "points": [ { "x": 130.92912946428572, "y": 196.53333333333333 }, { "x": 155.16382334183672, "y": 196.53333333333333 }, { "x": 155.16382334183672, "y": 221.4190476190476 }, { "x": 130.92912946428572, "y": 221.4190476190476 } ] } ], "version": "2.2.0" } |
2行目の「asset」の内容について、説明します。
- 「id」は、前述の通り、プロジェクトファイル「(プロジェクト名).vott」の値(「assets」-「id」)と紐づいた文字列です。「name」は、画像ファイル名です。
- 「path」は、上記画像ファイルのフルパスです。
15行目の「regions」の内容について、説明します。
- 「id」は、9文字のランダムな文字列で、画像内で物体として指定された箇所毎に生成されます。
また、値は次のようなPythonコードで生成できます。
Region ID の取得方法
1 2 3 4 |
import random, string ''.join(random.choices(string.ascii_letters + string.digits, k=9)) |
- 「boundingBox」は、次の項目でそれぞれ、アノテーション作業結果を保持します
- 「height」は、対象物の高さになります
- 「width」は、対象物の幅になります
- 「left」は、対象物の最も左の座標になります
- 「top」は、対象物の最も上の座標になります
- 「points」は、前述の「boundingBox」の値を基に、次の各項目を計算します
-
-
- 一つ目の座標(左上):
- x=「left」
- y=「top」
- 二つ目の座標(右上):
- x=「left」+「width」
- y=「top」
- 三つ目の座標(右下):
- x=「left」+「width」
- y=「top」+「height」
- 四つ目の座標(左下):
- x=「left」
- y=「top」+「height」
- 一つ目の座標(左上):
-
- 「version」=”2.2.0″
- VoTTのバージョンのことかと思われます
「VoTT構成ファイルの関係性」のまとめ
- ファイルは2種類
-
プロジェクトファイル 「(プロジェクト名).vott」
-
アノテーション定義ファイル 「(id)-asset.json」
-
- プロジェクトファイル 「(プロジェクト名).vott」
- プロジェクトに対して、1つ生成されます
- ファイル内の「assets」の中に、画像ファイル毎のIDが付与されます
- アノテーション定義ファイル 「(id)-asset.json」
- 画像ファイル毎に、1つ生成されます
- ファイル名とファイル内の「id」は、プロジェクトファイル「(プロジェクト名).vott」内の値(「assets」-「id」)と紐づきます
- ファイル内の「regions」は、画像内で物体として指定された箇所毎に「id」(ランダムな文字列)を生成します
3.複数人でアノテーション作業を実施する手順
VoTTの概要と、生成されるファイル構成を理解したところで、本題である、複数人での作業方法を説明します。
Step1:
作業を担当される方全員の作業環境に、VoTTをインストールし、アノテーション対象の画像ファイル群を各担当者の環境に保存します。
【注意事項】 全員の環境で、設定内容を一致させて下さい。 プロジェクトの設定: 物体に指定するタブ名の表記(表記ブレがない様に)とその順番 |
Step2:
各担当者が、各自の作業環境で、アノテーション作業を実施します。
Step3:
各担当者が、各自の環境でアノテーション作業を行った結果の次のファイルと画像ファイルを、マージ担当者に共有します。
-
-
-
プロジェクトファイル 「(プロジェクト名).vott」
-
アノテーション定義ファイル 「(id)-asset.json」
- アノテーションを行った画像ファイル
-
-
Step4:
各担当者がアノテーション作業を行った環境でファイルパスが異なる為、ファイルパスから生成している「Asset ID」が、マージ先の環境で整合性を保てません。
そこで、マージ担当者は、次の作業を通して、各自の作業結果をマージします。
-
-
- 全員のアノテーション作業結果を受領します。
- マージ用のVoTTプロジェクトを作成します。
- マージ作業(メイン)
※この作業は大量に行わないといけないので、次の処理を行うコードを書いて自動化して下さい- 受領したプロジェクトファイル「(プロジェクト名).vott」から、次のデータを取得します
- 「assets」-「id」 (※以後、「Asset Id」とする)
- 「assets」-「name」 (=画像ファイル名)
- 上記で取得した「Asset Id」から、受領したアノテーション定義ファイル「(id)-asset.json」を探し、次の内容を上書きした上で、移行先プロジェクトフォルダにコピーします。
また、コピーした「(id)-asset.json」のファイル名にある「id」は「Asset Id」に変更する必要があります。
(この作業を「Asset Id」の数だけ繰り返します)- 「asset」-「id」:実際にローカルに保存している「画像ファイル名(フルパス)」から生成し直したもの
- 「asset」-「path」:実際にローカルに保存している「画像ファイル名(フルパス)」から生成し直したもの
- 移行先のプロジェクトファイル「(プロジェクト名).vott」に、次の内容を画像ファイルの数だけ追記します。
- 「assets」-「id」:実際にローカルに保存している「画像ファイル名(フルパス)」から生成し直したもの
- 「assets」-「path」:実際にローカルに保存している「画像ファイル名(フルパス)」から生成し直したもの
- ※他の項目は、移行元の受領した「(プロジェクト名).vott」の内容を適用します。
- 受領したプロジェクトファイル「(プロジェクト名).vott」から、次のデータを取得します
-
Step5:
全員のアノテーション作業結果をマージしたら、VoTTで開き直して、アノテーション作業結果が取り込まれているかを確認します。各画像に各担当者がアノテーション作業を行った結果が、画像として確認できると思います。(VoTT公式ページ[https://github.com/microsoft/VoTT]より画像を引用)
しかし、下図の「アセット画面」を確認すると、取り込んだ画像が「未訪問アセット」としてカウントされてしまっています。このままでは、アノテーション作業結果をエクスポートした際に上手く出力できません。
「訪問済みアセット」「タグ付きアセット」として認識させる為に、全ての画像に対して何か適当な作業(例えば、「適当な箇所を範囲指定して、それを消す」など)をして、更新を行って下さい。
4.最後に
VoTTのファイル構成を理解すれば、今回のような「複数人でアノテーション作業を分担する」こと以外に、次のようなことも実現可能になります。是非、試してみて下さい。
- アノテーション実施済みのデータセットに含まれるPascal Voc形式のXMLファイルを、VoTTに取り込み、VoTTで編集する
- 方法:「Pascal Voc形式のXMLファイル」から、VoTTアノテーションファイル「(id)-asset.json」を生成する
- 学習済みモデルを使って物体検出を行った結果を、VoTTに取り組み、VoTTで編集する
- 方法:学習済みモデルを使って物体検出を行った結果をCSVファイルに出力し、そのCSVファイルからVoTTアノテーションファイル「(id)-asset.json」を生成する
執筆者プロフィール
- 入社以来、C/S型の業務システム開発に従事してきました。ここ数年は、SalesforceやOutSystemsなどの製品や、スクラム開発手法に取り組み、現在のテーマは、DeepLearning/機械学習です。
この執筆者の最新記事
- Pick UP!2021.11.11VoTTを複数人で使って、アノテーションを行いたい!(ファイル移行を用いて)
- Pick UP!2020.11.20AIoTデバイス「M5StickV」、はじめの一歩
- RPA2019.08.15「OSSのRPA」+「自作の三目並べマシン」でGoogleに挑む!
- AI2019.04.22暗記学習(Rote Learning)で三目並べを強くする