ハードウェア技術者のスキルアップ日誌

某家電メーカーの技術者がスキルアップのために勉強したことを記録するブログです

struct2depth(距離推定)を動かしてみた

久しぶりにGITHUBで公開されているDeep Learningのネットワークを動かしてみました。今回はtensorflowのソース内にあるstruct2depthです。慣れていればどうってことないのでしょうか、初見でつまずいてしまったので、手順を記録しておきます。

struct2depthとは?

Google Brainが開発した、単眼カメラから深度とエゴモーション(カメラ自身の動き)を推定する手法です。取得するのが難しい、距離の正解情報を必要とせずに距離推定器を学習させることができるのが特徴です。

プロジェクトサイト

https://sites.google.com/view/struct2depth

動作環境

 ● OS : Windows 10 Home (64bit)

 ● Python 3.5

 ● Anaconda 4.2.0

 ● Tensorflow 1.12.0

手順

GITHUBからレポジトリをクローンする

https://github.com/tensorflow/models
struct2depthはツリーの中のresearch/struct2depthにあります。

②struct2depthフォルダ内にinput, output, modelというフォルダを作る

f:id:masashi_k:20190925230058p:plain

③学習済みモデル(ckptファイル)をダウンロードし、modelフォルダに格納する

KITTIで学習したモデル
Cityscapesで学習したモデル

※KITTI, Cityscapesは車載カメラで撮影した画像と距離情報を含むデータセット

④推論したい画像をinputフォルダに格納する

試しにKITTIの画像データの一部を使って推論を行います。
KITTIのデータセットこちらからダウンロードできます。
今回は2011_09_26_drive_0002 を使います。
Image_03の中の画像をinputフォルダにコピーします。

f:id:masashi_k:20190925231114p:plain

⑤util.pyを修正する

このまま推論を実行すると私の環境では画像ファイルの読み込みで以下のエラーが発生しました。

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte


以下のようにutil.pyを修正します。

def load_image(img_file, resize=None, interpolation='linear'):
  """Load image from disk. Output value range: [0,1]."""
  #im_data = np.fromstring(gfile.Open(img_file).read(), np.uint8)  #コメントアウト
  #im = cv2.imdecode(im_data, cv2.IMREAD_COLOR) #コメントアウト
  im = cv2.imread(img_file)  #追加
  im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
  if resize and resize != im.shape[:2]:
  ip = cv2.INTER_LINEAR if interpolation == 'linear' else cv2.INTER_NEAREST
  im = cv2.resize(im, resize, interpolation=ip)
  return np.array(im, dtype=np.float32) / 255.0


⑥Anacondaを起動


⑦以下のコマンドで推論を実行

python inference.py --logtostderr --file_extension png --depth --egomotion true --input_dir input --output_dir output --model_ckpt model/KITTI/model-199160

outputフォルダに推論結果(距離画像とegomotion)が出力されます。

以下は結果の一例です。
右側の自転車に乗っている人と電柱が正しく推定できていることがわかります。

f:id:masashi_k:20190925233210p:plain


カメラ入力での推論

ここまではGITHUBの情報とほぼ同じですが、USBカメラで撮影した画像を入力してリアルタイムで距離推定を行ってみました。

inference.pyの中の関数_run_inferenceを以下のように修正し、inference_webcam.pyという新しいpythonスクリプトを作ります。

import cv2  #追加

