見出し画像

電子工作素人によるスタックチャン製作記5(顔カスタマイズ編)

まいど、これまでの記事(というか作業記録)と、今後の予定です。

以下、予定

  • シン・スタックチャン編:AI ChatGPT対応

この記事では

いったんスタックチャンの基本形(M5Stack+ボディ)までたどり着けたので、今回はスタックチャン・顔カスタマイズ編ということで、スタックチャンの標準の顔 [・_・] を表示しているライブラリをカスタマイズしてオリジナルの顔を作ってみようと思います。

今日の資材

今回の作業は、あくまでM5Stackの画面に表示される顔の部分のカスタマイズに特化しているので、サーボモーターなどの連動部分は含めていません。そのためこの記事では、サーボを動かすために入れたStackchan-tester-core2ではなく、いったん初期化した状態に戻したM5Stackを使って作業を進めます。

今後、ChatGPT対応やBluetooth対応のスタックチャンに今回の記事の内容を反映させてみたいなと考えています。(一気にやると問題の切り分けが大変なので、今回はまず顔からということで)

スタックチャンの顔の描画方法

ちなみに、スタックチャンの顔の描画方法ですが、2023年5月時点では大きく次の2つの方法があるようです。

  1. 丸や四角のオブジェクトを使って、顔を描く方法

  2. 顔や目などのパーツ毎の画像を使って、顔を描く方法

方法2の画像はこちらからお借りしました。
https://github.com/mongonta0716/M5Stack-Image-Avatar/

本記事では、両方法の簡単な概要と、スタックチャンの標準の顔 [・_・] を描画する際に使用されている 1. の方法については、描画の仕組みやカスタマイズ例を使ってその特徴やカスタム時のポイントを解説します。

1. 丸や四角のオブジェクトを使って、顔を描く方法の概要

M5Stack-avaterというプロジェクトとして、顔の描画部分のプログラムが公開されています。
スタックチャン動作テスト用のファームウェアStackchan-tester-core2や、M5Burner版AIスタックチャンの標準の顔にも組み込まれています。

  • GitHubリポジトリ

  • スタックチャンの発案&作成&公開をされている @meganetaaan さんの作成物です。

  • M5Canvasという画面にオブジェクト(丸や四角の形状)を描画する機能を利用して顔を表示させています。

  • スタックチャンの一番有名な顔もこの仕組みで描画されています。

    • というか、顔ができたので体もつけてオープンソースで発展させようプロジェクトがスタックチャンです。

詳細はリポジトリのReadmeもご覧ください。

2. 顔や目などのパーツ毎の画像を使って、顔を描く方法の概要

M5Stack-Images-avaterというプロジェクトとして、画像を使った顔の描画プログラムが公開されています。本記事ではこちらの方法は解説しません(まだ触ってないのでどういう仕組みかとか、わからない・・・すいません)
ご興味のある方はリポジトリをご覧ください。こっちも調べたら記事にしたいと思います。

  • GitHubリポジトリ

  • M5Stack-avaterとは別のグラフィック描画の仕組みであるLovyanGFXライブラリを利用して顔を表示させています。

  • ソフトウェアとしての動作や構造は、M5Stack-avaterを参考にされているようです。

  • 最近はこっちの方法でカスタムした顔を作る人が増えてきている印象があります。

詳細はリポジトリのReadmeもご覧ください。

M5Stack-avaterを使った顔のカスタマイズ手法

というわけで、そろそろ本題に入ります。

M5Stack-avaterの導入手順

公開されているM5Stack-avaterをそのまま使う場合は、公式のREADMEに書かれている方法で良いのですが、今回は自前でカスタマイズした物を使いたいので少し手順を加えます。

※ ここからはソースコードを直接いじっていくので、GitHubを利用する(最低限の使い方は分かっている)前提となります。
※ また、M5Stackへのソースコードの反映は、Arduino IDEを使用します。Arduino IDEのインストールについては、電子工作素人によるスタックチャン製作記2(Hello World編)をご覧ください。

本節ではカスタマイズする前のデフォルトの状態のM5Stack-avaterをM5Stackに書き込む手順を記載します。
個別にカスタマイズした顔も、同様の手順でM5Stackに導入します。

★★★大事★★★
この回の次に実施した Platform IO 環境構築編 の手順のほうが、ビルド時間とかがかなり短縮できるので、お勧めしますー。

カスタマイズ元となるソースコードの準備

M5Stack-avaterのリポジトリは、これ自体がM5Stackに書き込み可能なライブラリとして作成されています。そのため、このリポジトリをまるまるZIPにしたものをM5Stackに書き込むことができます。

