M5Core2ImageAvatarLiteのパーツを作成する

M5Stack Advent Calender 2023の12日目の記事です。M5Core2ImageAvatarLiteのパーツの作り方についてステップバイステップで紹介していきます。

 もくじ(Index)

M5Stack関連の目次へ戻る

M5Core2ImageAvatarLiteとは?

 M5Stack-Avatarは点や線を組み合わせて様々な表情を描画できます。そこから、複雑なキャラクターの顔をなんとか簡単に動きを付けられないかということから画像を元に目と口、頭のパーツを作成すればAvatarにできそうということで作成してみました。※補足、ImageAvatarLiteの上位バージョン(M5Stack-Image-Avatar)もありますが設定が複雑なので現在メンテしていません。(M5Unified化等もまだです。)
 下記の3ステップで自分の好きなキャラクターをM5Stackの顔にすることが可能です。

  1. 画像ファイルを5つ用意する。(開いた目、開いた口、閉じた目、閉じた口、顔)
  2. JSONファイルで各パーツの座標を指定する。
  3. SDカードに1,2で用意したファイルを書きこむ

キャラクターは20種類まで登録可能

 JSONファイルを切り替えて、異なるキャラクターを切り替えることができます。下記のツイートでは9種類のキャラクターを切り替えています。

用意するソフト

  • GIMP が便利です。

パーツの作り方(表情1個分)

 1キャラクターで必要なパーツは下記の5つです。普通・怒る・笑うという感情を切り替えたい場合は、目と口をそれぞれ表情の分用意します。

①元の画像を用意する

 正面の顔があればベストです。今回はDALL・Eで書いてみました。

 必要なのは、下記なので切り出せる素材を選びます。

  • 開いた目、閉じた目
  • 開いた口、閉じた口
  • 顔の背景

②画像を切り出して320×240に拡大縮小する

 画像をM5Stackサイズに変換します。 4:3で切り取って320×240に拡大縮小すると簡単です。

 今回の画像では400×300で切り抜いた後、320×240に縮小しました。

③画像のエクスポート(各工程共通)

 GIMPで画像をエクスポートします。拡張子はbmpで24bitのビットマップファイルとしてエクスポートします。以降のどのパーツもエクスポートする際は必ず「24bitBMP」でエクスポートしてください。

④目の切り抜き

切り抜きの注意事項ですが、開いた目と閉じた目を同じ大きさで切り抜きます。どちらか大きい方にサイズを合わせてください。切り抜きのポイントは下記です。

  • 閉じた目と閉じた目は同じ大きさにする
    大きい方に合わせて四角に切り抜きます。
  • サイズは縦、横ともに下記のルールを守ります。(画像の境界に線が出る場合があります。)
    2で割った時に偶数になるようにする。
    例、76/2=38はOK、74/2=37はNG
  • ファイル名は任意ですが、私は下記のようにしています。(※ファイル名は半角英数字32文字以内に抑えてください。)
    eye_(op or cl)_expression.bmp

    例、
    eye_op_normal.bmp
    eye_cl_normal.bmp

加工前の素材

加工後

 今回は104×104で切り抜いて周りを透明色(緑:0x00FF00)で鉛筆を使って塗りつぶします。
 ※塗りつぶし機能やブラシを使うと緑が中間色になってしまい残ります。必ず鉛筆機能を使って塗ります。

⑤口の切り抜き

目と同様です。

  • 閉じた口と閉じた口は同じ大きさにする
    大きい方に合わせて四角に切り抜きます。
  • サイズは縦、横ともに下記のルールを守ります。(画像の境界に線が出る場合があります。)
    2で割った時に偶数になるようにする。
    例、76/2=38はOK、74/2=37はNG
  • ファイル名は任意ですが、私は下記のようにしています。(※ファイル名は半角英数字32文字以内に抑えてください。)
    mouth_(op or cl)_expression.bmp

    例、
    mouth_op_normal.bmp
    mouth_cl_normal.bmp

加工前の素材

加工後

⑥顔(体)の背景

 今回はシンプルに塗りつぶしました。