##############
# 中略
##############

  with sv.managed_session() as sess:
    saver.restore(sess, model_ckpt)
    if not gfile.Exists(output_dir):
      gfile.MakeDirs(output_dir)
    logging.info('Predictions will be saved in %s.', output_dir)

    #input camera image
    video_capture = cv2.VideoCapture(0)
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    out = cv2.VideoWriter(output_dir + '/' + 'webcam.mp4', fourcc, 25.0, (416, 128))


    # Run depth prediction network.
    while True:
      if depth:
        im_batch = []

        ret, im = video_capture.read()
        im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
    #VGAの画像を切り出して416x128に合わせる
        ymin, ymax, xmin, xmax = [142, 339, 0, 640]
        im = im[ymin:ymax, xmin:xmax]
        im = cv2.resize(im, (416,128))
        im = np.array(im, dtype=np.float32) / 255.0

        im_batch.append(im)

        #im_batch.append(np.zeros(shape=(img_height, img_width, 3), dtype=np.float32))
        im_batch = np.stack(im_batch, axis=0)
        est_depth = inference_model.inference_depth(im_batch, sess)

        if flip_for_depth:
          est_depth = np.flip(est_depth, axis=2)
          im_batch = np.flip(im_batch, axis=2)

        color_map = util.normalize_depth_for_display(np.squeeze(est_depth))
        color_map = (color_map * 255.0).astype(np.uint8)
        color_map = cv2.cvtColor(color_map, cv2.COLOR_RGB2BGR)

        out.write(color_map)
        cv2.imshow('video', color_map)
        im_batch = []

      if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    video_capture.release()
    out.release()
  cv2.destroyAllwindows()

ソースコードの中で入力画像の加工を行っています。
ネットワークの入力解像度が416x128なので、カメラで撮影したVGAの画像をクリップ、リサイズして416x128の画像を作成しています。

以下のコマンドで推論を実行します。

python inference_webcam.py --logtostderr --file_extension png --depth --egomotion false --output_dir output --model_ckpt model/KITTI/model-199160


以下の画像はノートPCについているカメラで撮った映像を入力したときの結果です。

f:id:masashi_k:20190925235756p:plain

赤で囲ったところに手をかざしているのですが、何なのかよくわからない結果となっています。また、右側の黄色っぽところは何もないのですが、この部分は距離が近いと推定されています。
車載カメラで撮影した映像とノートPCについているカメラで撮った画像では違いが大きすぎて、学習結果をそのまま使うには無理があるのでしょう。用途に合わせた再学習が必要ということですね。

まとめ

Googleが開発したstruct2depthというネットワークの動かし方とUSBカメラで撮った映像で推論する方法をまとめてみました。何かのお役に立てればと思います。

参考サイト

[DL輪読会]Depth Prediction Without the Sensors: Leveraging Structure for…

【読書記録】ー 転職と副業のかけ算

今回はmotoさんの「転職と副業のかけ算」という本を読んだので、学んだことを書いていきたいと思います。

転職と副業のかけ算 生涯年収を最大化する生き方

転職と副業のかけ算 生涯年収を最大化する生き方

 

著者のmotoさんのことはtwitterで知りました。
この本が発売された直後、多くの推薦ツイートが挙げられていました。
本書は自分の最近の活動のテーマである、「会社に縛られず生きていける力をつける」ということと共通する内容であり、その成功例として研鑽の仕方、キャリアの作り方を学ばせていただきたいと思います。

 

これからの社会を生き抜くには

終身雇用、年功序列といった昭和、平成の雇用制度はこれからは期待できません。
会社の言いなりになり、言われた仕事をこなすだけの人間はいつリストラされてもおかしくありません。

これからの時代、安定的に暮らしていくには個人で稼ぐ力を身に付けていくことが必要です。会社に依存せず、いざとなったら転職できる、副業で収入を得るといった状態にしておくことが理想的でしょう。

自分の市場価値を伸ばす

いつでも転職できる状態にしておくためには、自分の市場価値を高め、企業から欲しい人材になっておくことが必要です。それは必ずしも会社内での評価とは一致しません。
あくまで転職市場での市場価値です。

市場価値が高い人とは、どんな環境であれ、組織を成長されられる人。会社に利益をもたらす人だと思います。そのような人になるために、スキルアップを図っていく必要があります。

私は結果が出ないことを周りの人や環境のせいにしてしまうところがあるのですが、市場価値の高い人はそのようなことに言い訳をしないはずです。この本を読んで考えを改めるべきと反省しました。

本業で実績を出す

スキルアップというと、社外のセミナーなどを受講するといったイメージがあるかもしれませんが、motoさんはあくまで本業で実績を出すことが大前提と言われています。

自分がやったことのない仕事は自分を成長させるチャンスです。このような機会を見逃さず、積極的に取りに行き、苦しい中でも仕事に全力を尽くすことで力がついていきます。

