2021年3月30日火曜日

MIT App Inventorで顔認識学習モデルFacemeshを

 【what is this】MIT App Inventor のExtensionとして、Googleの顔認識(主要450点)学習モデルFacemeshが利用できるようになりました[1][2]。これにより、顔認識関係のスマホアプリがさらに作りやすくなりました。さっそく、簡単なアプリ3つを作ってみましょう。

[Exercise-1] 顔の向きを考慮して、口の開閉でスイッチOn/Off
 これは、前のブログ記事で取り上げた例題です。その際は、PythonからFacemeshに関するAPIを利用して作りました。今回は、これと同じことを、MIT App Inventor のExtensionを利用して行います。

 解答例は、Fig.1 のようなApp Inventorプログラムです。これがソースプログラムの全てですから、「こんなに簡単に!?」と思う人も多いでしょう。プログラムは読みやすく、そのロジックも明解そのものです。
 図にはコメントがありますので、説明は特に必要ないと思います。口の開閉を上下の唇中央点のy座標の差分で、顔の向きを鼻筋2点のx座標の差分で検出していることにご注目下さい。それらが、ブロック(when...FaceUpdated)に纏められ、顔や口が動いた場合にリアルタイムに起動される仕組みです。


 簡単な拡張として、以下のように、マスクを付けたり外したりもやってみましょう。

[
Exercise-2] - 顔の動きで、"はい", "いいえ", "どっちかな"を識別
 上の[Ecercise-1]では、顔の現時点の特定の「状態」を検出しました。一方、顔の「連続した動き」を得たい場合もあります。例えば、「うなずく」「顔を横に振る」「顔を傾ける」などです。これらを検出するには、顔の揺れた方向(上下、左右、斜め)、および、その振幅を得る必要があるでしょう。このような処理も、同様にApp Inventor(Facemesh extension付き)の世界でできます。その実現例を下図に示します。以下の3つの振幅を正規化して、そのうち、最も大きい値を与えた動作を検出します。

Yes:うなずき(はい)→ 鼻の頂点の上下(y軸方向)の変動
No:いやいや(いいえ)→ 鼻の頂点の左右(x軸方向)の変動
●N/A:どうかな(?)→ 額の上の2点間の線分とx軸がなす角度の変動




[Exercise-3] - 発話時の口形面積の変化を可視化して楽しむ
 MIT App Inventorの強みのひとつは、GUIとの連携の容易さです。Fig.4 に示すこの練習問題も、それを生かしたアプリの作成です。Facemeshでは、顔の主要450点を検出できるのですが、ここでは、口(くち)回りの4点だけ使います。The simpler the better. この菱形の口の面積の推移(青い線)とその変化率(赤い線)をグラフにします。口の動きとその波形を見て楽しむ練習問題です。遊びが何らかのヒントを与えることもあり得る。

 このような口(くち)パクから、例えば、"イノシシ" / "トラ"、あるいは"apple" / "orange"をきちんと区別する課題に取り組む場合には、さらに面積変化の加速度の波形が必要かもしれない。そのような波形(またはその周波数解析結果)を、発話種類ごとに数百件用意して、それらを学習させることになるでしょう。
 なお、身体の動きの加速度の周波数解析に関しては、参考文献[3]に丁寧な解説があり有用です。また、口の動きを入力とする機械読唇に関しては、参考文献[4]に基本事項と手法が詳しく叙述されています。

感想
 今回のMIT App Inventor Extension for Facemeshによって、顔認識関係スマホアプリの開発がかなり容易になります。[Exercise-2]では、App InventorのBallコンポーネントを使っており、タッチ、ドラッグなどによるインタラクションも可能です。他にも、Facemeshと連携できる場面がありそうです。MIT App inventor leads us to a new frontier in smartphone programming.

References
[1] Artificial Intelligence with MIT App Inventor, http://appinventor.mit.edu/explore/ai-with-mit-app-inventor
[2] Facemesh Filter Camera, http://appinventor.mit.edu/explore/resources/ai/facemesh

[3] 田中博、五百蔵重典:IoT時代のデータ処理の基本と実践、コロナ社刊、2018年3月(特に、第5章フーリエ解析)
[4] 宮崎 剛、中島豊四郎:[推薦論文]日本語の発話映像における初口形の検出方法提案、情報処理学会論文誌、Vol.53、No.3、pp.1472-1479、2012.

Using the MIT App Inventor FaceExtension (for Facemesh)

 【abstract】The MIT App Inventor FaceExtension has been released [1][2]. This makes it very easy to create a smartphone app that uses Google's facial recognition (450 major points) learning model Facemesh. Let's make three simple apps right away.

[Exercise-1] On/Off by opening and closing the mouth considering face orientation
 You can see what I want to make by watching the animated gif below. Let's make this little app using the FaceExtension of MIT App Inventor.

 My answer is shown in Figure 1. Here's a complete App Inventor source program that works. I think this program is simple and very easy to understand. Notice that the opening and closing of the mouth is detected by the difference in the y-coordinate between upper and lower lips, and the orientation of the face is detected by the difference in the x-coordinates between the two points on the nose. They are grouped into a block (named whenFaceExtension.FaceUpdated) and it is activated in real time when the face or mouth moves.


    As a simple extension, try putting on and taking off the mask as follows.

[Exercise-2] - Identify "Yes","No", and "N/A" by face movement
  In the [Exercise-1] above, we have detected the current specific "state" of the face. On the other hand, you may want to get a "continuous movement" of your face. For example, "nod", "shake your face", and "tilt your face". To detect these, you will need to know the direction in which the face sways (up/down, left/right, diagonal) and its amplitude. You can do this in the App Inventor (with Facemesh extension) world as well. The following GIF shows an example of the answer. Three amplitudes in the figure are normalized, then, the movement that gives the maximum value is adopted.

Yes:Nod -> Fluctuation of the top of the nose up and down (y-axis direction)
No:Shake -> Fluctuation of the top of the nose right and left (x-axis direction)
N/A:Tilt -> Angle variation of the line segment between the two points on the forehead against x-axis



[Exercise-3] - Visualize the transition of the mouth-shaped area during utterance
 One of the great features of MIT App Inventor is the ease of integration with the GUI. Fig.4 is an app that makes the best use of it. Facemesh can detect the main 450 points on the face, but here we will use only 4 points around the mouth. The simpler the better. Graph the transition of the area of this diamond-shaped mouth (blue line) and the rate of change of the area (red line). This is an exercise that you can enjoy watching the movement of the mouth and its waveform. Play may give some hints.

 In order to properly distinguish, for example, "apple" from "orange" using such mouth movements, acceleration waveforms of mouth area change may also be needed. Hundreds of such waveforms (or their frequency analysis results) should be prepared for each utterance type. And thorough training (learning) using them will be necessary.

References
[1] Facemesh Filter Camera
http://appinventor.mit.edu/explore/resources/ai/facemesh
[2] Artificial Intelligence with MIT App Inventor,
http://appinventor.mit.edu/explore/ai-with-mit-app-inventor

2021年3月19日金曜日

顔認識(主要486点)学習モデルFacemeshの利用

 【what is this】Googleの顔認識(主要486点)や指の認識(主要関節21点)の学習モデルが、PythonやJavaScriptなどで使えるようになっています[1]。本記事は、これに基づいた顔認識モデルFacemeshに関する小生独自の簡単な説明です。

顔のキーポイント(全486点)のリアルタイム認識
 Facemeshによる顔のキーポイントの検出例を図1に示します。人間の実写の他、写真や肖像画でもOKのようです。福沢諭吉と平賀源内の肖像画(何故かこのお二人)、および大学HPの広報(女子学生)写真で試しました。顔認識や感情分析に重要な、口や鼻や目の付近のメッシュは当然ながら細かくなっています。

唇と瞼の開き具合の認識
 主要点番号とその位置の対応は、mesh mapにありますので、その番号を指定して、必要な点の検出ができます。一例として、唇と瞼の開き具合を見るため、図2のように、8点(唇4点と瞼4点)を赤色に着色してみました。


 これら8点のマップは図3のとおりです。鼻や頬や顎についてのキーポイントも同様に得られます。(キーポイント番号は、その後改訂にともない、図3とは異なるかも知れません。)これらを利用すれば、例えば口の開き具合で、何かの動作を制御する等、自分なりの顔認識関係アプリを(簡単なものであれば)作れそうな気になります!

 図4は、日本語母音の発話時の口形の検出例です。なかなか面白そうですが、これですぐに読唇ができるわけではありません。実際の機械読唇技術に関しては、宮崎剛教授らの論文[2]等を参考にして深く検討する必要があるでしょう。


口の開閉でオンオフを制御してみる
 →この項はその後修正し、こちらにまとめました。


もう一歩前へ(状態だけでなく、動きも検知)
 
→この項はその後修正し、こちらにまとめました。

感想
(1)プログラミングの容易化
 
図3を改めて眺めてみました。このようにランドマーク(キーポイント)がリアルタイムに検出されるのであれば、この後は顔の表情を認識することは格段に容易になります。(情報系が苦手な学生を含む)より幅広い人々が、AI技術発展の恩恵を受けられると思います。
(2)スマホなどGPU無しでも推論ができる
 
以前は、上記例題のようなリアルタイム顔認識には、GPU付きの高性能PCが必要でしたが、今はこのような認識(推論)は普通のスマホで十分できてしまう。アイディアと工夫次第で、思いもつかぬアプリケーションも生まれそうに思われます。

参考文献・資料
[1]
 Face and hand tracking in the browser with MediaPipe and TensorFlow.js, https://blog.tensorflow.org/2020/03/face-and-hand-tracking-in-browser-with-mediapipe-and-tensorflowjs.html
[2] 宮崎 剛、中島豊四郎:[推薦論文]日本語の発話映像における初口形の検出方法提案、情報処理学会論文誌、Vol.53、No.3、pp.1472-1479、2012.

2021年3月14日日曜日

5本の指で0〜31を数えるジェスチャの認識:handpose利用

 【what is this】手の指のランドマーク(キーポイント)21点をリアルタイムに検出する学習モデルhandpose (MediaPipe Hands)[1]があります。そのAPIを利用して、5本の指で0〜31までを数えるジェスチャを認識するデモアプリを作成しました。

5本の指で0〜31を数える
 2進法を使えば、5本の指で、0〜31を数えることができます。具体的には、図1のように、親指、人差指、中指、薬指、小指を折り曲げることで、各々1、2、4、8、16を与えます。通常、深層学習でこのようなパタンを認識させる場合は、この32種のそれぞれに500枚程度の画像を用意して学習させます。しかし、ここでは、そのような学習をせずに、handpose (MediaPipe Hands)から得られるランドマークを利用して簡単に認識させたい。



handpose (MediaPipe Hands)の利用
 handposeでは、図2のとおり、5本の指の関節合計21点をリアルタイムに検出します。それを、PythonやJavaScriptからAPIで使えるようになっています。ここでは、上記の目的に沿って、21点のうち、15点を利用します。すなわち、図1にあるとおり、各指の先端、第1関節、第2関節の検出結果のみを使います。



handpose (MediaPipe Hands)を利用した指の折れ曲りの検出で数値を決定
 各指の折れ曲がりの判定は、図1の説明にあるとおり、指の先端と第2関節の座標の差分を使って行います。ただし、親指の場合は、x座標を、その他の指はy座標に着目します。例えば、薬指の場合は、先端のy座標が第2関節のy座標よりも大きければ折れていることになります。図1の左図では、薬指と親指が折れていますので、9(=8+1)を意味します。
 この方法で指の形状を認識して、リアルタイムに2進法の数値を10進整数で表示します。実行結果のいくつかを図3に示します。なお、下部のGIF画像は、PCでの実行画面の録画から作成したものです。(折り曲げた指は"*"、伸ばした指は"_"で示しています。0〜31までを連続して示しています。)



感想
 正面から撮影するという条件下では、このようなジェスチャ32種を、ほぼ100%認識することができました。「学習」を行わずに、短めのPythonプログラムによって比較的簡単に実現できたことに驚きます。ただし、ランドマークがリアルタイムに得られるというのは、すでにそのための深層学習が十分に実行されているからです。
 状況によっては、指の折れ状態をもっと厳格に(他の関節点も利用するなど)する必要があるかも知れません。この例以外にも、何か応用ができそうです。

参考文献
[1] MediaPipe Hands, https://google.github.io/mediapipe/solutions/hands

2021年3月10日水曜日

祝:MIT App InventorがiOSでも利用可能となった!

素晴らしい朗報が入りました!
 2016年10月にスタートしたこのこのプロジェクトですが、幾多の困難を乗り越え、約4年半の年月を費やし、ついに、MIT App InventoriOSでも利用できるようになりました(図1)!特筆すべきは、これまでAndroid向けに開発されたソースプログラムは、全くそのままiOS用にも使えるという点です。

 「そんなに大変なの?」と思う人もいるでしょうが、AndoridとiOSという全く異なるアーキテクチャとOSを考えれば、この実現の偉大さは分かると思います。さらに、Appleの強い閉鎖性と極めて厳格な資源管理を考えれば、Apple側との交渉に膨大な時間がかかったことも想像に難くありません。
 マンパワーも膨大であり、約66,000行の新たなプログラム開発になったとのことです。当時、開発費を工面するためクラウドファウンデイングが行われており、小生も、同僚だったH.Tan先生とY.Sud先生と共に幾らかの寄付を行いました。それも懐かしいです。

 現時点では、図2のとおり、iOS用にはインタプリタ方式(Companionで接続)のリリースとなっており、コンパイル方式は2021年秋ころとなっています。また、出来たてなのでもちろん不具合もあるでしょう。それは問題ではありません。とにかく、素晴らしいスタートが切られたことをお祝いしたい!


 この記念すべき出来事を祝って、過去に大学のオープンキャンパスの高校生向け講座のためにつくられたApp InventorソースプログラムをiOSで実行させてみました。図3のとおり、完璧に動きました!この図からも分かりますが、スライダーやボタン等は、Androidとは若干異なる、iOS独特の美しいデザインが感じられます。

 なお、このApp Inventorの例題は、須藤康裕准教授が、ソーラーカーを鈴鹿サーキットで実際に走行させた時にリアルタイムに発進した位置情報を、後でトレースするものになっています。毎秒の位置情報の発信アプリも、須藤先生がAndroid用にApp Inventorで作成されたものです。


2021年2月24日水曜日

中学数学で折り紙ピラミッド

 YouTubeに「ドル札で折るピラミッド(Dollar Origami Pyramid)」なる動画(下部参照)がありました。良さそうに思い、やってみました。1ドル紙幣以外にも、数種類の長方形の紙で折ってみましたが、なかなかおしゃれな作品となります。古代エジプトピラミッドに比べると、先端がより鋭く尖っているようです。

 
 横長の紙を使うのですが、この折り方では、ピラミッドの大きさは縦方向の長さで決まります。横の長さには依存しませんが、横の長さが短すぎると底辺部が不安定になり、長すぎると底辺部を折り込む際に邪魔になります。動画にあるとおり、ドル札の縦横比がちょうどいいようです。

 このピラミッドは、2等辺のなす角度がいつも45度の三角形で構成されます。すなわち、どんな長方形の紙でも、その三角形は相似になります。中学数学(もしかすると小学校算数)の世界のようです。簡単だけど美しい。机上において眺めると、ちょっと心が落ち着くような気がします。


参考資料:Dollar Origami Pyramid
https://www.youtube.com/watch?v=dfnuhYNQEn0

2021年2月22日月曜日

私は誰でしょう

今回はクイズです。

 ある入力データに対する出力結果が図1に示してあります。入力データは、「千山万水」の四字熟語から、ランダムに漢字を選んで次々と並べた、長さ12の文字列です。このような入力データは、約1,700万個(4の12乗個)作れますが、図1にはその一部を示しています。それに対する「ある処理」を行った結果の出力データが右側に示されています。

 私は、このようなどの入力データに対しても、(恐らく)100%正しく出力結果を示すことができます。私は、図2のようなヒント(赤字の情報)は一切もらっていません。入力と出力の組みを5万個見て、「その処理」をひたすら学習しただけです。その結果、その処理内容を把握できたことを確信しました!

 さて、私は誰でしょうか。人間ではありませんが。
答えは、こちらの記事にあります。
(入力データのボキャビュラリが、「A,T,G,C」から「千,山,万,水」に変わっただけなのですが、Attention付きSeq2seqの感動が尾を引いていましたので、こんなクイズ記事になっています。)

2021年2月12日金曜日

新型M1 Mac miniに期待

【what is this】これまでのIntelプロセッサに替わり、Apple独自のM1(arm64)プロセッサ搭載のMacが発売になっています。Appleシリコン搭載とも呼ばれています。何といっても、「8コアCPU+ 8コアGPU+16コアNeural Engine」と言われると、長年のMacファンとして買わざるを得ませんでした。基本的なソフトウェアのネイティブ本格対応はこれからのようですが、現時点でも、手元の例題で、Intel版に対して、Javaアプリで3.2倍、Pythonアプリで2.5倍高速となりました。今後の、M1向けTensorflow(アルファ版はすでに公開)などが楽しみです。

雑然とした「研究室」に置かれた新型M1 Mac mini
(別のMacからリモートで利用のためモニターに接続されていません)

Javaアプリで試す
 小生の使う開発言語は、Java、Python、NetLogo、MIT App Inventorなどです。まず、Javaのアプリで確認します。Androidアプリで扱ったHamilton閉路問題のうち、サイズを少し大きくした、Groetzschグラフ(11ノード)を例題とします。最も原始的な解法なのですが、10ノード(出発は第0番ノードに固定するので)の順列(約360万個)を全て調べるものです。もちろん、可能な限り早期に適合しないパスは棄却します。図1に示すような、Hamilton閉路20個を全て答えます。



 このJavaプログラムの主要部(というよりも全体制御部)は、図2のとおりです。並列ストリームを使っています。実行の結果、M1 MacはIntel Macよりも、約3.2倍高速でした。素晴らしい!PC買い換えで3倍超の性能アップは、なかなかないです。



