Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

縦長の画像のアノテーションが上手くできていない #4

Closed
Kanazawanaoaki opened this issue May 17, 2020 · 44 comments
Closed

Comments

@Kanazawanaoaki
Copy link
Owner

labelmeによってアノテーションを行っているが、縦長の画像に対してのアノテーションが上手く言っていない可能性がある。
very_easy_data/train/382076.jpg

labelme --labels labels.txt very_easy_data/train/382076.jpg

Screenshot from 2020-05-17 20-56-00

labelme_draw_label_png very_easy_datasets/train/SegmentationClassPNG/382076.png 

Screenshot from 2020-05-17 20-58-40
画像が途中で切れてしまって上手くアノテーションが出来ていない気がする。

@Kanazawanaoaki
Copy link
Owner Author

そもそもの画像を反転させて、新しくアノテーションをすると上手くアノテーション出来ているように思える。
very_easy_data_kai/train/382076.jpg

labelme --labels labels.txt very_easy_data_kai/train/382076.jpg

Screenshot from 2020-05-17 20-59-24

labelme_draw_label_png very_easy_data_kai_datasets/train/SegmentationClassPNG/382076.png

Screenshot from 2020-05-17 20-59-04

@Kanazawanaoaki
Copy link
Owner Author

以前学習させたネットワークをtrainの予測を見て確認した時にも、横長の画像はそれなりに学習できていそうなのに、縦長の画像は上手く言っていないという事があった。それもこれが原因だったのかも。これからは横長の写真を使うか縦長の場合は回転させて使うのが良さそう。
Screenshot from 2020-05-16 13-10-14
Screenshot from 2020-05-16 13-10-54

@knorth55
Copy link
Contributor

画像をiphoneとかでとっていますか?
iphoneで縦長の画像をとっている場合には、たまに画像の表示は縦長なのに画像のデータとしては横長になっていることがあります。
そうなるとlabelme_draw_みたいなプログラムで、横長と認識して可視化している可能性があります。
cv2などで画像をreadしてshapeなどをみてみると良いかと思います。

img = cv2.imread(path)
# shape = (Height, Width, Channel)
print(img.shape)

そうなっているとアノテーションもかなりおかしなことになりますね。
アノテーションが縦長画像に対して行われているのに、画像が横長としてロードされていると意味がないので
そうなると学習も上手くいかないでしょう。
データセットの画像について詳しく見る必要がありそうですね

@Kanazawanaoaki
Copy link
Owner Author

ありがとうございます。
画像はiphoneでとっています。 なるほどそういうことだったんですね。
データセットの画像について確認してみようと思います。

@MiyabiTane
Copy link

MiyabiTane commented May 25, 2020

この問題に関連して、画像が逆さまになってしまうという問題を発見しました。
iphoneで写真を撮る時はホームボタンが右側にくるようにし、外カメラで撮影するとこの問題が回避できる気がします。
iphoneで写真を撮った後に回転させてからPCに送ってもdlboxでは最初に撮ったときの情報で処理されるというのと、内カメラで撮った写真は逆さまになるのではないかというのが私の考えです。(確信はないです。)

下の図では上の画像がアノテーションしたもの、下の画像がtensorboardで見たものです。
ground-truth(下の画像の右側)の画像からアノテーションの情報と画像がずれていることがわかります。

Screenshot from 2020-05-25 15-26-00

@knorth55
Copy link
Contributor

@MiyabiTane ちなみに、iPhoneでみたときはtensorboardのほうが正しいですか?(つまり上下逆さまにはiPhoneではなってないんですよね)
labelmeでこの画像表示した時の画面キャプチャもみてみたいです。

@MiyabiTane
Copy link

iPhoneで送った後、PC上で向きの操作などは一切していないです。

そして、すみません。画像(上のコメントの、上の画像がアノテーションしたもの、の方)を見て向き的に自分でiphone上で回転させたものだろうと思っていたのですが、今iphoneで編集ボタンを押すとオリジナルに戻す、という表示が出ないのでiphoneで撮ったままの画像のようです。

説明がわかりにくくて申し訳ないのですが、つまり言うと、iphoneで撮影した後、iphone上でもPC上でも、何の回転も加えていないはずだと言うことです。

ただ、普通写真をとると下の画像のような向きになるはずで、なぜ逆さまになっているのかは撮った本人もわかっていないです。。。

スクリーンショット 2020-05-25 17 05 20

@MiyabiTane
Copy link

labelme上の向きもiphoneと同じなので、違っているのはtensorboardだけだと思います。

Screenshot from 2020-05-25 17-02-10

@Kanazawanaoaki
Copy link
Owner Author