できるかどうかわからないことでもまずやってみる。たとえ失敗して会社の評価が下がっても、経験値を得ることが市場での評価が高まります。多くの場合、会社側もチャレンジを認めてくれるでしょうから、デメリットはそれほど多くありません。
まず手を挙げる!

そして、そのような新しい仕事を振ってもらえるようにするためには、自分がやりたいこと、実現したい姿を周りに発信することが重要。そうすれば上司も希望を叶えようとしてくれるでしょうし、自分も公言したことに対して必死になるはずです。結果として、成長が加速していきます。

 

自分株式会社

本書の中で一番印象的だったワードが「自分株式会社」というものです。
自分自身を会社に見立て、自分という会社を経営する。そのような考えに立つと、会社の利益を上げるためにはどうすべきかが見えてきます。

本業の収入UP、副業、、、どのような価値を提供すれば収入UPにつながるか。
このような意識の有り無しで、仕事の質も変わってくるように思います。

副業のノウハウ

副業は物販や投資などいろいろなやり方がありますが、motoさんが勧めるのはブログや動画などのコンテンツ配信です。本業で得た知見や人の役に立つ情報をブログで発信することで収入にします。もちろん、所属する会社の機密情報を漏らすことがないように。

ブログへの誘導はtwitterが有効です。ただ、やみくもにブログの記事のリンクを貼ってつぶやくのではなく、twitter上で自分はどういうことができる人なのか、というブランドを築いていくことが必要だそうです。motoさんの場合は「転職に詳しい人」。
自分のブランドは、自分はどういう方向にスキルを磨くのかということに大きく関わるので、自己分析をしっかりやって、やりたいことを明確にしておくことが重要です。

ブランディングのためには「自分が誰よりも詳しい情報を他の人が役立つ形で発信すること」が大切。そして、自分の意見に共感してくれるフォロワーが必要。motoさんは同じ意見の他人のツイートに対し、引用リツイートすることでフォロワーを増やされたそうです。このような戦略的なSNS活用方法は非常に参考になります。

まとめ

motoさんの「転職と副業のかけ算」という本で学んだことをまとめてきました。

自分が目指す姿を実現されているmotoさんのノウハウを知ることができ、非常に有益な内容でした。特に、本業で実績を出すための心構えはmotoさんほどではないにしろ、意識していたことであったため、今までやってきたことが正しかったと再認識できました。

このブログもマネタイズできるところまで行ければいいですが、まずは勉強したことのアウトプットの場として、記事数を増やすことを優先にしていきます。ただ、独りよがりの内容ではなく、人の役に立つ情報をお伝えできるようにこれからコンテンツを検討していこうと思っています。

私は現在転職を考えてはいないので、本業の取り組み方、副業のやり方について学ぶことが多かったですが、本書には転職ノウハウもふんだんに書かれています。転職を考えておられる方にもおすすめの本です。

転職と副業のかけ算 生涯年収を最大化する生き方

転職と副業のかけ算 生涯年収を最大化する生き方

 

  

【読書記録】ー 考具

技術者という仕事をやっていてもアイデアを求められることは常日頃あります。
そのような周りからの期待に応えたい気持ちは山々なのですが、中々いいアイデアを出せず、悔しさを感じていました。
そんな中、書店で「考具」という本を見つけたので、アイデア出しのヒントになればと思い読んでみました。

考具 ―考えるための道具、持っていますか?

考具 ―考えるための道具、持っていますか?

 

 文体が著者が語りかけてくれているような感じで非常に読みやすく、且つ、今までの自分の考えと違う気づきが多く得られました。

今回は本書を読んで学んだ、アイデアの出し方、企画の作り方をまとめていきます。

 

イデア出しにあたっての考え方、心構え

イデアを出せる人とそうでない人の違いは「意識」をしているか

普段の生活でアイデアのヒントを探しているか。
ぼーっと生きているだけではアイデアは生まれない。

イデアはまず自分がどうしたいか、欲求から生まれる

「わがまま」⇒「思いやり」
周りの意見や状況から考え始めてもありきたりなものしか生まれない。

イデアは既存の要素の組み合わせでしかない

自分が考えているその領域にとって新しければよい。
どこか別の業界のやり方を持ってきてもOK。

とにかく量を出すことが大事