Pythonアプリで試す
 次にPythonアプリです。例題としては、すでに報告しました、ショットガン法によるDNAの復元問題(トイプログラム)です。Deep Learningでのprediction部分です。ここでは、上記Javaのようなparallel機能は特に意識せず、GPUの使用もありません。ですが、CPUのコア数の違いが、図3のとおり、実行性能に現れています。この例でも、M1 MacはIntel Macよりも2.5倍高速でした。


 このグラフ、緑はユーザプロセス、赤はシステムプロセスのはずです。M1 Macでは、8コアの利用率が、計算時に100%近くに達しています。それは良いのですが、システムの割合が大きいことがちょと気になります。Interl MacはPython3.8で、M1 Macは(最適化された)Python3.9です。もしかすると、ユーザプログラムの実行時にPython3.9のある部分がシステムプロセス扱いになっているのかも知れない。

今後の期待:M1用に最適化されたTensorflow等
 以上、現時点で試せるJavaとPythonの例題をM1 Mac miniで実行してみました。従来よりも2.5倍〜3.2倍の高速化となったことは素晴らしいと思います。現時点ですでに、GPUやNeural Engineを駆使するであろうTensorflowのアルファ版は公開されています。今後、それも利用していけば、Deep Learningを手元のマシンで実現できる場面が広がりそうです。



2021年2月6日土曜日

春の息吹

 立春を過ぎたとはいえ、まだ2月6日です。寒い日が続くなか、時には少し暖かな日もあります。散歩で、早くも春の息吹を見つけました。以下の写真はいずれも、厚木市郊外で2021--02-6に撮影しました。

梅のつぼみ、すでに開花したものも

やなぎの木も芽吹いてきた


2021年2月5日金曜日

Enjoy finding out Hamiltonian Cycles

This app has won the "2021 March's MIT APP INVENTOR OF THE MONTH" award. 

 Abstract 

This app solves the Hamiltonian cycle problem for a given graph. The problem is to find out paths in a directed graph of n vertices, starting from one starting point, visiting all vertices only once, and returning to the starting point. This is known as an NP-complete problem and no efficient solution is known in general. From the perspective of programming education, I provide a solution for small graphs with six or fewer vertices, along with an easy-to-use user interface. 

Basically, it searches all possible paths, but the method is not so trivial and you need to think carefully about the procedure. The use of multiple lists and recursive functions in implementing the algorithm is useful for improving programming capabilities. You should also consider the graphical user interface for setting up and displaying graphs. The sense of accomplishment gained by completing this app enhances the educational effect. It's also fun to run the finished app and see the results on the graph. 

This time, I used MIT App Inventor to create this app. The use of App Inventor's familiar feature blocks (especially Lists, AnyComponent, Canvas, Checkboxes, etc.) was very useful for efficient program development. 

●This app is published on the Google Play Store:
https://play.google.com/store/apps/details?id=appinventor.ai_Fujio_YAMAMOTO.HamiltonianCycles1

●The source code of this app is published below :
https://gallery.appinventor.mit.edu/?galleryid=3048beec-25b8-46ba-a746-25c0dc3702b6

Directed graphs and the Hamiltonian cycle

Figure 1 shows an example of a directed graph and the Hamiltonian cycle. A single matrix can be used to represent the connections between nodes. In this matrix, the "From" node is in the row and the "To" node is in the column. In the example, there are two Hamiltonian cycles. This app provides both a way to give a directed graph with such a matrix and a way to automatically generate a random graph. 


How to use the app for the Hamiltonian cycle problem

Fig.2 shows the GUI of the app developed this time. The number of nodes can be specified in the range of 2 to 6. If you want to specify a directed graph in the matrix on the left, check the check box "prefer Matrix". After that, when you press the button "genGraph", a graph with an arrow will be drawn on the canvas at the top. Next, if you press the button "solve", the Hamiltonian cycle will be searched, and as a result, the number of cycles and the path of each cycle will be displayed. On the other hand, if you want to generate a graph randomly instead of specifying the graph yourself, uncheck the check box "prefer Matrix". Even then, the matrix corresponding to the generated graph is automatically displayed. It would be fun to discover such a cycle for different graphs.


Acknowledgments

In this app, I referred to the following documents when generating permutations:
Asao Kasai, "Introduction to algorithms in Java”, chapter 4, Gijyutsu-Hyouron-sha, July 2001.(in Japanese)