MotoJapan's Tech-Memo

技術めも

【ECCV2018 論文メモ#2】Contemplating Visual Emotions: Understanding and Overcoming Dataset Bias

Maker Faire Tokyo 2018では感情推定ロボットを出展したので感情繋がりでこの論文。

今回の論文と出典

Contemplating Visual Emotions: Understanding and Overcoming Dataset Bias
https://arxiv.org/abs/1808.02212

著者

Rameswar Panda, Jianming Zhang, Haoxiang Li, Joon-Young Lee, Xin Lu, Amit K. Roy-Chowdhury

内容

  • 視覚的感情の考察:データセットバイアスの理解とその克服
  • 感情データセットには、バイアスが存在する
  • 話したいのは3つの話題
  1. 最新のデータセットや精度の話を追わず、既存データセットの持つバイアス問題点を認識し、方法論の見直すこと
  2. Webなどの大規模データを用いることで、バイアス効果を軽減できること、シンプルなカリキュラム(体系的)学習方法を提案し、SoTAを達成したこと
  3. データセットの提案すること

詳細

  • データセットは、Deep Sentiment, Deep Emotion, Deep Emotion-6の3つで話が展開される
  • バイアスの例(Deep Emotion)は、下図の通りで、
    • Postive : amusementな画像は、ほぼamusement parkの画像で、視覚的コンセプトの多様性が低い
    • Negative : sadnessな画像は、amusement parkの画像は無く、その属性を十分に表現できていない

f:id:motojapan:20180818155938p:plain
(バイアスの考察例1:出典より抜粋)

  • データセットの持つバイアスを評価する手法をいくつか紹介している
    • 3データセットを分類する手法 (ResNet-50)
      • 期待値は、全て同じ精度だが偏りがある
      • 高い信頼度を示す画像を見ると、Deep Emotionは「屋外画像が多い」、Deep Emotion-6は「中心に対象物があり、背景はクリア」というバイアスがある

f:id:motojapan:20180818160008p:plain
(データセットを3クラス分類した結果(左)と信頼度の高い画像(右):出典より抜粋)

    • Pos/Neg2クラス分類する手法 (ResNet-60)
      • 感情情報を圧縮して2クラス(Pos/Neg)分類する
      • 各データセットでcrossにtrain/testした結果を考察
      • Binary Coss-Dataset Generationと呼ぶが、これの優位点は次の2点
        • 「シンプルな2値分類は評価の難しいデータセットにフェアな比較が可能」
        • 「シンプルなテストに一般化できていないモデルの場合、適切な粒度に分類したデータでもうなく動かないことがわかる」

f:id:motojapan:20180818160037p:plain
(各データセットをPos/Neg2クラス分類した結果:出典より抜粋)

    • オブジェクトとシーンについて条件付きエントロピーの分布で評価する手法
      • これでデータセットの中のデータ量を調査
      • 条件:確率をふっても変化が少ない感情属性はそもそもデータセットに少ないと解釈できる

f:id:motojapan:20180818160045p:plain
(バイアスの考察例2:出典より抜粋)

  • データセットの提案
    • WEBEmoというデータセットを提案
    • Deep Emotion の12倍のデータ量
    • Web上に存在するデータを既存研究をベースに組織化したもの
    • 良い点は、下記の2点
      • 検索エンジン差を軽減できること」
      • 「異なるタスクを学習することで区別可能な感情特徴量を学習できること」
    • 感情データセットは階層化
      • level 1 : 2 [categories](basic)
      • level 2 : 6 [categories]
      • level 3 : 25 [categories](fine-grained)

f:id:motojapan:20180818160049p:plain
(適切な粒度と呼ばれる25分類:出典より抜粋)

  • 効率的なカリキュラム的学習
    • データセットに跨った様々なタスクに対してパフォーマンスがでる
    • 連続的手順により学習することが可能
    • 基本は、学習ステージを分け、早期ステージではlebel 1、後半に進について高いlevelを学習
    • 上記を満たすようにCNNに情報を挿入していくようなモデル(ResNet-50 base)

f:id:motojapan:20180818160053p:plain
(各データセットでのテスト結果:出典より抜粋)
f:id:motojapan:20180818160057p:plain
(テスト結果:出典より抜粋)

読み時間2時間:執筆時間30分:勘違い、間違いあれば教えていただけると嬉しいです。

以上。

【ECCV2018 論文メモ#1】Learning to Anonymize Faces for Privacy Preserving Action Detection

ECCV2018まで1ヶ月を切ったので興味がある論文のメモを残していく。(
1日1本のペースで空き時間を使ってやっていきたい。(多分無理だ)

今回の論文と出典

Learning to Anonymize Faces for Privacy Preserving Action Detection
https://arxiv.org/abs/1803.11556

著者

Zhongzheng Ren, Yong Jae Lee, Michael S. Ryoo

内容

  • アクション検出を維持しながらプライバシーのための顔情報匿名化の学習
  • アクション検出とは、「電話をする、歯を磨く、化粧をする」などを指す
  • 顔情報匿名化とは、既存手法では、顔へのBlurやMask、Noiseなどを指す

f:id:motojapan:20180817012039p:plain
(既存匿名化手法例 / 上図:出典より抜粋)

  • 提案手法では、より自然にシーンやアクションを維持したピクセルレベルの匿名化が可能

f:id:motojapan:20180817012042p:plain
(左顔は提案手法匿名化前、右顔は提案手法匿名化後 / 上図:出典より抜粋)

  • GANの仕組みをベースに敵対的学習する
  • 「異なる見た目の修正顔を作るGenerator(Modifier)」
  • 「修正顔であるにも関わらず正しく個人識別できるように学習するDiscriminator」
  • 更にマルチタスク学習として、ActionDetectionを統合して精度を高めている

詳細

  • モデルは下図の通り

f:id:motojapan:20180817012036p:plain
(モデル / 上図:出典より抜粋)

  • fr_{v}は、顔画像 (r_{v}はFaceDetection後の画像となる)
  • Action Detectionは、Faster RCNN
  • Face Detectionは、SSH[29]
  • Face Recognitionは、Sphereface[26]
  • Generatorは、個人識別精度を最小化したい
    • InputとOutputで別人にしたいので
  • Discriminatorは、個人識別精度を最大化したい
    • (修正済みだろうと)どんな入力が来ても正しく識別できてしまえるようにしたいので
    • Tips : 大量のデータで事前学習しておく
  • L_{det}L_{l1}は最小化、 L_{adv}は、最大化するように最適化していく
  • L_{l1}は、Photorealistic Lossで、l1のみだと今回のプライバシータスクに最適でないため、 λを入れ、生成した顔画像の酷似を防止している

以上。

【python】raspiでwebカメラとpicameraの両対応コードを実装

モチベーション

カメラをフラグ(PICAM = True )で切り替えられるようにしたい。

[カメラ初期化] cv2.VideoCaptureの置き換え

これはpicameraだと動かないはず。
カメラのイニシャライズをcap取得のwebカメラ、piカメラ両対応する関数を作成。

def initCamera():
    cap = None
    res = False
    while res is False:
        if PICAM:
            cap = picamera.PiCamera()
            # cap.start_preview()
            cap.resolution = (640, 480)
            cap.framerate = 33
            cv2.waitKey(1000)
            res = True
        else:
            cap = cv2.VideoCapture(DEVICE_ID)
            res, _ = cap.read()
            #pass
            cv2.waitKey(1000)
            print('retry ..')
    return cap

そしてcv2.VideoCaptureを置き換え。

cap = cv2.VideoCapture(device_id)
↓
cap = initCamera()

[画像取得] cap.readの置き換え

こちらもpicameraだと動かない気がする。
picameraはstreamから取ってくるので、次のようなwebカメラpiカメラ両対応の関数を作成する。

def getImage(cap):
    c_frame = None
    if PICAM:
        with picamera.array.PiRGBArray(cap, size=(640, 480)) as stream:
            c_frame = cap.capture(stream, 'bgr')
            c_frame = stream.array
            if c_frame is None:
                exit

    else:
        end_flag, c_frame = cap.read()
        if end_flag is False or c_frame is None:
            exit
    return c_frame


そして置き換え。

img = cap.read()
↓
img = getImage(cap)

以上。

【ipython/jupyter】 ipython notebookの出力データを外部からclearする方法

ipython notebookもしくはjupyter notebookで日頃の作業をしている中で

  • 大量のログを出力したままファイルを閉じたり
  • ログを出しすぎて処理が重くなり、不用意にterminateしたり

して、次の実行時にipynbファイルの展開が遅くなったり、最悪展開できない、kernelが展開時にterminateすることがある。

その時の対処法をメモ。
やりたいこと=外部から出力カラムを削除

$ pip install nbclean
$ python
> import nbclean
> c = nbclean.clean.NotebookCleaner('./hoge.ipynb')
> c.clear(False, True)
> c.save('./hoge_cleaned.ipynb')

ポイントは下記。

> c.clear(False, True)

これの第一引数が入力カラム、第二引数は出力カラムを削除するフラグ。
間違えて、第一引数をTrueにするとコード本体が消える。

詳細はこれ。
https://www.pydoc.io/pypi/nbclean-0.1/autoapi/clean/index.html

追記: それでも開けない場合、ブラウザが未対応なデータを読み込もうとしていたりするので、起動ブラウザを変更してみる。


(個人的にipython notebookを日頃使います)

iPad 9.7 用にpencilケースを100円(格安)で自作する方法

f:id:motojapan:20180418003938j:plain

また箸休めですが、今回は最近買ったiPad 9.7 (2018)とApple pencilの為に、100円程でpencilホルダーを作成しました。(ついにこのブログで縫い物を紹介するとは思いませんでした)

最初に断っておくと、私はApple信者ではないので、デザイン性より利便性、カスタマイズ性、重量を重視しております。

なので、「せっかく廉価モデルのiPad 9.7 2018買って費用安く抑えたのに、ケースやらなんやらで4〜5000円とか払うのなんてやだよ!」って人にはオススメです。

別にすごいことはなく誰でも思い付くアイディアではあります。

必要なスキルは、「縫い物ができること」のみです。
(縫い物できなくてもいいですね、そうミシンがあればね)

完成画像

まず完成形はこちら。

iPadiPadのケースに巻きつけるようなゴムバンドケースを作成しました。
f:id:motojapan:20180418010515j:plain

ケースに取り付けるとこんな感じ。
f:id:motojapan:20180418011654j:plain

割とサラサラとしたゴムバンドなので上から左にスライドすると、
f:id:motojapan:20180418012853j:plain
下から「ぴょこん」と出てくる。(これがかなり便利)
f:id:motojapan:20180418012901j:plain
すっ、、、ぴょこん!
f:id:motojapan:20180418011640g:plain

作り方

作り方のまとめはこちら。
※慣れの為に、図や絵はApple Pencilで書いてます。(割と書ける)

f:id:motojapan:20180418013017j:plain

雑だけどこれが全てである。
大雑把に言うと、20mmゴムバンドを一周半して重なる部分をコの字に縫い付けるだけでできる。

必要な材料と道具

材料

  • 20mmゴムバンド (税別100円)
  • 刺繍糸
  • ボンド
  • 爪楊枝 (option)

道具

  • 定規
  • ハサミ
  • 刺繍針
  • 待ち針 (option) 

手順

スーパーシンプルな3ステップです。

1. 測って

f:id:motojapan:20180423010722p:plain

まずゴムバンドを635 [mm] 切り出す (幅はそのまま 20 [mm])
f:id:motojapan:20180423004829j:plainf:id:motojapan:20180423005755j:plain

【重要】切り出した両端はボンドをつけて乾かす
f:id:motojapan:20180423004959j:plain
解れ防止です。
放置、もしくは、ドライヤーで乾かすとあらキレイ。
f:id:motojapan:20180423005237j:plain

2. 折り曲げて

f:id:motojapan:20180423010816p:plain

横から見た図は実際にはこんな感じ。(オーバーラップは145 [mm] あればOK)
f:id:motojapan:20180423005325j:plain
マチ針か仮縫いで留めておく

3. 縫って(終了)

f:id:motojapan:20180423010828p:plain
オーバーラップ部分をコの字に縫い付けていく
(私は左下から縫っていく)
f:id:motojapan:20180423005941j:plain
一応、縫う所のイメージ(赤線を上下で繋げる)
f:id:motojapan:20180423012816j:plain
縫い付けは端から 2 [mm] ぐらいだといい感じにペンをホールドしてくれる

途中経過はこんな具合
f:id:motojapan:20180423012652j:plain

【重要】コの字出口は5 [mm]ほど残しておく(反対側からの写真)
f:id:motojapan:20180423012544j:plain
これを残しておくと、スライドした時にここがストッパーになるし、差し込む時の目印にもなるので便利

あとは無心で縫って完成
f:id:motojapan:20180423005959j:plain

所感

  • ペンケースの保持力もOK(逆さにしても落ちる気がしない)
  • スライド感もOK
  • めちゃくちゃ便利
  • 2週間程使っているが、全く壊れそうにない

ペンキャップ Ver.も作ったがそれも便利だった。

Julia言語とは(備忘録 : 更新版)

twitterなどで目にする機会が増えて、昨日初めてJuliaチュートリアルに参加したので備忘録。(更新版)


チュートリアルで頂いたステッカー↓↓
f:id:motojapan:20180324113623j:plain
可愛いね。

Juliaについて

  • 本家サイト https://julialang.org/
  • Github上で開発されるOSS
  • 2012年公開、現在のバージョンはv0.6.0(0.7.0-DEV)
  • 数値計算や科学計算処理向けの動的プログラミング言語
  • 科学計算処理向けのため、下記を実現・意図する。
    • 数式記述が楽(文法やコマンド)
    • ライブラリが豊富
    • 処理速度が早い
    • 処理量に対するスケーリング(分散処理)
  • その他の特徴は
    • モダンな言語仕様
    • UTF-8対応
    • etc...

Juliaのライセンス

MITベース
ただし中にあるプロジェクト単位で様々なライセンスがぶら下がっている模様 
商用利用はお気をつけて。
julia/LICENSE.md at master · JuliaLang/julia · GitHub

Juliaは何故早い

細かいことはよくわかりませんが、わかっていることだけで

  • LLVMベースの高パフォーマンスJITコンパイラを搭載
    • 実行前の型推論や最適化などでC(ネイティブ)相当の処理速度を目指す
    • 本家サイトのベンチマークにもあるようにCに遜色ない速度という参考結果
  • バージョンアップによる高速化とチューニング

Juliaを始める人

こんな人が多い気がする

簡単に始める方法

パッケージ

https://pkg.julialang.org/
2018/3/24時点で1749パッケージが登録されている
個人的に、Mamba.jl , BackpropNeuralNet.jlに興味がある
github.com
github.com

他の言語を実行可能

Julia上でgccやclangが実行できるため、C, Fortranのコードを実行可能
Calling C and Fortran Code · The Julia Language
Juliaboxのチュートリアルにもある

Cxx.jiで対話実行できるのでこっちも。
github.com

所感

  • 基本的に数値演算がめちゃめちゃ書きやすい!
  • 型指定や型比較が厳密(で個人的に好き)
  • ruby同様に破壊的関数などのシンタックスがあり読みやすい
  • 関数定義が多様でシンプルなものは1行で定義できて楽だし、直感的
  • モダン言語仕様であるため、書きやすく、python文法や演算記述も類似性がある
  • (まだ全貌をちゃんとわかってないな〜、勉強しよう)

勘違いがあれば教えていただけると助かります。

勉強会はこちらでした。

data-refinement.connpass.com

【python】OCR(tesseract-ocr / pyocr)で賞味期限を読み取る(画像→数列) 【お家IT#19】

本件の実装の一部  
motojapan.hateblo.jp

前回の続き  
motojapan.hateblo.jp

目次

前回は、バーコード画像から商品情報を取得するところまで進めた。
ただ、商品情報には賞味期限情報は含まれていない。
今回は、OCRを用いて賞味期限を数値、記号情報として取得する。

OCRとは

Optical Character Recognition 光学的文字認識を指す。
紙面に書かれている文字情報を認識してデジタル化する技術であり、書籍や資料を電子化することでデータ圧縮や管理の容易化ができるだけでなく、ソフトウェアと連携してデータ分析なども可能となる。

今回は賞味期限を読み取りたい。
特に、stand-aloneで利用できるtesseract-ocrをpyocrから触ってみる。
(その他のライブラリは次回)

tesseract-ocr / pyocrとは

tesseract-ocrは、OCRエンジンである。
最新α版は、4.00.00alpha。
4系からは、OCR Engine Modeで、LSTMが選択できるようになっている。
(ただし、下記pyocrからは、Mode設定がサポートされていない模様で、LSTMは今回は試せなった)※2017/10時点
github.com

pyocrは、tesseract-ocrpythonから操作する為のWrapperである。
かなり感単に操作が可能となっている。

インストール

tesseract-ocrをインストール & チェック

#install
$ sudo apt-get install tesseract-ocr

#check
$ tesseract -v
tesseract 3.03
  leptonica-1.71
   libgif 4.1.6(?) : libjpeg 6b : libpng 1.2.50 : libtiff 4.0.3 : zlib 1.2.8 : libwebp 0.4.1 : libopenjp2 2.1.0

pyocrをインストール & チェック

#install
$ pip install pyocr 

#check
$ python
>>> import pyocr
>>> pyocr.get_available_tools()
[<module 'pyocr.tesseract' from '/usr/local/lib/python2.7/dist-packages/pyocr/tesseract.pyc'>]

使い方と実装

pyocr.builders

pyocr.buildersには次の5つの使えそうなBuilderがある。

TextBuilder 文字列を認識
WordBoxBuilder 単語単位で文字認識 + BoundingBox
LineBoxBuilder 行単位で文字認識 + BoundingBox
DigitBuilder 数字 / 記号を認識 今回はこれを採用
DigitLineBoxBuilder 数字 / 記号を認識 + BoundingBox

今回は、撮影枠を準備しているので、DigitBuilderを採用。

tesseract_layout (pagesegmode)

tesseract_layoutを設定しているが、ここは次のpagesegmodeの番号と対応している。
ここの設定でかなり精度は変わる。
デフォルト設定は、tesseract_layout=3。
今回は、tesseract_layout=6で、単一ブロックとして認識。
OSDとは、On Screen Display? サブタイトルなどの認識に利用するらしい。

pagesegmode values are:
  0 = Orientation and script detection (OSD) only.
  1 = Automatic page segmentation with OSD.
  2 = Automatic page segmentation, but no OSD, or OCR
  3 = Fully automatic page segmentation, but no OSD. (Default)
  4 = Assume a single column of text of variable sizes.
  5 = Assume a single uniform block of vertically aligned text.
  6 = Assume a single uniform block of text.
  7 = Treat the image as a single text line.
  8 = Treat the image as a single word.
  9 = Treat the image as a single word in a circle.
  10 = Treat the image as a single character.

実装

import time
import pyocr
from PIL import Image
import pyocr.builders

#img : PIL image
def get_digit_ocr_info(img):
    result = None
    start_time = time.time()
    print('******** start convert_image_to_deadline  *********')

   width, height=img.size

    tools = pyocr.get_available_tools()
    tool = tools[0]
    print(tool)
    langs = tool.get_available_languages()
    print("support langs: %s" % ", ".join(langs))
    #lang = langs[0]
    lang = 'eng'  #言語設定で、「英語」を選択

    digit_txt = tool.image_to_string(
      img,
      lang=lang,
      builder=pyocr.builders.DigitBuilder(tesseract_layout=6)
    )
    print('DigitBuilder', digit_txt)

    print('******** end convert_image_to_deadline  *********')
    return digit_txt

結果

色々なパターンを12件ほど評価。


入力画像

tesseract+pyocr



2018. 6.12



18.12.31



2018. 5. 7



18.09.14



18.03.28



4 13 11-13 . . 3



2017.12 31



4 21 3



13. 1-7



17.12.22



20-178.... 3 13



2311 8.13

200 x 60 の画像に対して、処理速度は、2 - 3 [s]程度。結構時間がかかる。
上手くいくものもあれば、厳しいものもある。
特に、太い文字、判で刻印されたシャープな数字はかなりいい感じだが、無駄な文字が含まれている画像、暗い画像、ドット記載されている数字が上手く読み取れていない印象。

以上。

これでシステム全体の開発は終わり。
また何か作る予定です。

今回触れなかった他のOCRライブラリの話もそのうち纏めたい。