概要
Open Image Dataset V5をダウンロードして中身を確認する。
BoxやSegmentationの情報をplotしてみる。
Open Image Dataset V5とは
Googleが公開しているアノテーション付きの画像データ
- 600カテゴリ、1585万のボックス
- 350カテゴリ、278万のセグメンテーション
- 2万弱のカテゴリ、3646万の画像単位のラベル
などかなりの量のデータが入っている。
アノテーションデータのダウンロード
下記のページからダウンロードできる。
https://storage.googleapis.com/openimages/web/download.html
とりあえずアノテーションやメタデータだけダウンロードしてみる。
# box wget https://storage.googleapis.com/openimages/2018_04/train/train-annotations-bbox.csv wget https://storage.googleapis.com/openimages/v5/validation-annotations-bbox.csv wget https://storage.googleapis.com/openimages/v5/test-annotations-bbox.csv # segmentation wget https://storage.googleapis.com/openimages/v5/train-annotations-object-segmentation.csv wget https://storage.googleapis.com/openimages/v5/validation-annotations-object-segmentation.csv wget https://storage.googleapis.com/openimages/v5/test-annotations-object-segmentation.csv # relationship wget https://storage.googleapis.com/openimages/2019_01/train/challenge-2018-train-vrd.csv wget https://storage.googleapis.com/openimages/v5/validation-annotations-vrd.csv wget https://storage.googleapis.com/openimages/v5/test-annotations-vrd.csv # image label wget https://storage.googleapis.com/openimages/v5/train-annotations-human-imagelabels-boxable.csv wget https://storage.googleapis.com/openimages/v5/validation-annotations-human-imagelabels-boxable.csv wget https://storage.googleapis.com/openimages/v5/test-annotations-human-imagelabels-boxable.csv # image id wget https://storage.googleapis.com/openimages/2018_04/train/train-images-boxable-with-rotation.csv wget https://storage.googleapis.com/openimages/2018_04/validation/validation-images-with-rotation.csv wget https://storage.googleapis.com/openimages/2018_04/test/test-images-with-rotation.csv # metadata mkdir metadata cd metadata wget https://storage.googleapis.com/openimages/v5/class-descriptions-boxable.csv wget https://storage.googleapis.com/openimages/2019_01/challenge-2018-relationships-description.csv wget https://storage.googleapis.com/openimages/2019_01/challenge-2018-attributes-description.csv wget https://storage.googleapis.com/openimages/2019_01/challenge-2018-relationship-triplets.csv wget https://storage.googleapis.com/openimages/v5/classes-segmentation.txt cd ../
続いてsegmentationの0〜Fまでのファイルをダウンロード。zipになっているのでsegmentationsというディレクトリを作ってそこに展開してみる。zipの中にはsegmentationした物体のpng画像が入っている。
# segmentations mkdir segmentations cd segmentations mkdir train mkdir validation mkdir test for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f do unzip train-masks-$i.zip -d train/ unzip validation-masks-$i.zip -d validation/ unzip test-masks-$i.zip -d test/ done
画像データのダウンロード
画像のダウンロードはawscliを用いる。Pythonを使っていればpipからインストールできる。
pip install awscli
awscliが入ったら下記URLを参考にしながらダウンロードする。500GBを超えるなかなかの大物。
https://github.com/cvdfoundation/open-images-dataset#download-images-with-bounding-boxes-annotations
class-descriptions-boxable.csv
ダウンロードしたmetadataの中を確認してみる。
まずはclass-descriptions-boxable.csv。Boxでアノテートしてるクラスの一覧が入っている。
$ head metadata/class-descriptions-boxable.csv /m/011k07,Tortoise /m/011q46kg,Container /m/012074,Magpie /m/0120dh,Sea turtle /m/01226z,Football /m/012n7d,Ambulance /m/012w5l,Ladder /m/012xff,Toothbrush /m/012ysf,Syringe /m/0130jx,Sink
csvで1列目がラベルのid、2列目がラベルの名称。
/m/011k07はTortoise(亀)らしい。
annotations-bbox.csvの中をgrepして実際に亀であることを確認してみる。
$ grep /m/011k07 test-annotations-bbox.csv | head -3 023b4802f26b54e6,xclick,/m/011k07,1,0.25,0.7647059,0.124168515,0.9179601,0,0,0,0,0 05373b7f9363f1b5,xclick,/m/011k07,1,0.29056048,0.77138644,0.28318584,0.73893803,0,0,0,0,0 061bad48d5f83750,xclick,/m/011k07,1,0.015086207,1,0.36611196,0.881997,0,0,0,0,0
1番目のカラムが画像のID。023b4802f26b54e6.jpg がファイル名になるので、中身を見てみる。
うん、確かに亀だ。
classes-segmentation.txt
classes-segmentation.txtにはセグメンテーションのラベルの一覧が入っている。
$ head metadata/classes-segmentation.txt /m/01_5g /m/0c06p /m/01lsmm /m/01bqk0 /m/0l14j_ /m/0342h /m/09j2d /m/076bq /m/01xqw /m/01599
こちらは見ての通りラベルのIDだけ。名称はBoxと共通。
例えば1番上に表示されたID、/m/01_5gをBoxの方の一覧でgrepすれば名称が出てくる。
$ grep /m/01_5g metadata/class-descriptions-boxable.csv /m/01_5g,Chopsticks
challenge-2018-attributes-description.csv
challenge-2018-attributes-description.csv には下記のような5レコードが入っている。
$ cat metadata/challenge-2018-attributes-description.csv /m/02gy9n,Transparent /m/05z87,Plastic /m/0dnr7,(made of)Textile /m/04lbp,(made of)Leather /m/083vt,Wooden
プラスチック(Plastic)、織物(Textile)、革(Leather)など素材に関する情報が入っているようだ。
challenge-2018-train-vrd.csv の中に当該IDが振られた情報が入っている。
/m/02gy9n(Transparent)のデータを確認してみる。
$ grep /m/02gy9n challenge-2018-train-vrd.csv | head -2 82d16a22f703df5c,/m/04dr76w,/m/02gy9n,0.612,0.735,0.4189189,0.9504505,0.612,0.735,0.4189189,0.9504505,is 7da79ddcea564138,/m/04dr76w,/m/02gy9n,0.416875,0.468125,0,0.2532833,0.416875,0.468125,0,0.2532833,is
実際の画像を確認してみる。
確かに瓶などの透明(Transparent)な物体が写っている。
challenge-2018-relationships-description.csv
challenge-2018-relationships-description.csv には下記のようなデータが入っている。
$ cat metadata/challenge-2018-relationships-description.csv at,at on,on (top of) holds,holds plays,plays interacts_with,interacts with wears,wears is,is inside_of,inside of under,under hits,hits
わかりやすそうなところで wears が振られている画像を見てみる。
$ grep wear challenge-2018-train-vrd.csv | head -2 23d725e3f329db33,/m/03bt1vf,/m/080hkjn,0.534375,0.875625,0.11333334,0.9825,0.49125,0.81375,0.31916666,0.9875,wears 6e61958358f360fe,/m/03bt1vf,/m/080hkjn,0.52086556,0.7658424,0.34774256,0.9990394,0.57341576,0.74806803,0.6676273,0.9990394,wears
うん、確かにwearsだ。
Boxの矩形を表示
annotations-bbox.csvのレコードに書いてある座標から矩形を表示する。
2枚ほど犬(/m/0bt9lr)の画像に対して矩形を出してみる。
$ grep "/m/0bt9lr" train-annotations-bbox.csv | head -2 0000b9fcba019d36,xclick,/m/0bt9lr,1,0.165000,0.903750,0.268333,0.998333,1,1,0,0,0 0000cb13febe0138,xclick,/m/0bt9lr,1,0.000000,0.651875,0.000000,0.999062,1,1,0,0,0
カラムのヘッダはこんな内容。
ImageID,Source,LabelName,Confidence,XMin,XMax,YMin,YMax,IsOccluded,IsTruncated,IsGroupOf,IsDepiction,IsInside
ImageIDから画像のファイル名、XMin, XMax, YMin, YMaxで矩形が取れる。
# 犬の上2つの画像を読み込む df = pd.read_csv('train-annotations-bbox.csv', nrows=10000) df = df[df.LabelName == '/m/0bt9lr'].head(2) f, ax_list = plt.subplots(1, 2, figsize=(12, 6)) for idx, (df_id, row) in enumerate(df.iterrows()): # 画像の読込み path = 'images/train/%s.jpg' % row.ImageID img = cv2.imread(path) # 座標の取得 y, x = img.shape[:2] x_min = int(x * row.XMin) x_max = int(x * row.XMax) y_min = int(y * row.YMin) y_max = int(y * row.YMax) # 矩形の表示 cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color=(0, 0, 255), thickness=5) # plot ax_list[idx].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
出力結果
Segmentの抽出
segmentationのデータも確認してみる。
$ grep "/m/0bt9lr" train-annotations-object-segmentation.csv | head -2
ヘッダの情報も合わせて結果を表示するとこんな感じ。
MaskPath,ImageID,LabelName,BoxID,BoxXMin,BoxXMax,BoxYMin,BoxYMax,PredictedIoU,Clicks 871991d5e1d800a5_m0bt9lr_9f191f9e.png,871991d5e1d800a5,/m/0bt9lr,9f191f9e,0.213832,0.543402,0.318519,0.998942,0.83814,0.43900 0.98096 1;0.34233 0.98247 1;0.52251 0.72368 1;0.38990 0.33436 1;0.36837 0.98628 0;0.51072 0.55970 1;0.48918 0.91509 0;0.31680 0.99227 1;0.37546 0.95996 0 0abe18d0e7f90ff7_m0bt9lr_ee783a59.png,0abe18d0e7f90ff7,/m/0bt9lr,ee783a59,0.585625,0.868125,0.109765,0.616957,0.70112,0.77855 0.24412 1;0.60155 0.35340 1;0.67869 0.61283 1;0.83916 0.24329 1;0.75244 0.36364 1;0.60633 0.40386 1;0.78011 0.22287 0;0.74185 0.31033 0;0.64125 0.36710 1;0.67212 0.58310 1
ImageIDから画像名がわかり、MaskPathにセグメンテーション画像のパスが入っている。
確認の為、画像を2つほど加工せずに表示してみる。
# 適当な犬画像を2つほど取得 df = pd.read_csv('train-annotations-object-segmentation.csv', nrows=10000) df = df[df.LabelName == '/m/0bt9lr'].head(10).tail(2) df.head() # 上下に並べて元画像とセグメンテーション画像を表示 f, ax_list = plt.subplots(2, 2, figsize=(8, 10)) for idx, (df_id, row) in enumerate(df.iterrows()): # 画像の読込み img_path = 'images/train/%s.jpg' % row.ImageID img = cv2.imread(img_path) # セグメンテーション画像の読込み seg_path = 'segmentations/train/%s' % row.MaskPath mask = cv2.imread(seg_path) print(img.shape, mask.shape) # 画像の表示 ax_list[0][idx].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) ax_list[1][idx].imshow(cv2.cvtColor(mask, cv2.COLOR_BGR2RGB))
画像のshapeを標準出力しているが、その結果は下記のようになる。左が元画像、右がマスク画像。
(1024, 768, 3) (1600, 1200, 3) (683, 1024, 3) (800, 1200, 3)
どうやら元画像とマスク画像でshapeが違うらしい。
元画像とサイズを合わせて重ねて表示してみる。
f, ax_list = plt.subplots(1, 2, figsize=(12, 6)) for idx, (df_id, row) in enumerate(df.iterrows()): # 画像の読込み img_path = 'images/train/%s.jpg' % row.ImageID seg_path = 'segmentations/train/%s' % row.MaskPath img = cv2.imread(img_path) mask = cv2.imread(seg_path) # maskを元画像のサイズにリサイズ y, x = img.shape[:2] mask = cv2.resize(mask, (x, y)) print(img.shape, mask.shape) # 重ねて表示 dst = cv2.addWeighted(img, 0.5, mask, 0.5,gamma=1.0) ax_list[idx].imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
実行結果。かなりキレイに切り取ってありますね。
昔、学習用データを作る為に延々とlabelmeで延々と切り抜きをしたことがあるけど、とても辛かった。これだけのデータを作った方々には頭が下がる。
Boxの情報とClicks(このポイントはセグメント内だよ)の情報もあるので一緒に表示してみる。
Clicksは下記のようにセミコロン区切りになっていて、X座標、Y座標、T(そのポイントがセグメント内なら1、違う場合は0)が入っている。
0.43900 0.98096 1; 0.34233 0.98247 1; 0.52251 0.72368 1;
これらの情報を画像に表示してみる。
df = pd.read_csv('train-annotations-object-segmentation.csv', nrows=10000) df = df[df.LabelName == '/m/0bt9lr'].head(10).tail(2) df.head() f, ax_list = plt.subplots(1, 2, figsize=(12, 12)) for idx, (df_id, row) in enumerate(df.iterrows()): # 画像の読込み img_path = 'images/train/%s.jpg' % row.ImageID img = cv2.imread(img_path) # 矩形の表示 y_size, x_size = img.shape[:2] x_min = int(x_size * row.BoxXMin) x_max = int(x_size * row.BoxXMax) y_min = int(y_size * row.BoxYMin) y_max = int(y_size * row.BoxYMax) cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color=(128, 128, 255), thickness=5) # clickのT=1の位置に赤circleを, 0に青circleを表示 clicks = row.Clicks.split(';') for click in clicks: x, y, t = click.split(' ') x = int(x_size * float(x)) y = int(y_size * float(y)) color = (0, 0, 255) if int(t) == 1 else (255, 0, 0) cv2.circle(img, (x, y), radius=20, color=color, thickness=-1) # 重ねて表示 ax_list[idx].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
改定履歴
Author: Masato Watanabe, Date: 2019-06-18, 記事投稿