アノテーションをしたフォルダの画像を見ると正しい向き(?)になっていそうですが、
image_test2
(https://github.com/MiyabiTane/HIRO_LunchBox/blob/master/labelme/okazu_50/train/IMG_5765.JPG )

VOC形式にした後のJPEGImages内の画像を見ると反転されてしまっているみたいですかね?
image_test
(https://github.com/MiyabiTane/HIRO_LunchBox/blob/master/lunch_box_50_dataset/train/JPEGImages/IMG_5765.jpg )
VOC形式に変換する時に画像が反転されてしまうことがあるのでしょうか。

labelme_draw_label_png lunch_box_50_dataset/train/SegmentationClassPNG/IMG_5765.pngを見るとセグメンテーションは反転される前の画像の向きになっているのでそこでラベル付けのズレが生じているのが問題なのでしょうか。
image_test3

@knorth55
Copy link
Contributor

金沢くんの最初の人参もデータセットでは正しく縦になってたんだっけ?

@knorth55
Copy link
Contributor

となるとlabelmeのバグっぽいですね
cc. @wkentaro

@Kanazawanaoaki
Copy link
Owner Author

Kanazawanaoaki commented May 25, 2020

僕の最初の人参の画像(iPhoneで縦長で撮影して回転など編集は一切行っていない)場合はアノテーションした時の画像が縦長、
Screenshot 2020-05-25 20:54:45
(https://github.com/Kanazawanaoaki/cook_eyes/blob/master/food_detector/food_only_data/very_easy_data/train/382076.jpg )

VOC形式に変換した時のJPEGImages内の画像が横長、
Screenshot 2020-05-25 20:55:28
(https://github.com/Kanazawanaoaki/cook_eyes/blob/master/food_detector/food_only_data/very_easy_datasets/train/JPEGImages/382076.jpg )

labelme_draw_label_png very_easy_datasets/train/SegmentationClassPNG/382076.pngで確認したときは縦長画像に対してのアノテーションが横長に無理やり変換されているようになっています。
Screenshot 2020-05-25 20:53:05

>>> import cv2
>>> img = cv2.imread("382076.jpg")
>>> print(img.shape)
(4032, 3024, 3)

なのでOpenCVで読んでも縦長に認識されているようですが、iPhoneで撮影した画像の場合labelmeのVOC変換を行う際にJPEGImagesが回転や反転して、セグメンテーションとずれてしまう事があるみたいですね。

@knorth55
Copy link
Contributor

なるほど、おもしろいですね
つまりlabelmeの読み込みと保存で形が変わってしまっているのですね
PRチャンスですね。

@MiyabiTane
Copy link

あ、ほんとだ、気づかなかった...。金沢くん指摘ありがとう!
これが直ればiphoneの写真の撮り方や回転編集の有無を考慮しなくてよくなりそうですね。

直せたらPRですね、時間つくって頑張ってみます。

@knorth55
Copy link
Contributor

knorth55 commented May 25, 2020 via email

@MiyabiTane
Copy link

labelme input --labels labels.txt
として開いてアノテーションした後

https://github.com/MiyabiTane/HIRO_LunchBox/tree/master/labelme
のようにしてvoc変換しています。

今ふと思ったのですが画像の形が変わってしまうことにpython3で実行していることが関係しているでしょうか?
金沢くんはpythonで実行していますか?

今コードを見ていたのですが99行目のnp.asarrayが悪さをしているようです。
https://github.com/MiyabiTane/HIRO_LunchBox/blob/master/labelme/labelme2voc.py

私の環境ではpythonで実行すると以下のようなエラーになります。
Traceback (most recent call last):
File "./labelme2voc.py", line 143, in
main()
File "./labelme2voc.py", line 122, in main
loc='rb',
File "/home/tork/.local/lib/python2.7/site-packages/imgviz/label.py", line 169, in label2rgb
legend, aabb1, aabb2, fill=(255, 255, 255)
File "/home/tork/.local/lib/python2.7/site-packages/imgviz/draw.py", line 188, in rectangle
xy=(x1, y1, x2, y2), fill=fill, outline=outline, width=width
TypeError: rectangle() got an unexpected keyword argument 'width'

@Kanazawanaoaki
Copy link
Owner Author

僕も種本さんのREADMEを見てやったので、Python3で実行しています。

labelme2voc.pyにはinstance_segmentationのものsemantic_segmentationのものがあるのですが、semantic_segmentationの方で変換すると向きが変わらないみたいです。
semantic_segmentation
382076
instance_segmentation
382076

@knorth55
Copy link
Contributor

knorth55 commented May 25, 2020 via email

@Kanazawanaoaki
Copy link
Owner Author

あ、試してみます。とりあえずご報告ですが、semanticの方を真似して、

from labelme import utils

# 中略

img_file = osp.join(osp.dirname(label_file), data['imagePath'])
image_pil = PIL.Image.open(img_file)
image_pil = utils.apply_exif_orientation(image_pil)
img = np.asarray(image_pil)
PIL.Image.fromarray(img).save(out_img_file)

とするとJpegの画像は変換されなくなりました!
382076

@MiyabiTane
Copy link

北川さんの方法でも画像のサイズを保つことができました!
output_dirに保存する部分のコードはまだ書けていないので金沢くんができているならそれでOKな
気がします!

@Kanazawanaoaki
Copy link
Owner Author

@MiyabiTane 何故かimg = cv2.imread(img_file)(https://gist.github.com/Kanazawanaoaki/7140bc0e0d429a9249bce419ace6ed5e#file-instanve_voc_cv-py )にすると色が変になってしまったんだけどそうならなかった?
382076
もしそうなっていないなら僕のは他の部分も変な可能性がある?

@MiyabiTane
Copy link

cv2を使った後PILを使うのはどうなんだろうと思ってcv2で保存する方法を探してたところに金沢くんのコメントが来たからその方法は確認してないです、ごめんなさい...。
私の手元でも金沢くんが共有してくれた方を試してみます。

@Kanazawanaoaki
Copy link
Owner Author

そうだよね、、 確かOpenCVとPILでRGBの順番が違うみたいな話があった気がするのでそれを直す必要があるんだよね、多分。
問題なさそうなら、とりあえず僕が書いたやつでPRを出して見ようと思います。

@MiyabiTane
Copy link

ちょっとまって動かないです

@MiyabiTane
Copy link

img_file = osp.join(osp.dirname(label_file), data['imagePath'])
image_pil = PIL.Image.open(img_file)
image_pil = labelme.utils.apply_exif_orientation(image_pil)
img = np.asarray(image_pil)
PIL.Image.fromarray(img).save(out_img_file)

で動きました、書き間違えただけかな?金沢くんの手元でlabelme.がついてるならOKです。逆さまの画像問題も直ってました!

@Kanazawanaoaki
Copy link
Owner Author

from labelme import utilsもした?それでもエラーになったのかな?
どっちにしてもそっちの書き方の方が良さそうかな

@MiyabiTane
Copy link

MiyabiTane commented May 25, 2020

あ、それはしてない...。でもわざわざimport labelmeしてるからそっち使った方がいいのかな、と。
ごめんなさいちょっと勘違いしてたどっちでもいいと思います。

@MiyabiTane
Copy link

MiyabiTane commented May 25, 2020

ちなみにpythonで動かないのも問題な気がするのでもしよかったら金沢くんの手元でもpythonで動かすの試してほしいです。

#!/usr/bin/env python

ってことはpython3では動かさない想定のはず...。

@Kanazawanaoaki
Copy link
Owner Author

$ python labelme2voc.py annotated/ voc_dataset_instance_test/ --labels labels.txt 
Creating dataset: voc_dataset_instance_test/
class_names: ('_background_', 'potate', 'onion', 'carrot', 'tomato', 'octopus_wiener', 'broccoli', 'flower_carrot', 'rolled_egg', 'fried_chicken', 'lunch_box')
Saved class_names: voc_dataset_instance_test/class_names.txt
Generating dataset from: annotated/382076.json
Traceback (most recent call last):
  File "labelme2voc.py", line 140, in <module>
    main()
  File "labelme2voc.py", line 119, in main
    loc='rb',
  File "/usr/local/lib/python2.7/dist-packages/imgviz/label.py", line 169, in label2rgb
    legend, aabb1, aabb2, fill=(255, 255, 255)
  File "/usr/local/lib/python2.7/dist-packages/imgviz/draw.py", line 188, in rectangle
    xy=(x1, y1, x2, y2), fill=fill, outline=outline, width=width
TypeError: rectangle() got an unexpected keyword argument 'width'

とりあえず試してみただけど、同じエラーっぽい?

@MiyabiTane
Copy link

うーん、なるほど。ありがとう。
とりあえずプルリク出しても大丈夫な気がします🎉

@knorth55
Copy link
Contributor

そうですねcv2.imreadつかったら最後までcv2.imsaveするほうがいいですね。

ちなみに、cv2はBGRの順番で画像を読んでしまうので、こうするとRGB順になります(numpyの逆順にする操作)

img = cv2.imread(img_filename)
# BGR -> RGB
img = img[:, :, ::-1]

@knorth55
Copy link
Contributor

knorth55 commented May 25, 2020

あと、Pillow >= 5.3.0でないと, width は使えないみたいですね。
python3つかっているなら、pip3 install --user Pillow>=5.3.0とかで解決かな。
python2なら pip install --user Pillow>=5.3.0

@knorth55
Copy link
Contributor

@Kanazawanaoaki @MiyabiTane
PRありがとうございます、デバグお疲れ様です
結局、手軽にやるには手元スクリプトをどう変更するのがいいかな?
大日方くんにも共有してくれると助かります。

@mqcmd196

@MiyabiTane
Copy link

ありがとうございます。

python -m pip install --upgrade pip
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Defaulting to user installation because normal site-packages is not writeable
Collecting pip
  Downloading pip-20.1.1-py2.py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 2.8 MB/s 
Installing collected packages: pip
Successfully installed pip-20.1.1
 pip install --user Pillow>=5.3.0

としてみましたがpython2のサポートが終わってしまっていてうまくいかないようです...。

DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support

@knorth55
Copy link
Contributor

なるほど、じゃあこのlabelmeはpython2ではうごかないみたいですね。
なのでpython3でやってしまいましょう、アノテーションなのでROS関係ないので

@Kanazawanaoaki
Copy link
Owner Author

Kanazawanaoaki commented May 25, 2020

ありがとうございます。

結局、手軽にやるには手元スクリプトをどう変更するのがいいかな?

labelme2voc.pyを使うときに、

wget https://gist.githubusercontent.com/Kanazawanaoaki/7140bc0e0d429a9249bce419ace6ed5e/raw/83d52893fe089515c5f038a28dcd843a3383bbdd/instanvce_voc_utils.py -O labelme2voc.py

としてとってきたlabelme2voc.pyを使っていただくのが良いと思います。

@MiyabiTane
Copy link

MiyabiTane commented May 25, 2020

結局、手軽にやるには手元スクリプトをどう変更するのがいいかな?

これで動くと思います
タイミング被っちゃいましたね...。金沢くんのを参考にしてください。
https://github.com/MiyabiTane/HIRO_LunchBox/blob/master/labelme/labelme2voc.py

python3でやってしまいましょう、アノテーションなのでROS関係ないので

了解しました

@wkentaro
Copy link

wkentaro commented May 25, 2020

となるとlabelmeのバグっぽいですね

これは、iphoneの姿勢を使うかどうかというところで、単純にimreadしているところは使えていないからおかしく見えるということだと思います。labelme2voc.pyが正しいはず。
ちなみに、UbuntuのGUIだと姿勢は反映されず、Macだとされた気がする。

@wkentaro
Copy link

僕も種本さんのREADMEを見てやったので、Python3で実行しています。

これですね。instance_segmentaion/labelme2voc.pyではapply_orientationがされていなかった。
あとUbuntuのGUIでも普通に姿勢反映されていました。

wget https://raw.githubusercontent.com/Kanazawanaoaki/cook_eyes/master/food_detector/food_only_data/very_easy_data/train/382076.jpg
python
>>> import matplotlib.pyplot as plt
>>> plt.imshow(plt.imread("382076.jpg")); plt.show()

xdg-open ./382076.jpg

@knorth55
Copy link
Contributor

@wkentaro xdg-openも賢いんですね、ぼくは昔他のやつでダメだった記憶がありました。
対応ありがとうございます。

@knorth55
Copy link
Contributor

@wkentaro

これは、iphoneの姿勢を使うかどうかというところで、単純にimreadしているところは使えていないからおかしく見えるということだと思います。labelme2voc.pyが正しいはず。
ちなみに、UbuntuのGUIだと姿勢は反映されず、Macだとされた気がする。

こういう感じだそうです。
#4 (comment)
#4 (comment)
labelmeで表示した画像とlabelme2voc.pyで保存されてる画像が異なっていたみたいです。
自分も確認していないので、わかりませんが

@wkentaro
Copy link

このPRでlabelm_draw_json等も含め全て治ったと思います。また起こったら教えてください。
wkentaro/labelme#666

こういう感じだそうです。

labelmeコマンド自体は賢くしたんだけど、labelme2voc.pyの方で漏れがあったみたい。
昔labelmeでこのfeatureをリクエストされたのときはwebcamとかKinectでちゃんとやればいいじゃんとか思っていたけど、コロナでiPhoneを使ってデータ作ったりするようになって役に立ってよかった。

@Kanazawanaoaki
Copy link
Owner Author

対応ありがとうございます。とても勉強になりました。

昔labelmeでこのfeatureをリクエストされたのときはwebcamとかKinectでちゃんとやればいいじゃんとか思っていたけど、コロナでiPhoneを使ってデータ作ったりするようになって役に立ってよかった。

そうだったんですね!

解決して頂いたのでこのissueはcloseしたいと思います。

@knorth55
Copy link
Contributor

ちなみに、ぼくはiphoneで撮った画像で昔おなじことになったときは、スクリプト書いて全画像をcv2.imreadしてcv2.imsaveして上書きしました。
乱暴なやりかたですがexif情報が消えるので解決します。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants