ロビ2の画像認識調査
2021年1月17日


 ロビ2の画像認識について調べてみました。
 ロビ2のプログラム(STARTUP.BIN)で画像認識を行っている部分と画像認識ボードへの命令について記述しています。

 画像処理ボードのステータスは0x08e0で取得できます。
 画像処理を行う前にこのステータスで画像処理ボードの異常を検出しています。
 ステータスは0の場合は正常で0以外の場合はで異常としてロビがを「カメラの調子がおかしいよ」と言います。

アイドリング時の顔認識

 ロビ2はアイドリング時に顔を認識すると目をピンクにしてその方向に顔を向ける機能があります。

 まず目をピンクにする部分は以下命令で行っています。
  0x00004f6b
   <calc><mem_r size="1" adr="0x0e88"/><const data="48"/><sub/><eq/><jump adr="0x00004f54"/></calc>
  0x00004f54
   <calc><mem_r size="1" adr="0x0e98"/><const data="0"/><sub/><gt/><jump adr="0x00005249"/></calc>
 0x0e88が48でかつ0x0e98が1以上の場合は目をピンクにしています。
 0x0e88が48は顔が認識されたというステータスで0x98は認識できた人数を表します。

 でかつ0x0e98が1以上の場合は目をピンクにしています。
 なお目をピンクにするモーションは0x000051b0(高輝度)と0x0000510a(低輝度)です。

 次に認識した顔が登録されている顔か次のサブルーチンでチェックします。
 0x000102e
   <call adr="0x0003811"/>

 このサブルーチンで次の命令で画像認識ボードから登録番号を取得しています。
  0x0e98 >= 1  の場合 0x0fa8 = 0x0e99(0x0e99 > 0)
  0x0e98 >= 2  の場合 0x0fa8 = 0x0ea1(0x0ea1 > 0)
  0x0e98 >= 3  の場合 0x0fa8 = 0x0ea9(0x0ea9 > 0)
 登録番号が取得できない場合は0x0fa8に-1を返します。

 この後次のサブルーチンでな認識した認識した顔の名前に変換します。
 0x000106a
   <call adr="0x0003971"/>

顔の追従機能

 顔を向ける処理はまず上記と同様の処理で顔を認識しているか確認します。
  0x0000d7e
   <calc><mem_r size="1" adr="0x0e88"/><const data="48"/><sub/><eq/><jump adr="0x00000d62"/></calc>
  0x00000d62
   <calc><mem_r size="1" adr="0x0e98"/><const data="0"/><sub/><eq/><jump adr="0x000010b5"/></calc>
 認識できた場合は次のサブルーチンで顔の位置を取得します。
  0x00003668
   <call adr="0x000264e6"/>
 0x0e9bと0x0e9dで次の計算式で認識した顔の位置の値を求めています。
  0x0e9d <= -96   の場合 0x0fa8 = (0x0e9b + 0x0e9d & 255) / 2
  0 > 0x0e9d > -96 の場合 0x0fa8 = 0x0e9b
  0x0e9d >= 0    の場合 0x0fa8 = (0x0e9b + 0x0e9d) / 2

 求めた顔の位置でロビの顔の向き(0x0f83)を更新します。
 顔の向き(0x00f3)のステータスは以下の通りです。
 右=2,やや右=1,正面=0,やや左=-1,左=-2
  0x0fa8 <= 53  の場合 0x0f83 = 0x0f83 + 1(2以下の場合)
  0x0fa8 >= 106  の場合 0x0f83 = 0x0f83 - 1(-2以上の場合)

 更新された値により次のサブルーチンで実際に顔を動かしています。

  0x0000368e
   <call adr="0x0002665a"/>


防犯モードの顔認識

 認識語「防犯モード」でロビ2は顔認識で侵入者を発見して登録されている顔か判定する機能があります。

 まず顔認識で顔を検出するとロビが「侵入者発見」と言います。
 この検出は顔の向きを更新する時の顔検出と同じ処理で行っています。
  0x000129f5
   <calc><mem_r size="1" adr="0x0e88"/><const data="48"/><sub/><eq/><jump adr="0x00012af6"/></calc>
  0x000129de
   <calc><mem_r size="1" adr="0x0e98"/><const data="0"/><sub/><eq/><jump adr="0x0001299a"/></calc>
 認識できた場合はロビの顔をそちらに向けるため顔の向きと同じサブルーチンで顔の位置を取得します。
  0x0fa8 < 27  の場合 0x0f83 = -2
  0x0fa8 < 53  の場合 0x0f83 = -1
  0x0fa8 > 133  の場合 0x0f83 = 2
  0x0fa8 > 106  の場合 0x0f83 = 1

 次に登録されている顔か判定するためアイドリング時と同じサブルーチンで登録番号を取得します。
  0x00012a16
   <call adr="0x0003811"/>


絵本認識

 認識語「絵本読んで」でロビ2は絵本を画像認識してその内容を読む機能があります。

 認識を開始すると以下命令で画像取得を待ちます。
  0x0001231a
   <calc><const data="0xffff8050"/><mem_w size="2" adr="0x0e82"/></calc>
  0x0001233b
   <calc><mem_r size="1" adr="0x0e88"/><const data="80"/><sub/><eq/><jump adr="0x000122f6"/></calc>

  0x00012365
   <calc><const data="0x00008000"/><mem_w size="2" adr="0x0e84"/></calc>
  0x0001238b
   <calc><mem_r size="1" adr="0x0e88"/><const data="82"/><sub/><eq/><jump adr="0x000123d0"/></calc>

 0x0e88が42は絵本が認識されたというステータスを表します。

  0x000123d0
   <calc><const data="128"/><mem_w size="1" adr="0x0eb8"/></calc>
 0x0eb8に128をストアして絵本番号とページ番号を取得します。
 0x0eb0は次の取得ステータスを返します。
 0: 認識成功
 1: 認識エラー、パラメーターを変えてリトライ、リトライカウントを越えるとロビが「あれ良く見えなかった」と言う
 2: SDカード読み取りエラー、ロビが「あれSDカードを確認してね」と言う
 0x0eb1は絵本番号、0x0eb2はページ番号が取得され次のサブルーチンでその内容を朗読する。
  0x000126c4
   <call adr="0x0007b7b5"/>


QRコード認識

 認識語「メール読んで」でロビ2はQRコードを画像認識してそのコードの内容でパワーアップする機能があります。

 認識を開始すると以下命令で画像取得を待ちます。
  0x001e1f8b
   <calc><const data="96"/><mem_w size="2" adr="0x0e82"/></calc>

  0x001e2022
   <calc><mem_r size="1" adr="0x0e88"/><const data="98"/><sub/><eq/><jump adr="0x000123d0"/></calc>
 0x0e88が98はQRコードが認識されたというステータスを表します。

  0x000123d0
   <calc><const data="128"/><mem_w size="1" adr="0x0eb8"/></calc>
 0x0eb8に128をストアしてQRコードを取得します。
 0x0eb0は次の取得ステータスを返します。
 0: 認識成功
 1,2: 認識エラー、ロビが「良く見えなかった」と言う
  0x0f00 = 0x0eb1 - 1
 パワーアップ番号(0x0f00)が取得され次のサブルーチンでパワーアップ取得済かチェックする。
  0x001e21f5
   <call adr="0x003edeb2"/>


笑顔判定

 認識語「ニコロビシャッター」でロビ2は顔認識で笑顔を判定してして写真撮影する機能があります。

 次の命令で撮影の準備開始します。
   <calc><<const data="0x00008040"/><mem_w size="2" adr="0x0e82"/></calc>
 撮影を開始すると以下命令でステータス取得を待ちます。
   <calc><mem_r size="1" adr="0x0e88"/><const data="64"/><sub/><eq/><jump adr="0x0000fbe2"/></calc>
 0x0e88が64は写真撮影のステータスを表します。
 64であれば続いて次の命令で写真撮影を行います。
   <calc><const data="0x00008002"/><mem_w size="2" adr="0x0e84"/></calc>
 なお通常の写真撮影の場合はストアする値は"0x00008000"となります。
 写真撮影のステータスは0x0e88の値で取得できます。
 64: 撮影失敗、撮影終了
 65: 撮影成功
 66: 撮影失敗、リトライを行う
 67: 撮影撮影失敗、再度撮影を行う
     ステータスが65の場合、次の命令で撮影結果をチェックします。
   <calc><const data="128"/><mem_w size="1" adr="0x0eb8"/></calc>
 0x0eb8に128をストアしてステータスを取得します。
 0x0eb0は次の取得ステータスを返します。
 0,4: 撮影成功、笑顔と判定
 1: 認識エラー、ロビが「ガシャ」と言う
 2: 笑顔じゃないと判定
 3: 撮影失敗、ロビが「あれ撮れないよ」と言う
 0x0eb1は絵本番号、0x0eb2はページ番号が取得され次のサブルーチンでその内容を朗読する。
  0x000126c4
   <call adr="0x0007b7b5"/>