大したことないと思うことでも頭の中に留めずに紙に書く。

 

イデアを生み出すための4ステップ

1.アイデアのネタ素を貯める

2.目の前の課題についての情報を仕入れる

3.貯め込んだネタ素の中から使えそうなアイデアを引っ張り出す

4.ネタ素と課題について集めた情報を組み合わせて新しいアイデアを生み出す

この方法を使い、できるだけたくさんのアイデアを出す。
少なくとも30案は必要。
絞るのは後で出来るので、この段階ではアイデアを広げる。

 

イデアを企画に落とし込む方法

イデアの組み合わせ、パーツの交換などを行い、使えそうなものに絞る

企画の全てが新しいアイデアでなくてもOK。
肝の部分が新しければ、その他の部分は従来の手法を使うこともある。

絞ったアイデアを実行可能なところまで具体化していく

実現可能なアイデアが企画。
関係先との調整など、詳細を詰めるところまでやって初めて提案できるものになる。

 

情報インプットの考具

f:id:masashi_k:20190907225045p:plain

①カラーバス

何か(色、形状、位置、音など)を意識して生活すると、意識したことが引っかかって普段はスルーしていた情報が自分の中に入ってくる。頭の中でその気づきを意識するだけで十分。いつかのアイデア出しの時に組み合わせの素になる。

②聞き耳

電車、ファミレス、喫茶店、居酒屋などで周りの人の会話に聞き耳を立てる。話の話題やその人の様子から顧客の生活を想像する。(どんなことに興味があるのか、どんなことに困っているのかなど)

③お客様の立場に立って演じる

頭の中でお客様のことを想像するだけでなく、実際にお客様の立場に立って同じことをやってみる。例えば、商品を使う、サービスを受ける、子供向けのものを考えるのであれば、目線を下げるなど。実際にやってみないとわからない気づきがある。

④現場に行く

お題となる現場に行き、できるだけ詳しく取材する。話を聞きだすコツは相手を褒めながら聞くこと。

⑤気になったら何でもメモ

気になったことを書き留める。手を動かすという行為でいざというときに思い出す。できるだけビジュアルでメモを書くとよい。

 

イデア展開のための考具

f:id:masashi_k:20190907230724p:plain

ポストイット

1枚1ネタを書き、大きな紙に貼っていく。思いついたものをそのまま書く。ネタ同士の組み合わせから別のアイデアが出てくる。

②マンダラート

テーマを9マスの真ん中に書き、アイデアを周りに入れていく。8個マスがあるため、強制力が働く。すべてのマスが埋まったらそれぞれのアイデアをマスの中心にし、さらにアイデアを広げていく。マスはすべて埋める必要はなく、膨らみそうなアイデアがあればそれを広げていけばOK。

マインドマップ

テーマを真ん中に書き、思いついたアイデアや要素を放射状に書く。マンダラート同様、各アイデアからさらにアイデアを広げていく。結びつく言葉を線でつなぎ、組み合わせでアイデアを作っていく。アイデアのヒントとなる言葉が一枚の紙の上にひしめき合って並ぶ形になる。

④連想ゲーム

お題から「~といえば」という問いかけでどんどん言葉を広げていく。頭の中の記憶を呼び起こし、それが今の課題と合わさって新しいアイデアが出る。

⑤オズボーンのチェックリスト

転用・応用・変更・拡大・縮小・代用・置換・逆転・結合
イデアを生み出すための要素の組み合わせ方の基本パターン9つ。一つの事象をいろんな角度から見ることでアイデアが生まれる可能性を何倍にも広げることができる。

全てにおいて共通していることは、テーマをいろんな切り口で深堀し、組み合わせの要素を抽出すること、そして要素同士の組み合わせで新しいアイデアを作っていくこと。型にこだわりすぎず、アイデアが膨らむところがあれば、そこを突き詰める。

 

企画へ落とし込むための考具

5W1H

いけそうなアイデアをお題の条件(5W1H)に当てはめる。先に条件から考えないこと。あくまでアイデアができてそのあとで5W1Hを考える。最初から条件を満たすことはないので折り合いをつけていく。

②タイトル