⑦パーツをmicroSDカードのフォルダにコピー

microSDカードにフォルダを作成し、作成したbmpファイルをコピーします。(例、フォルダ名はbmp_demo)

JSONファイルの準備

M5Core2ImageAvatarLiteでは下記のように3種類のjsonファイルが必要です。(キャラクターを増やしたい場合はM5AvatarLite_???.jsonを増やします。)

①/json/M5AvatarLiteSytem.json(ファイル名変更不可)

今回の例(demo顔のみ)

{
    "volume" : 200,
    "lcd_brightness" : 150,
    "avatar_json": [
        "/json/M5AvatarLite_demo.json"
    ],
    "bluetooth_device_name" : "M5StackBTSPK",
    "bluetooth_reconnect"   : true,
    "servo_json" : "/json/M5AvatarLiteServo.json",
    "servo_random_mode" : true,
    "auto_power_off_time" : 10000,
    "led_lr" : 2
}

複数のキャラクターを切り替える例

{
    "volume" : 200,
    "lcd_brightness" : 150,
    "avatar_json": [
        "/json/M5AvatarLite_demo.json",
        "/json/M5AvatarLite_phy.json",
        "/json/M5AvatarLite_mieai.json",
        "/json/M5AvatarLite_gundam00.json",
        "/json/M5AvatarLite_hoshinoai.json",
        "/json/M5AvatarLite_makimaki2.json",
        "/json/M5AvatarLite00bocchi.json",
        "/json/M5AvatarLite01ahnya.json",
        "/json/M5AvatarLite01yurei.json"
    ],
    "bluetooth_device_name" : "ESP32Core2_05",
    "bluetooth_reconnect"   : true,
    "servo_json" : "/json/M5AvatarLiteServo.json",
    "servo_random_mode" : true,
    "auto_power_off_time" : 10000,
    "led_lr" : 2
}

②M5AvatarLite_demo.json(ファイル名はM5AvatarLiteSystem.jsonに記述したもの)

表情がnormal1つの場合

{
    "expression": [
        "normal"
    ],

    "sprite_info": {
        "psram": "true",
        "color_depth": 16,
        "swap_bytes": 0
    },
    "color_info": {
        "skin"  : "0xFF5B00",
        "eye_white" : "0xFFFFFF",
        "transparent"    : "0x00FF00",
        "transparent2"   : "0x00FF00U"
    },
    "fixed_parts": [
        {
            "parts": "body",
            "x": 0,
            "y": 0,
            "w": 320,
            "h": 240,
            "filename": "/bmp_demo/head.bmp"
        }
    ],
    "mouth": [
        {
            "normal": {
                "x": 160,
                "y": 180,
                "w": 76,
                "h": 76,
                "filename": {
                    "open": "/bmp_demo/mouth_op_normal.bmp",
                    "close": "/bmp_demo/mouth_cl_normal.bmp"
                },
                "minScaleX": 1.0,
                "maxScaleX": 1.0,
                "minScaleY": 0.01,
                "maxScaleY": 1.0
            }
        }
    ],
    "eye": [
        {
            "normal": {
                "rx": 70,
                "ry": 120,
                "lx": 250,
                "ly": 120,
                "w": 104,
                "h": 104,
                "filename": {
                    "open": "/bmp_demo/eye_op_normal.bmp",
                    "close": "/bmp_demo/eye_cl_normal.bmp"
                },
                "minScaleX": 1.0,
                "maxScaleX": 1.0,
                "minScaleY": 0.3,
                "maxScaleY": 1.0,
                "invert"   : false
            }
        }
    ],
    "init_param": [
        {
            "normal": {
                "eye_l_ratio": 0.0,
                "eye_r_ratio": 0.0,
                "mouth_ratio": 0.0,
                "angle": 0.0,
                "breath": 0
            }
        }
    ]
}

表情が複数ある場合(今回は目の反転を変えるだけです。)