顔登録

 ロビ2の顔認識で名前を呼んでもらうには画像認識ボードに顔(画像)を登録する必要があります。

 次の命令で登録の準備開始します。
 0x0003a897
  <calc><const data="0x8030"/><mem_w size="2" adr="0x0e82"/>
 以下命令でステータス取得を待ちます。
 0x0003a8d4
  <calc><mem_r size="1" adr="0x0e88"/><const data="48"/><sub/><eq/><jump adr="0x00000258"/></calc>
 0x0e88が48は登録準備のステータスを表します。
 登録命令で顔を登録します。登録番号(1〜10)を0x0e84にそのまま指定します。
 0x0003a90b
  <calc><const data="2"/><mem_w size="2" adr="0x0e84"/></calc>
 この場合ユーザ番号2に登録します。
 以下の命令で登録ステータス取得します。
 0x0003acc0
   <calc><const data="128"/><mem_w size="1" adr="0x0eb8"/></calc>
 0x0eb8に128をストアしてステータスを取得します。
 0x0eb0は次の取得ステータスを返します。
 0: 削除成功、「」と言う
 0x0eb1は登録した番号が返されます。

顔登録削除

 画像認識ボードに登録した顔(画像)は以下の処理で削除しています。

 次の命令で削除の準備開始します。
 0x0000419c
  <calc><const data="0x8030"/><mem_w size="2" adr="0x0e82"/>
 以下命令でステータス取得を待ちます。
 0x0003a8d4
  <calc><mem_r size="1" adr="0x0e88"/><const data="48"/><sub/><eq/><jump adr="0x000043b1"/></calc>
 0x0e88が48は登録準備のステータスを表します。
 削除命令で顔の登録を削除します。登録番号(1〜10)を0x0e86に指定します。
 0x000041da
  <calc><const data="0x8002"/><mem_w size="2" adr="0x0e86"/></calc>
 この場合ユーザ番号2を削除します。
 以下命令でステータス取得を待ちます。
 0x0003a8d4
  <ca0x0000423elc><mem_r size="1" adr="0x0e88"/><const data="48"/><sub/><eq/><jump adr="0x000041fb"/></calc>
 0x0e88が48は削除のステータスを表します。
 次の命令で削除の後処理をします。
 0x000041fb
  <const data="0x8010"/><mem_w size="2" adr="0x0e82"/>


 各機能と制御アドレスは次の通りです。

機能 0x0e82 0x0e84 0x0e86 0x0e88 0x0e98 0x0e99 0x0e9b 0x0e9d 0x0eb0 0x0eb1 0x0eb2 0x0eb8
顔検出(アイドリング) - - - 48 検出人数 登録番号* - - - - - -
顔追従(アイドリング) - - - 48 検出人数 - 顔位置 顔位置 - - - -
防犯モード - - - 48 検出人数 登録番号* 顔位置 顔位置 - - - -
絵本認識(前段階) 0x8050* - - 80 - - - - - - - -
絵本認識(頁認識) - 0x8000* - 82 - - - - 0:成功 絵本番号 頁番号 128*
QRコード認識 96* - - 98 - - - - 0:成功 コード番号 - 128*
写真撮影(前段階) 0x8040* - - 64 - - - - - - - -
写真撮影(撮影) - 0x8000* - 65 - - - - 0,4:成功 - - 128*
写真撮影(笑顔撮影) - 0x8002* - 65 - - - - 0,4:笑顔 - - 128*
顔登録 0x8030* 登録番号* - 48/50 - - - - 0:成功 登録番号 - 128*
顔登録削除 0x8030*
0x8010*
- 登録番号*
| 0x8000
48 - - - - - - - -
                   * 書込み、登録番号:複数検出時は0x0ea1または0x0ea9から取得

 これらの機能を使ってロビ2のテストプグラムを作ってみました。
 一応参考のためプログラムを記載しておきます。(実際に動かすには音声ファイルとサブプログラムが必要です)
 
人数当てプログラム
 笑顔判定プログラム
 顔登録プログラム 登録番号2番に登録
 顔登録削除プログラム 登録番号2番を削除
 実際にテストプグラムを動かした動画です。

       


目次に戻る