企画に必ずタイトルをつけること。初めて聞く人に概要をわかってもらうためのもの。言葉を具体的にすることで伝わる情報が増える。

③絵で表現

プレゼンをするときはできるだけ自分のイメージを絵にして伝える。絵で表現できる=企画の詳細なイメージを自分の中で詰められているということ。詳細まで丁寧に絵で表現する。

 

感想

 タイトルの通り、アイデアの素となる情報のインプット、アイデア出し、企画の作り方までたくさんの「考具」が紹介されています。ポストイットなどはよく使っていましたが、今まで知らなかったものもあり、特にマンダラートはこれから試してみたいと思っています。

本書を読んで感じたのは、企画を生み出すためには日ごろから課題意識をもって世の中を見ることが必要だということです。そうすれば、生活の中で得られる情報も変わってくるし、自ずと新しい要素同士の組み合わせも生まれるのではと思います。

そのような意識を持った状態で考具を使って考える時間を作れば、さらにいいアイデアを生み出すことができるでしょう。斬新なアイデアを出せる人を目指して、考具を活用していきたいです。

 

ラズパイでUART通信を行う

前回、ラズパイでハードウェアを制御する方法の勉強をスタートしました。

masaeng.hatenablog.com

少し間が開いてしまいましたが、第二回目はUART通信です。
UARTはマイコンデバッグ用通信やデバイス間通信などによく使われていますね。ラズパイでUARTを使う方法を調べましたので、必要な時にすぐ使えるように整理しておきたいと思います。

UARTとは?

UARTはUniversal Asynchronous Receiver Transmitterの略で、非同期方式による通信です。UARTの信号線は送信用のTXDと受信用のRXDの2本です。

規格の詳細は割愛しますが、こちらのサイトに詳しく書かれています。

tri-s.world.coocan.jp

 

ラズパイとデバイスの接続

ラズパイでUARTを使用するにはデバイスと以下のように1対1で接続します。
ラズパイのUART端子は設定を変えることでGPIO14をTXDに, GPIO15をRXDに割り当てることができます。

   f:id:masashi_k:20190825225842p:plain

同じUARTに複数のデバイスを接続することはできませんので注意。

 

UARTを使うための設定

Rasbianのデフォルト設定ではラズパイでUARTを使うことはできません。
以下の2つの設定が必要となります。

①シリアルコンソールの設定

プログラムで使用するUARTは/dev/serial0ですが、デフォルトではOSの
シリアルコンソールが/dev/serial0を使用するようになっています。
(USBシリアル変換ケーブル経由でGPIO14,15とPCをつなぐことで
PCのターミナルソフトからラズパイにアクセスできる)

シリアルコンソールが/dev/serial0に接続しないように/boot/cmdline.txtに記載されている”console=serial0,115200”を削除する必要があります。 

f:id:masashi_k:20190825233940p:plain

②UARTの有効化

ラズパイに搭載されているSoC BCM2835は高機能なPL011 UARTと機能が限定されたmini UARTの2種類を搭載しています。デフォルトはPL011 UARTだけが有効でBluetoothモジュールに割り当てられているのでプログラムがUARTを使用することはできません。
/boot/config.txtに"enable_uart=1"を追記するとMini UARTがGPIO14,15に
マッピングされます。(図の(2))
さらに"enable_uart=1"の代わりに"dtoverlay=pi3-miniuart-bt", "core_freq=250"を追記するとPL011 UARTがGPIO14,15にマッピングされ、高機能なUART機能を使用可能になります。この時BluetoothモジュールはMiniUARTに接続されます。(図の(3))

f:id:masashi_k:20190825232040p:plain

 

UARTで通信を行うプログラム

ラズパイのpythonでUART通信を行うにはpySerialライブラリを使用します。Raspbian標準搭載されています。以下にサンプルコードを示します。

import serial
import binascii
ser = serial.Serial('/dev/serial0', 115200, timeout = 0.5)  #UART初期化

#コマンド送信
ser.write(b'\x22\x00\x00\x22') #4バイトのByte型でデータを送信
ser.write("hello")

#コマンドの結果を受信(4byte)
data = ser.read(4)
#コマンドの結果を受信
data = ser.readline()  #区切り文字0x0Aまでのデータを受信