{
    "expression": [
        "normal",
        "laugh"
    ],

    "sprite_info": {
        "psram": "true",
        "color_depth": 16,
        "swap_bytes": 0
    },
    "color_info": {
        "skin"  : "0xFF5B00",
        "eye_white" : "0xFFFFFF",
        "transparent"    : "0x00FF00",
        "transparent2"   : "0x00FF00U"
    },
    "fixed_parts": [
        {
            "parts": "body",
            "x": 0,
            "y": 0,
            "w": 320,
            "h": 240,
            "filename": "/bmp_demo/head.bmp"
        }
    ],
    "mouth": [
        {
            "normal": {
                "x": 160,
                "y": 180,
                "w": 76,
                "h": 76,
                "filename": {
                    "open": "/bmp_demo/mouth_op_normal.bmp",
                    "close": "/bmp_demo/mouth_cl_normal.bmp"
                },
                "minScaleX": 1.0,
                "maxScaleX": 1.0,
                "minScaleY": 0.01,
                "maxScaleY": 1.0
            }
        },
        {
            "laugh": {
                "x": 160,
                "y": 180,
                "w": 76,
                "h": 76,
                "filename": {
                    "open": "/bmp_demo/mouth_op_normal.bmp",
                    "close": "/bmp_demo/mouth_cl_normal.bmp"
                },
                "minScaleX": 1.0,
                "maxScaleX": 1.0,
                "minScaleY": 0.1,
                "maxScaleY": 1.0
            }
        }
    ],
    "eye": [
        {
            "normal": {
                "rx": 70,
                "ry": 120,
                "lx": 250,
                "ly": 120,
                "w": 104,
                "h": 104,
                "filename": {
                    "open": "/bmp_demo/eye_op_normal.bmp",
                    "close": "/bmp_demo/eye_cl_normal.bmp"
                },
                "minScaleX": 1.0,
                "maxScaleX": 1.0,
                "minScaleY": 0.3,
                "maxScaleY": 1.0,
                "invert"   : false
            }
        },
        {
            "laugh": {
                "rx": 70,
                "ry": 120,
                "lx": 250,
                "ly": 120,
                "w": 104,
                "h": 104,
                "filename": {
                    "open": "/bmp_demo/eye_op_normal.bmp",
                    "close": "/bmp_demo/eye_cl_normal.bmp"
                },
                "minScaleX": 1.0,
                "maxScaleX": 1.0,
                "minScaleY": 0.3,
                "maxScaleY": 1.0,
                "invert"   : true
            }
        }
    ],
    "init_param": [
        {
            "normal": {
                "eye_l_ratio": 0.0,
                "eye_r_ratio": 0.0,
                "mouth_ratio": 0.0,
                "angle": 0.0,
                "breath": 0
            }
        },
        {
            "laugh": {
                "eye_l_ratio": 0.0,
                "eye_r_ratio": 0.0,
                "mouth_ratio": 0.0,
                "angle": 0.0,
                "breath": 0
            }
        }
    ]
}

③M5AvatarLiteServo.json(サーボの設定)

 サーボを使わない場合は特に変更は必要ないですが、置いてください。

{
    "initial_settings": {
        "x_axis": {
            "pin"    : 13,
            "center" : 90,
            "lower"  : 0,
            "upper"  : 180,
            "start"  : 90,
            "offset" : 0
        },
        "y_axis": {  
            "pin"    : 14,
            "center" : 60,
            "lower"  : 30,
            "upper"  : 90,
            "start"  : 90,
            "offset" : -5
        }

    },
    "servo_enable" : "false"
}

Demoデータのフォルダ構成

動作に必要なファイルの構成は下記のようになります。

  • json
    • M5AvatarLiteSystem.json
    • M5AvatarLiteServo.json
    • M5AvatarLite_demo.json
  • bmp_demo
    • head.bmp
    • eye_cl_normal.bmp
    • eye_op_normal.bmp
    • mouth_cl_normal.bmp
    • mouth_op_normal.bmp

Demoが動作している様子

キャラクターの切り替えはBtnA、感情の切り替えはBtnCを長押しするとできます。

終わりに

 自分の好きなアニメのキャラをAvatarにできると一層可愛さが増します。あなた自身のオリジナルキャラでもいいので是非挑戦してみてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です