書き込むためには、このリポジトリをZIP形式に固めたものが必要となります。ZIPの作り方を場合に分けて記載します。

  • M5Stack-avaterをそのまま書き込む場合

    • ブラウザでM5Stack-avaterのリポジトリにアクセスして、画面右にある緑色のCodeボタンを開き、Download ZIPを実行します。

  • M5Stack-avaterを自前でカスタマイズしたものを書き込む場合(次の2種類のどちらか)

    • M5Stack-avaterのDLを解凍したソースコードをカスタマイズしてから、再度ZIPに圧縮する。

    • または、M5Stack-avaterをフォークしたリポジトリを作成し、ローカルにCloneした後にカスタマイズを実施してからZIPに圧縮する。

本記事では、カスタマイズしたコードも公開する方針なので、M5Stack-avaterをフォークしたリポジトリを作成しました。

  • Zipの準備ができたら、Arduino IDEを起動し、スケッチ > ライブラリをインクルード > .ZIP形式のライブラリをインストール… を選択し、先ほど作成したZIPファイルを指定します。

  • 正しくインクルードが完了したら、Arduino IDEのコンソールに「Library installed」の文字が表示されます。

  • M5Stack-avater/examples フォルダ以下にいくつかのアバター表示用のスケッチ例があり、それらは、Arduino IDEで次の手順で読み込むことができます。

    • ファイル > スケッチ例 > M5Stack_Avatar > [スケッチ例の名前]

    • スタックチャンの標準の顔 [・_・] を表示させるスケッチ(プログラム一式)を読み込ませる場合は、 basic を選びます。

  • basicが読み込まれた状態のArduino IDEがもう一枚起動します。

  • 2023年5月時点のM5Stack-avaterは、Hello World編でインストールしたM5Core2ではなく、M5Unifiedというライブラリに依存しているため、ツール > ライブラリを管理 から ライブラリマネージャーのパネルを開き、検索窓を使ってM5Unifiedを探してインストールしておきます。M5UnifiedをインストールせずにM5Stack-avaterをM5Stackに書き込もうとすると、コンパイル時に2枚目の様なエラーが表示されます。

  • 書き込みが成功すると、スタックチャンの顔 [・_・] が表示されます。やったね。

  • 読み込むスケッチ例を face-and-color にすると、ABCボタンを使って、Dog Faceへの切り替え、色合いの変更、表情の変更(♥とか)ができたりします。

起動直後はちょっと反応が悪い気がするので、ちょっと待ってからがよさそうです。
あと、気持ち上側を触る感じだと反応しやすいかも?

以上を簡単に書くと、プログラム描いて、ZIPを作って、ZIPを読み込んで、スケッチを指定して、書き込むという流れになります。

補足1:顔カスタマイズ作成時にはまった点

ソースコードを編集してZIPに固めて読み込んで、を繰り返していた際に、過去に編集したコードが混ざっているような挙動になったことがありました。原因は、ZIPに圧縮する際に前に作成されたものに上書きでZIP化してたのですが、その際にZIPファイルを置き換えるのではなく、過去のファイルにマージされる形で圧縮されていたのが原因でした。自分がzip圧縮につかった7zipの問題なのか、zipの仕様七日までは調べてませんが、ZIPファイルは毎回別名にするか、一度削除してから作り直す、などのケアが必要な場合があるようです。

M5Stack-avaterのファイル構造

カスタマイズの手順に進む前に、そもそものM5Stack-avater自体の理解もしておいた方がいいので、簡単に記述します。このプログラムは、プログラム言語のC++で書かれており、大まかに下の様な用途別のフォルダに分けられています。

/src直下のファイルがライブラリの本体部分になるので、簡単な顔のカスタマイズの場合はこの直下のファイルはいじる必要はありません。

基本的に赤文字で書いた場所に、カスタマイズ用の顔定義のプログラム(拡張子.h)と、Arduino IDEでスケッチを書き込むためのプログラム(拡張子.ino)を作成して格納します。

  • m5stack-avatar-ut-customでは、自分がカスタム用に作成したコードがどれかわかりやすくするために、/src/faces-custom というフォルダを新規に作りました。

また、本記事では、読み解くために必要な最低限の補足や顔カスタマイズのための要点の説明は行いますが、全てのコードの逐次解説までは行いません。ご了承ください。

顔用プログラムの基本構造

/srcフォルダの直下に、顔用のパーツとして、目、眉毛、口用のクラスが用意されており、初期値としてスタックチャンの顔 [・_・] 用のパラメータが設定されています。また、それらの顔のパーツ用のクラスをまとめた顔用のクラス(Face.h, Face.cpp)があり、M5Stackの画面にはこのクラスの単位で顔が表示されます。

簡単に分類にまとめると次のようになります。

ちなみにスタックチャンの顔 [・_・] は、下記のファイルの指定行所に定義されています。(可読性のため、少し改行位置を変えています)

/src/Face.cpp   L12-17

Face::Face()
    : Face(new Mouth(50, 90, 4, 60),  new BoundingRect(148, 163),
           new Eye(8, false),         new BoundingRect(93, 90),
           new Eye(8, true),          new BoundingRect(96, 230),
           new Eyeblow(32, 0, false), new BoundingRect(67, 96),
           new Eyeblow(32, 0, true),  new BoundingRect(72, 230)) {}

Faceクラスの引数として、パーツ(サイズなど) → 配置場所(左肩座標) という組で、口, 左目, 右目, 左眉, 右眉の順番に顔パーツ定義が並んでいます。

スタックチャンの標準の顔 [・_・] の特徴としては、眉の定義は幅や位置が設定されていますが、高さが 0 になっているため、実際には表示されない、という風になっています。この0を1以上に変えて書き込むと、眉毛ありの顔になります。

顔カスタマイズではこの顔クラスの定義と顔パーツの定義を作成します。

顔パーツの描画の仕組み

M5Stack-avaterでは、目や口といった顔パーツは、丸や四角のオブジェクトに色を付けたものの組み合わせや重ね合わせで表現されています。

レイヤー構造に分けた簡単な図解と、正面から見た状態(=描画される形状)を次に示します。ここでは、口の形状は重ね合わせの際に、背景色と同色の四角を楕円の上半分に重ねて表現しています。

(説明用にエイやで描いたのでまったくかわいくない)

顔のパーツの書かれる順番は、Faceクラスの引数と同じく 口, 左目, 右目, 左眉, 右眉 の順になっているようです。そのため、例えば顔の輪郭の様な一番ベースになる部分を描きたい場合は、口を描画する際に輪郭部分の描画記述を行う、などの工夫が必要となるようです。

この例は、カスタム例2で実演しています。

顔カスタマイズ用プログラム作成の要点

次に、顔カスタマイズ用プログラム作成の要点について、ひとまず文字で説明します。具体的なコードは、後述するカスタマイズ例の説明や、公開しているサンプルをご覧ください。

M5Stack-avaterには、face-and-colorというスケッチ例で動作させることができるDogFace.h というサンプルが入っています。このサンプルが一番独自カスタマイズの参考になるので、まずこのプログラムを見てみるのが良いと思います。(それ以外にもいくつか入っていますが、一番顔カスタマイズの参考にしやすいのがDogFaceなので、本記事ではこれだけを紹介します)

C++言語に慣れている方は、カスタムした顔をヘッダーファイルと実装クラスのファイルに分けるなどもできるかと思いますが、本記事ではDogFace.hと同様にヘッダーファイルだけで顔レイアウトの実装も書いてしまいます。

m5stack-avatar-ut-customでは、独自の顔の定義は、/src/faces-custom フォルダ の中に作成しています。

また、先に説明した通り、/examplesフォルダの下にArdino IDEで書き込むスケッチ単位で .inoファイルが配備されています。ここでの注意点として、Ardino IDEの仕様から、inoファイル名とinoファイルを格納するフォルダの名前は同じにしておく必要があります。

ちなみに、自分が作ったカスタム顔を書き込むためのinoファイルは、face-and-color.inoを元に作成するのが良いと思います。このファイルのDogFace.hを読み込んでいる箇所を、自分が作成したカスタムFaceクラスに書き換えれば動作するはずです。

また、このface-and-color.inoを元にすることで、ボタンAで作成したカスタム顔の表示、ボタンBで顔の色合い変更、ボタンCで感情の変更による見た目の確認ができます。

カスタム例1:AA顔(ショボーン/シャキーン)

実際にカスタマイズして作成した例として、スタックチャンのデフォルトの顔 [・_・] をベースにして、AA(アスキーアート)でよく見る(よく見ていた?)ショボーン (´・ω・`) やシャキーン(`・ω・´)の顔を作成してみました。

このカスタムフェイス用に実装したコードは下記の2つになります。

  • スケッチファイル

    • /example/aa-face/aa-face.ino

  • カスタムフェイス定義

    • /src/faces-custom/AAFace.h

このカスタマイズでは、目、眉毛、口の顔パーツを新規に定義しています。
コードの詳細については、リポジトリの上記ファイルをご覧ください。
ここではカスタムフェイス定義での作成概要を記載します。

  • AAFace.h : AAEye

    • 目のクラス

    • 標準顔に適用される /src/Eye.cpp の内容をベースにしています。

    • 標準では、感情表現がAngryおよびSadの場合に目が半月状に加工されますが、今回のカスタマイズではその加工をしないように修正しています。

  • AAFace.h : AAEyeblow

    • 眉毛のクラス

    • 標準顔に適用される /src/Eyeblow.cpp の内容をベースにしています。

    • 標準では、感情表現がAngryおよびSadの場合に眉毛が傾くように定義されていますが、今回のカスタマイズではNeutralの場合にシャキーン(`・ω・´)、Sadの場合にショボーン (´・ω・`)の形状になるように定義しています。

    • また、それ以外の感情では眉毛は表示しないように修正しています。

  • AAFace.h : AAMouth

    • 口のクラス

    • 顔カスタムのサンプルである /src/faces/DogFace.h の内容をベースにしています。

    • AAの口である ω の形状になるように、円や四角を重ね合わせて描画するように記述しています。

実際に作ってみた感想として、特にAAMouthクラスで要素の重ね合わせによる表現の練習ができたのが良かったと思います。

また、M5Stackの画面は 320 * 240 の液晶画面なので、画面のどの辺りにどの形状の要素を配置し、重ね合わせればいいのかを考えるために下記の様なExcelファイルを使って配置の検討を行いました。
乱雑なものですが、参考までに /src/faces-custom/ フォルダに格納してあります。

カスタム例2:ラピュタのロボット

もう一つのカスタマイズ例として、天空の城ラピュタに出てくるロボット兵の顔を作ってみました。

このカスタムフェイス用に実装したコードは下記の2つになります。

  • スケッチファイル

    • /example/laputa-face/laputa-face.ino

  • カスタムフェイス定義

    • /src/faces-custom/LaputaFace.h

このカスタマイズでは、顔の輪郭の作成、目、口の顔パーツの新規定義を行っています。
眉毛は表示させないようスタックチャンのデフォルトの顔 [・_・]と同様に高さを0にしています。
コードの詳細については、リポジトリの上記ファイルをご覧ください。
ここではカスタムフェイス定義での作成概要を記載します。

  • laputa-face.ino

    • Avatarクラスの初期化の際に、引数を与えて複数色の使用を有効にしています。

      • avatar.init(8);

        • 8ビットカラーの使用が可能。もっと多色にしたい場合16,24などに上げることができるようです。

      • デフォルトは avatar.init(); この状態だと2色しか表示できない。

  • LaputaFace.h : LaputaEye

    • 目のクラス

    • 感情ごとに、目の色が変わるように設定しています。

  • LaputaFace.h : LaputaMouth

    • 口のクラス

    • ロボット兵の輪郭の部分もこのクラスの中で定義しています。

      • 丸や三角などを組み合わせて輪郭の形状を作りました。

    • 顔の輪郭部の色は、固定値かつ任意のRGBで指定しています。

    • 口の機能は顔の中央にある2つの小さい●に持たせたい(しゃべると色が変わるような感じ)と考えていますがまだ実装できてません。とりあえず起こったときだけ赤くしています。

この作例では、複数色の使用や顔輪郭の作成などが試すことができて、表現の幅が広がりました。
(頑張ればガンダムとかも作れるんじゃないか?とか)

こちらの顔でも、要素配置のあたりを付けるために次のような下絵を作成してみました。

補足2:使用可能な色について

M5Stackでは、いくつかの色について、TFT_REDやTFT_BLACKといった名前で定義されているため、基本的にはその定義を使うのが簡単です。
https://github.com/m5stack/m5-docs/blob/master/docs/ja/api/lcd.md

ただ、やっぱり自分の欲しい色(またはそれに近い色)が無い!という場合は、下記のサイトなどを使ってRGB
値を調べて、下記のコードを使ってプログラムで使用可能な形に変換する必要があります。
http://hello.lumiere-couleur.com/app/16bit-colorpicker/

// darkkhaki / #BDB76B / 189,183,107
// RGB値をM5Stackで使用可能な数値に変換
uint16_t  basefaceColor = M5.Lcd.color565(189,183,107);

なんかめっちゃ長くなった。。。
読みにくかったらすいません。

謝辞

複数色を扱おうとしていた際に、avatar.init(数字)の仕組みに気が付かず悩んでいた時にタカオさん(@mongonta555)に助けていただきました。ありがとうございました!

この記事が気に入ったらサポートをしてみませんか?