#binデータで読み出されるので結果をhexに変換
data=binascii.b2a_hex(data)

ser.close() # ポートのクローズ

 

まとめ

ラズパイでデバイスとのUART通信を行う方法を記載しました。UARTのみをインターフェスにもつセンサーを使いたい場合は、この方法でセンサーデータを取得できると思います。今手元にデバイスがなく、実際に動作確認はできていませんが、機会があれば、動作結果を追記します。

 

参考サイト

qiita.com

【読書記録】- PLAY WORK

今回は「PLAY WORK」という本を読みましたので、要点をまとめます。

PLAY WORK プレイ・ワーク 仕事の生産性がグングン高まる「遊びながら働く」方法

PLAY WORK プレイ・ワーク 仕事の生産性がグングン高まる「遊びながら働く」方法

 

 著者のピョートルさんは元Googleの方で働き方や組織に関する本を多数出されています。以前「NEW ELITE」を読ませてもらって、働く上での考え方で大いに刺激をもらったので、今作も期待して読みました。

ニューエリート グーグル流・新しい価値を生み出し世界を変える人たち

ニューエリート グーグル流・新しい価値を生み出し世界を変える人たち

 

それでは、早速まとめていきたいと思います。

PLAY WORKとは?

遊ぶように働く、仕事と遊びの境があいまいな働き方

落合陽一さんが著書の中で言われていましたが、「ワークアズライフ」(寝ている時間以外はすべて仕事でありその仕事が趣味である)に通ずる考え方だと思います。

 

PLAY WORKに必要な4つのステップ

①自己認識

問いを通して自分に向き合い、自分を掘り下げる
 ・自分とは何?何をしたい?どうなりたい?
 ・自分が本当にやりたいことは?
 ・子供の頃、何に一番興味があった?
 ・学生の頃、どんなふうに活躍したいと思ってた?
 ・この一週間楽しかったタスクは?それはなぜ?

「メモの魔力」でも言われていましたが、これから自分が何をしたいか、自己分析の重要性は高まっていくと思います。自己分析1000問はぴったりのツールですね。

②自己開示

自分がやりたいことを周りに伝える
 ⇒周りの人がやりたいことを手助けしてくれる

被害者意識はNG 「上司が○○してくれないからできない」
当事者意識に変える!

自己開示をするには考えを整理しないといけない
他者視点のフィードバックをもらえる
 ⇒自己開示をすると自己認識がますます深まる

③自己表現

自分がやりたいことを自分らしく実現すること =「仕事」
自分が提供できる価値は何かを考え、仕事の幅を広げていく

アクションはすぐ起こすことが大事 直感で動く
仕事は楽しんだもの勝ち! 楽しく仕事する!

自己実現

他人から言われた仕事を嫌々やるといった他人のための人生ではなく、
自分がやりたいことをやる「自分の人生」を生きる
 ”THIS IS YOUR LIFE. (これはあなたの人生です)”

自分にしかできないことで社会や周りの人に貢献していく
そうすれば楽しんで、前向きに仕事ができるようになる

まとめ

ここまでの内容をスライド1枚にすると以下のようになります。


f:id:masashi_k:20190824234913p:plain

この本で紹介されているPLAY WORKという働き方は自分の中では理想の働き方です。
仲間とワイワイ議論して、面白いことを実現するために素早く行動していく。
今は職場環境含めて理想とは差がありますが、そんな働き方に近づけながら自己実現を目指していきたいです。

Tensorflow ー 複数の学習済みモデルを同時に実行する

GITHUBで公開されているディープラーニングの学習済みモデルを流用し、
USBカメラ映像を入力して推論するというプログラムをいくつか作ってきました。
今まで動かしたプログラムは全てモデル1つだけを動かしていましたが、
複数の学習済みモデルを組み合わせて機能を作れないか試してみました。
動かし方を調べたのでまとめておきます。

 

モデルが一つの場合

以下のような構成でプログラムを書いていました。
USBカメラの映像をWhileループ内で取得するため、ループの外でセッションを作成し、学習済みモデルの復元までを行います。ループ内ではsess.run()のみを行います。

import tensorflow as tf
import cv2

video_capture = cv2.VideoCapture(0)

with tf.Session() as sess:
    saver = tf.train.Saver()
    saver.restore(sess, model_path)

    while True:
        ret, frame = video_capture.read()
        sess.run()

        if cv2.waitKey(10) & 0xFF == ord('q'):
            break
video_capture.release() cv2.destroyAllwindows()

 

 

ネットワークが二つの場合

2つの異なるグラフを作成し、それぞれのグラフのセッションを構築してモデルを復元します。そして、whileループ内でそれぞれのセッションを実行しています。

従来の処理ではwith tf.Session() as sess:の中にwhileループを置いていましたが、
withを使わずにSessionを作成するように少し変更しました。

import tensorflow as tf
import cv2

video_capture = cv2.VideoCapture(0)

with tf.Graph().as_default() as graph_1:
     saver1 = tf.train.Saver()
sess1 = tf.Session(graph = graph_1)
saver1.restore(sess1, model_path1)

with tf.Graph().as_default() as graph_2:
     saver2 = tf.train.Saver()
sess2 = tf.Session(graph = graph_2)
saver2.restore(sess2, model_path2)

     while True:
            ret, frame = video_capture.read()
            sess1.run()
            sess2.run()

            if cv2.waitKey(10) & 0xFF == ord('q'):
                 break

    video_capture.release()
cv2.destroyAllwindows()

 

参考サイト

事前に訓練された複数のTensorflowネットを同時に実行する - コードログ

 

Tensorflow - ckptからpbへの変換方法

PC上で学習したモデルを動かす際にはckptファイルで問題ないですが、iOS, Android上や組み込み機器上で動かしたい場合、pb(protocol buffer)形式のファイルが必要となります。ckptからpbへの変換方法を調べたのでメモしておきたいと思います。

ckpt, pbとは?

変換方法に行く前にckpt, pbのおさらいです。

Tensorflowで重み、ネットワーク構造を保存するデータのファイルが.ckptです。
check pointの略(?)です。

ckptファイルは3種類あります。
  ckpt.meta : モデルの構造を記述 重み情報はない
  ckpt.data : 実際の重みが入ったバイナリ
       ckpt.data-00000-of-00001のようなファイル名となる
  ckpt.index : どのファイルがどのstepのものかを一意に特定するためのバイナリ

 

一方、protocol bufferは元はGoogleが開発したシリアライズフォーマットとのことで、Tensorflowのグラフ(モデル構造と重み)をこのprotocol buffer形式で記述できます。

Protocol Buffers - Wikipedia

 

変換方法

以下の参考サイトでいろいろなやり方が紹介されていますが、私の環境でうまくいったサンプルコードです。

import tensorflow as tf
import models

graph = tf.get_default_graph()

sess = tf.Session()

saver = tf.train.import_meta_graph('test.ckpt.meta')
saver.restore(sess, 'test.ckpt')

tf.train.write_graph(sess.graph_def, '.', 'graph.pb', as_text=False)

まず前提として、学習は完了しており、そのネットワークや重みデータはckpt形式で保存されています。(test.ckpt) このckptファイルを用いてグラフを復元し、pb形式で保存しなおします。

tf.train.import_meta_graphを使って.metaからモデルをロードします。これを使えば新たにモデルのインスタンスを作る必要がありません。
そして、saver.restoreでckptを読み込み、学習済みモデルを復元します。
pb形式への変換にはtf.train.write_graphを使用します。 

こちらのサイトには、通常のモデルでは学習済みのWeightやBiasを保持するためのtf.Variableの変数を持つが、これをpbファイルに保存できないため、 
graph_util.convert_variables_to_constants() を使ってConstに変換する必要があると記載されています。
しかし、私の環境ではこれをやるとうまくいかなかったです。
もし、上記のやり方でNGであればこちらをお試しください。

 

参考サイト

https://codeday.me/jp/qa/20190407/569692.html

https://tyfkda.github.io/blog/2016/09/14/tensorflow-protobuf.html

http://workpiles.com/2016/07/tensorflow-protobuf-dump/

https://gist.github.com/funwarioisii/68ed46d8ccfcbc31a456b7c4166b8d0e