ツールの話をしよう~コマンドライン翻訳


このブログを見てらっしゃる方はtwitterのFFの方がメインであろうかと思います。
つまりは小説関連のご同胞ですよね?
皆さん、翻訳・辞書ツールを使っていらっしゃると思います。
今回は私が使っている Windows10 PC上でのコマンドラインで動作する翻訳・辞書ツールをご紹介しようと思います。

その名もtranslate-shellです。
soimort/translate-shell: Command-line translator … – GitHub

このツールはコマンドラインからgoogle翻訳等のWEBアプリを使って、翻訳したり辞書をひいたりしてくれる超便利なソフトです。
小説の執筆をしているときに、ちょっと「この英単語、どういう意味だっけ?」とか、「英語タイトルなんにしよう?」とか思うことありますよね。
それでいちいちChromeを立ち上げてgoogle翻訳を開くってめんどくさいですよね?
そんなとき、コマンドラインからバシャバシャっと入力して辞書を引いたり翻訳できたら便利だと思いません?
私はすごく思います。

例えば和英翻訳ならばこんな感じ。

kuyo@DESKTOP-8O0L9BP:~$ je '腹が減った'
腹が減った
(Haragahetta)

I am hungry

Translations of 腹が減った
[ 日本語 -> English ]

腹が減った
    I am hungry, hungry
kuyo@DESKTOP-8O0L9BP:~$

例えば英和翻訳ならばこんな感じ。

kuyo@DESKTOP-8O0L9BP:~$ ej 'Never let me go'
Never let me go

私を離さないで
(Watashi o hanasanaide)

Translations of Never let me go
[ English -> 日本語 ]

Never let me go
    私を離さないで, 私を手放すことはありません, 私は手放すことはありません
kuyo@DESKTOP-8O0L9BP:~$

例えば和英辞書ならばこんな感じ。

kuyo@DESKTOP-8O0L9BP:~$ je -d 'きょうだい'
きょうだい
(Kyō dai)

Siblings

Translations of きょうだい
[ 日本語 -> English ]
kuyo@DESKTOP-8O0L9BP:~$

例えば英和辞書ならこんな感じ。

kuyo@DESKTOP-8O0L9BP:~$ ej 'Sibling'
Sibling
/ˈsibliNG/

兄弟姉妹
(Keiteishimai)

Translations of Sibling
[ English -> 日本語 ]

Sibling
    兄弟姉妹, 兄弟
kuyo@DESKTOP-8O0L9BP:~$

英英辞書的にも使えます。

kuyo@DESKTOP-8O0L9BP:~$ ej -d 'love'
love
/ləv/

愛
(Ai)

Definitions of love
[ English -> 日本語 ]

verb
    feel a deep romantic or sexual attachment to (someone).
        - "Though you tried to deny it, you must trust your heart that deep inside you love him."
    Synonyms: care very much for, feel deep affection for, hold very dear, adore, think the world of, be devoted to, dote on, idolize, worship, be in love with, be infatuated with, be smitten with, be besotted with, be mad/crazy/nuts/wild about, have a crush on, carry a torch for

noun
    an intense feeling of deep affection.
        - "My brother, and his real, strong love for me that was able to pull me back into the world I know."
    Synonyms: deep affection, fondness, tenderness, warmth, intimacy, attachment, endearment, devotion, adoration, doting, idolization, worship, passion, ardor, desire, lust, yearning, infatuation, besottedness

    a person or thing that one loves.
        - "By the end of the trip I knew she had two loves ; her son and her carpets."
    Synonyms: beloved, loved one, love of one's life, dear, dearest, dear one, darling, sweetheart, sweet, angel, honey, lover, inamorato, inamorata, amour, paramour

    (in tennis, squash, and some other sports) a score of zero; nil.
        - "To come back from two sets to love and win it is an awesome feeling."

Synonyms
    verb
        - care very much for, feel deep affection for, hold very dear, adore, think the world of, be devoted to, dote on, idolize, worship, be in love with, be infatuated with, be smitten with, be besotted with, be mad/crazy/nuts/wild about, have a crush on, carry a torch for
        - like very much, delight in, enjoy greatly, have a passion for, take great pleasure in, derive great pleasure from, relish, savor, have a weakness for, be partial to, have a soft spot for, have a taste for, be taken with, get a kick out of, have a thing about, be mad/crazy/nuts/wild about, be hooked on, get off on
        - enjoy
        - have intercourse, eff, hump, get laid, make out, have sex, do it, fuck, bed, make love, jazz, sleep together, bang, screw, bonk, be intimate, know, lie with, have it off, sleep with

    noun
        - relationship, love affair, romance, liaison, affair of the heart, amour
        - beloved, loved one, love of one's life, dear, dearest, dear one, darling, sweetheart, sweet, angel, honey, lover, inamorato, inamorata, amour, paramour
        - best wishes, regards, good wishes, greetings, kind/kindest regards
        - liking of/for, enjoyment of, appreciation of/for, taste for, delight for/in, relish of, passion for, zeal for, appetite for, zest for, enthusiasm for, keenness for, fondness for, soft spot for, weakness for, bent for, proclivity for, inclination for, disposition for, partiality for, predilection for, penchant for
        - compassion, care, caring, regard, solicitude, concern, friendliness, friendship, kindness, charity, goodwill, sympathy, kindliness, altruism, unselfishness, philanthropy, benevolence, fellow feeling, humanity
        - deep affection, fondness, tenderness, warmth, intimacy, attachment, endearment, devotion, adoration, doting, idolization, worship, passion, ardor, desire, lust, yearning, infatuation, besottedness
        - love life, lovemaking, making love, sexual love
        - passion
        - dear, dearest, beloved, honey
        - sexual love

Examples
    - In short, how can there be love for the country without love for the people?

    - they were both in love with her

    - babies fill parents with intense feelings of love

    - Ian drinks his coffee and talks enthusiastically about his love of singing.

    - people who love democracy

    - I guess Michael and I were trying to find a way to express our brotherly love for one another.

    - So passionate is my love of opera, that I crave any activity that extends my time in the Arts Centre.

    - Years later he has combined his love for zoology with his appreciation of the female form.

    - She dwells on her charming manner, love of clothes, loyalty to her brother and, in later life, to her adoptive city.

    - you're such a love!

    - "Emily, my dear," said the spinster aunt, with a patronising air, "don't talk so loud, love."

    - You did that? I love it!

    - He lost his ambition and forgot everything but his love for this unworthy woman.

    - Brotherly love comes at a price, it seems.

    - He truly did love her, and deep down he knew his family would too, but he was still nervous.

    - All the very very best to you Tom, and lots of love from Charlie.

    - I had a great interest and love of music, and music was always a part of the family, but no one had ever pursued it.

    - Looking forward to seeing you soon, Lots of love, Grannie

    - We also send our best love to you and the children all wish that they were going on the same ship as their Father.

    - Each one is very powerful, but none of them is as strong as your love for your daughter.

    - do you love me?

    - We have always happy together and our love for each other has been strong and growing for sometime now.

    - we share a love of music

    - Try falling in love with someone who is from a different country and speaks a different language.

    - She did not overtly try to attract Edgar, but he was still falling in love with her.

    - My love for her was as strong as ever, as it is now, at this very moment.

    - I'd love a cup of tea

    - It's alright my love you are safe with me.

    - I had to try to put my intense passionate love for him to the side and be his friend.

    - their love for their country
kuyo@DESKTOP-8O0L9BP:~$

どうですか?
便利でしょう?
これはLinuxのShellとかで動作するコマンドなのですが、Windows10にインストールすることも可能です。
ただ、多少手順がめんどくさいので順を追って説明しますね。

Windows10上のコマンドラインと言ってもDOS窓でもなければ、PowerShellでもありません。
WSLです。

WSLはWindows Subsystem for Linuxの略で、マイクロソフトが提供する、Windows10上で動作するLinuxなんですね。
コマンドライン上でLinuxの様々なツールが使えてしまうというスグレモノです。

先ずはWSLのインストールから始めます。
WHLのインストールのために、まずWHLを許可します。
コントロールパネルを開きます。

[プログラム]をクリックします。

[プログラムと機能]をクリックします。

左ペインにある[Windowsの機能の有効化または無効化]をクリックします。

リストの下のほうにある[Windows Subsystem for Linux]のチェックを入れて[OK]をクリックします。

暫く待つと完了します。

PCの再起動を求められるので再起動します。

スタートメニューから[Microsoft Store]を起動します。

検索から[WSL]を探します。

LinuxのDistributionを選びます。
特に好みが無ければUbuntuが良いでしょう。

[入手]をクリック。
インストールされます。

[起動]をクリックするとWSLのコマンドラインが開きます。

暫く待つとuser nameを聞いてきます。

ここで自分の作成したいuser nameを入力します。
私はkuyoにしました。

次にuserのpasswordを聞いてきます。
ローカルの話なので適当に覚えやすいpasswordを設定します。

確認のためにもう一度passwordを入力します。

これでWSLのインストールはおしまいです。
Windows上に仮想的なLinuxが立ち上がったことになります。
しかもUbuntuですからaptで欲しいツールを簡単にインストールすることができます。

ちなみにこのLInux環境のrootディレクトリは以下になります。

C:\Users\%USERNAME%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\

kuyoのhomeは以下ですね。

C:\Users\%USERNAME%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\kuyo

ではWSLのコマンドターミナルから必要なツールをインストールします。
先ずはaptのupdate。

kuyo@DESKTOP-8O0L9BP:~$ sudo apt update
[sudo] password for kuyo:

passwordを聞いてくるので先ほど設定したものを入力します。

導入にはいくつかのツールが必要です。
具体的にはgit, gawk, makeが必要なのでインストールします。

kuyo@DESKTOP-8O0L9BP:~$ sudo apt install git
kuyo@DESKTOP-8O0L9BP:~$ sudo apt install gawk

gitとgawkが必要ですが既に最新のものが入っていました。
makeもインストールします。

kuyo@DESKTOP-8O0L9BP:~$ sudo apt install make
kuyo@DESKTOP-8O0L9BP:~$ sudo apt install make-guile

途中”Do you want to continue? [Y/n] Y”と聞いてきますのでyと[enter]キーを押します。
ネットへの接続が必要です。

次にtranslate-shellをダウンロードします。

kuyo@DESKTOP-8O0L9BP:~$ git clone https://github.com/soimort/translate-shell

ディレクトリを移動します。

kuyo@DESKTOP-8O0L9BP:~$ cd translate-shell

makeしてinstallします。

kuyo@DESKTOP-8O0L9BP:~/translate-shell$ make
[OK] Task build completed.
kuyo@DESKTOP-8O0L9BP:~/translate-shell$ sudo make install
[OK] Task build completed.
[OK] translate-shell installed.
kuyo@DESKTOP-8O0L9BP:~/translate-shell$

以上でインストールはおしまいです。
transというコマンドがインストールされました。
使い方は以下で分かります。

kuyo@DESKTOP-8O0L9BP:~$ trans --help
Usage:  trans [OPTIONS] [SOURCES]:[TARGETS] [TEXT]...

Information options:
    -V, -version
        Print version and exit.
    -H, -help
        Print help message and exit.
    -M, -man
        Show man page and exit.
    -T, -reference
        Print reference table of languages and exit.
    -R, -reference-english
        Print reference table of languages (in English names) and exit.
    -L CODES, -list CODES
        Print details of languages and exit.
    -S, -list-engines
        List available translation engines and exit.
    -U, -upgrade
        Check for upgrade of this program.

Translator options:
    -e ENGINE, -engine ENGINE
        Specify the translation engine to use.

Display options:
    -verbose
        Verbose mode. (default)
    -b, -brief
        Brief mode.
    -d, -dictionary
        Dictionary mode.
    -identify
        Language identification.
    -show-original Y/n
        Show original text or not.
    -show-original-phonetics Y/n
        Show phonetic notation of original text or not.
    -show-translation Y/n
        Show translation or not.
    -show-translation-phonetics Y/n
        Show phonetic notation of translation or not.
    -show-prompt-message Y/n
        Show prompt message or not.
    -show-languages Y/n
        Show source and target languages or not.
    -show-original-dictionary y/N
        Show dictionary entry of original text or not.
    -show-dictionary Y/n
        Show dictionary entry of translation or not.
    -show-alternatives Y/n
        Show alternative translations or not.
    -w NUM, -width NUM
        Specify the screen width for padding.
    -indent NUM
        Specify the size of indent (number of spaces).
    -theme FILENAME
        Specify the theme to use.
    -no-theme
        Do not use any other theme than default.
    -no-ansi
        Do not use ANSI escape codes.
    -no-autocorrect
        Do not autocorrect. (if defaulted by the translation engine)
    -no-bidi
        Do not convert bidirectional texts.
    -bidi
        Always convert bidirectional texts.
    -no-warn
        Do not write warning messages to stderr.
    -dump
        Print raw API response instead.

Audio options:
    -p, -play
        Listen to the translation.
    -speak
        Listen to the original text.
    -n VOICE, -narrator VOICE
        Specify the narrator, and listen to the translation.
    -player PROGRAM
        Specify the audio player to use, and listen to the translation.
    -no-play
        Do not listen to the translation.
    -no-translate
        Do not translate anything when using -speak.
    -download-audio
        Download the audio to the current directory.
    -download-audio-as FILENAME
        Download the audio to the specified file.

Terminal paging and browsing options:
    -v, -view
        View the translation in a terminal pager.
    -pager PROGRAM
        Specify the terminal pager to use, and view the translation.
    -no-view, -no-pager
        Do not view the translation in a terminal pager.
    -browser PROGRAM
        Specify the web browser to use.
    -no-browser
        Do not open the web browser.

Networking options:
    -x HOST:PORT, -proxy HOST:PORT
        Use HTTP proxy on given port.
    -u STRING, -user-agent STRING
        Specify the User-Agent to identify as.
    -4, -ipv4, -inet4-only
        Connect only to IPv4 addresses.
    -6, -ipv6, -inet6-only
        Connect only to IPv6 addresses.

Interactive shell options:
    -I, -interactive, -shell
        Start an interactive shell.
    -E, -emacs
        Start the GNU Emacs front-end for an interactive shell.
    -no-rlwrap
        Do not invoke rlwrap when starting an interactive shell.

I/O options:
    -i FILENAME, -input FILENAME
        Specify the input file.
    -o FILENAME, -output FILENAME
        Specify the output file.

Language preference options:
    -l CODE, -hl CODE, -lang CODE
        Specify your home language.
    -s CODES, -sl CODES, -source CODES, -from CODES
        Specify the source language(s), joined by '+'.
    -t CODES, -tl CODES, -target CODES, -to CODES
        Specify the target language(s), joined by '+'.

Text preprocessing options:
    -j, -join-sentence
        Treat all arguments as one single sentence.

Other options:
    -no-init
        Do not load any initialization script.

See the man page trans(1) for more information.
kuyo@DESKTOP-8O0L9BP:~$

ただしこのままでは使いにくいので ~/.bashrc に以下の二行を付け加えます。

alias ej="trans -sl=en -tl=ja"
alias je="trans -sl=ja -tl=en"

テキストエディッタはnanoというものが標準でインストールされているのでそれを使います。
もちろんvimをインストールするのでも良いし、以下のファイルをWindowsのテキストエディッタで直接編集するのでも構いません。

C:\Users\%USERNAME%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\kuyo\.bashrc

編集できましたら一度exitコマンドで抜けます。

kuyo@DESKTOP-8O0L9BP:~$ exit   

再度の起動はスタートメニューから行えます。
Ubuntuならば以下のようなアプリが増えています。

いかがでしょうか?
手順は多いのですが、意外と簡単にインストールすることができました。
これで快適な執筆ライフがおくれますね。

WSLは単にtranslate-shellのためだけではなく、様々なツールを使うことができます。
例えば電卓。
bcというコマンドがあります。
これはコマンドラインで計算ができるというスグレモノです。

小説を執筆しているときに距離だとか時間の確認に電卓が欲しい場合がありますが、これもコマンドラインで用が足りてしまうわけです。
変数も使えるし、上下カーソルで履歴も拾えるので普通の電卓よりも高機能だったりします。
終了は quit と入力して[enter]キーを押します。

ご同胞の諸兄姉の執筆ライフが少しでも充実されんことを心より祈りつつ。


挿絵画家になろう(その8)


「挿絵画家になろう(その8)」です。
Blenderのアドオン、MB-Labの啓蒙です。
MB-Labを使って秀逸な少女キャラクターのメッシュオブジェクトを生成し、VRoidStudioの髪をインポートして装着させ、そこそこの服を着せ、キャラクターのマテリアルも弄れるようになり、更に表情も変更できるようになりました。

今回はポーズについてです。
しかしながらMB-LabのキャラクターはBlenderの人型モデルなので単にポーズをつけるだけならばBlenderの操作方法を学べばよいことになります。
ググればポーズのつけかたを解説しているサイトがいくつもあるので今更私が説明する必要もないでしょう。
難しいですが慣れるとわりと自由にポーズを付けられるようになります。

ではあるものの、我らがMB-Labにはポーズライブラリが付属します。
Blenderで人型キャラクターのポーズ付けに挫折した人でもポーズライブラリから選択し、ポーズをつけることができます。
らくちんですね。

ただ決められたポーズだけでは、挿絵を欲する同胞の諸兄姉は満足できないでしょう。
そんな諸兄姉にポーズライブラリを組み合わせて新しいポーズを作成する方法を展開しましょう。
Blenderの知識が要らない代わりにスクリプト言語の知識が必要になってきます。
諸兄姉はPythonの知識がありますよね?
あるといいな。
無くても、今回は言語的な知識はなくても良いように記事を書く予定です。
以前の記事』にPythonのインストールに書いてますので参考にしてください。

MB-LabはBlenderのアドオンなのですが、Windows10の場合、難しい事をしなければ通常以下にインストールされます。

C:\Users\%USERNAME%\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\addons\manuelbastionilab

MB-Labで生成されるキャラクターの雛形は以下のBlender Projectファイルに収められています。

C:\Users\%USERNAME%\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\addons\manuelbastionilab\data
humanoid_library.blend

このファイルを開くと分かるのですが、メッシュやアーマチュア、マテリアル、その他が定義されています。

基本ポーズはAポーズですね。
で、ポーズライブラリは以下のディレクトリになります。

C:\Users\%USERNAME%\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\addons\manuelbastionilab\data\poses

このディレクトリには以下の三つのディレクトリがあります。
female_poses
male_poses
rest_poses

rest_poseのディレクトリには以下のファイルがあります。
a-pose.json
a-pose.json
lambda-pose.json
lambda-pose.json
lambda-pose.json

このファイル名、どこかで見たことがありますね。
そうです、MB-LabのRest Poseの選択肢です。

各ポーズはjson形式というテキストファイルで記述されています。
試しにa-pose.jsonの中身を確認してみましょう。
テキストファイルなので普通にテキストエディッタで開けば見ることができます。
しかし改行がないので若干見にくいので次のようなスクリプトを使って解析します。

import json

pose = './a-pose.json'

with open(pose) as f_b:
    df_b = json.load(f_b)
    for w in df_b:
        print(w," = ",df_b[w])

jsonのファイルはKeyとValueの対を定義するリスト構造となっています。
このスクリプトはKeyとValueの対を表示します。
結果は以下のようになります。

thumb02_L  =  [1.0, 0.0, 0.0, 0.0]
calf_twist_R  =  [1.0, 0.0, 0.0, 0.0]
ring03_L  =  [1.0, 0.0, 0.0, 0.0]
thumb02_R  =  [1.0, 0.0, 0.0, 0.0]
pinky00_L  =  [1.0, 0.0, 0.0, 0.0]
pinky02_R  =  [1.0, 0.0, 0.0, 0.0]
ring00_R  =  [1.0, 0.0, 0.0, 0.0]
breast_L  =  [1.0, 0.0, 0.0, 0.0]
ring02_R  =  [1.0, 0.0, 0.0, 0.0]
lowerarm_R  =  [1.0, 0.0, 0.0, 0.0]
middle02_L  =  [1.0, 0.0, 0.0, 0.0]
neck  =  [1.0, 0.0, 0.0, 0.0]
ring02_L  =  [1.0, 0.0, 0.0, 0.0]
middle03_L  =  [1.0, 0.0, 0.0, 0.0]
ring00_L  =  [1.0, 0.0, 0.0, 0.0]
pelvis  =  [1.0, 0.0, 0.0, 0.0]
ring01_R  =  [1.0, 0.0, 0.0, 0.0]
thigh_R  =  [1.0, 0.0, 0.0, 0.0]
index02_R  =  [1.0, 0.0, 0.0, 0.0]
upperarm_L  =  [1.0, 0.0, 0.0, 0.0]
clavicle_R  =  [1.0, 0.0, 0.0, 0.0]
pinky02_L  =  [1.0, 0.0, 0.0, 0.0]
index01_R  =  [1.0, 0.0, 0.0, 0.0]
middle00_L  =  [1.0, 0.0, 0.0, 0.0]
calf_twist_L  =  [1.0, 0.0, 0.0, 0.0]
thigh_twist_L  =  [1.0, 0.0, 0.0, 0.0]
upperarm_twist_L  =  [1.0, 0.0, 0.0, 0.0]
middle02_R  =  [1.0, 0.0, 0.0, 0.0]
hand_R  =  [1.0, 0.0, 0.0, 0.0]
ring01_L  =  [1.0, 0.0, 0.0, 0.0]
toes_R  =  [1.0, 0.0, 0.0, 0.0]
index03_R  =  [1.0, 0.0, 0.0, 0.0]
lowerarm_L  =  [1.0, 0.0, 0.0, 0.0]
spine03  =  [1.0, 0.0, 0.0, 0.0]
lowerarm_twist_L  =  [1.0, 0.0, 0.0, 0.0]
middle01_R  =  [1.0, 0.0, 0.0, 0.0]
index00_R  =  [1.0, 0.0, 0.0, 0.0]
spine01  =  [1.0, 0.0, 0.0, 0.0]
foot_L  =  [1.0, 0.0, 0.0, 0.0]
index02_L  =  [1.0, 0.0, 0.0, 0.0]
thumb01_R  =  [1.0, 0.0, 0.0, 0.0]
pinky03_L  =  [1.0, 0.0, 0.0, 0.0]
ring03_R  =  [1.0, 0.0, 0.0, 0.0]
thumb03_R  =  [1.0, 0.0, 0.0, 0.0]
index01_L  =  [1.0, 0.0, 0.0, 0.0]
middle00_R  =  [1.0, 0.0, 0.0, 0.0]
lowerarm_twist_R  =  [1.0, 0.0, 0.0, 0.0]
breast_R  =  [1.0, 0.0, 0.0, 0.0]
foot_R  =  [1.0, 0.0, 0.0, 0.0]
middle01_L  =  [1.0, 0.0, 0.0, 0.0]
upperarm_R  =  [1.0, 0.0, 0.0, 0.0]
pinky01_R  =  [1.0, 0.0, 0.0, 0.0]
middle03_R  =  [1.0, 0.0, 0.0, 0.0]
hand_L  =  [1.0, 0.0, 0.0, 0.0]
pinky01_L  =  [1.0, 0.0, 0.0, 0.0]
head  =  [1.0, 0.0, 0.0, 0.0]
spine02  =  [1.0, 0.0, 0.0, 0.0]
calf_R  =  [1.0, 0.0, 0.0, 0.0]
thigh_L  =  [1.0, 0.0, 0.0, 0.0]
clavicle_L  =  [1.0, 0.0, 0.0, 0.0]
upperarm_twist_R  =  [1.0, 0.0, 0.0, 0.0]
index03_L  =  [1.0, 0.0, 0.0, 0.0]
thumb03_L  =  [1.0, 0.0, 0.0, 0.0]
calf_L  =  [1.0, 0.0, 0.0, 0.0]
root  =  [1.0, 0.0, 0.0, 0.0]
toes_L  =  [1.0, 0.0, 0.0, 0.0]
pinky03_R  =  [1.0, 0.0, 0.0, 0.0]
pinky00_R  =  [1.0, 0.0, 0.0, 0.0]
index00_L  =  [1.0, 0.0, 0.0, 0.0]
thumb01_L  =  [1.0, 0.0, 0.0, 0.0]
thigh_twist_R  =  [1.0, 0.0, 0.0, 0.0]

ポーズデーターファイルはボーンとその回転量を表す四つの実数の組のリストデーターなのです。
対応するボーンは以下のように実際に使われているアーマチュアのボーン名と一致します。

ボーンは親のボーンがあって子のボーンは親の位置と回転量に影響をうけます。
親子関係のツリー構造は以下のようになっています。

root:すべてのボーンの親
└pelvis:腰
  ├thigh_R:太腿
  │├thigh_twist_R
  │└calf_R:脛
  │  ├calf_twist_R
  │  └foot_R:足の甲
  │    └toes_R:爪先
  ├thigh_L:太腿
  │├thigh_twist_L
  │└calf_L:脛
  │  ├calf_twist_L
  │  └foot_L:足の甲
  │    └toes_L:爪先
  └spine01:脊椎
    └spine02
      └pine03
        ├neck:首
        │└head:頭
        ├breast_R:乳房
        ├breast_L:乳房
        ├clavicle_R:鎖骨
        │└upperarm_R:上腕
        │  ├upperarm_twist_R
        │  └lowerarm_R:下腕
        │    ├lowerarm_twist_R
        │    └hand_R:手首
        │     ├thumb01_R:親指
        │     │└thumb02_R
        │     │  └thumb03_R
        │     ├index00_R:人差し指
        │     │└index01_R
        │     │  └index02_R
        │     │    └index03_R
        │     ├middle00_R:中指
        │     │└middle01_R
        │     │  └middle02_R
        │     │    └middle03_R
        │     ├ring00_R:薬指
        │     │└ring01_R
        │     │  └ring02_R
        │     │    └ring03_R
        │     └pinky00_R:小指
        │       └pinky01_R
        │         └pinky02_R
        │           └pinky03_R
        └clavicle_L:鎖骨
          └upperarm_L:上腕
            ├upperarm_twist_L
            └lowerarm_L:下腕
              ├lowerarm_twist_L
              └hand_L:手首
                ├thumb01_L:親指
                │└thumb02_L
                │  └thumb03_L
                ├index00_L:人差し指
                │└index01_L
                │  └index02_L
                │    └index03_L
                ├middle00_L:中指
                │└middle01_L
                │  └middle02_L
                │    └middle03_L
                ├ring00_L:薬指
                │└ring01_L
                │  └ring02_L
                │    └ring03_L
                └pinky00_L:小指
                  └pinky01_L
                    └pinky02_L
                      └pinky03_L

面白いことに 親の位置と回転量に影響をうけるものの、子の相対的な回転は子自身の回転量によってのみ決まります。
つまり、肩の位置がどれだけ変わろうが、腕の回転量は影響を受けないということです。

ボーンの回転量はQuaternionという形式の四つの実数のリストによって表現されます。
Quaternion が何であるのかはさておいて、回転を意味する以上はどのポジションからの回転かが重要です。
答えを言えばa-poseを基準とする回転です。
なので、a-pose.jsonはすべての要素が[1.0, 0.0, 0.0, 0.0]、回転なしと定義されています。

さて、ここからが本題なのですが Quaternion で表現する任意の二つの回転量は球面線形補間ができるのです。
つまり二つのポーズの中間のポーズを計算によって求めることができてしまうのです。
実際にやってみましょう。

次のスクリプトをpose_slerp.pyとして保存してください。
スクリプトの意味を理解する必要はとりあえずはありません。

import sys
import json
import numpy
from pyquaternion import Quaternion

if __name__ == '__main__':
    args = sys.argv
    if 2 <= len(args):
        base_pose = args[1]
    else:
        print("no base pose!")
        exit()
    if 3 <= len(args):
        reference_pose = args[2]
    else:
        print("no reference_pose!")
        exit()
    if 4 <= len(args):
        amount = args[3]
    else:
        print("no amount!",args[3])
        exit()
    if 5 <= len(args):
        out_pose = args[4]
    else:
        out_pose = './output.json'

with open(base_pose) as f_b:
    print("Base pose",base_pose, "is loaded")
    df_b = json.load(f_b)

with open(reference_pose) as f_r:
    print("Reference pose",reference_pose, "is loaded")
    df_r = json.load(f_r)

for w in df_b:
    q1 = Quaternion(df_b[w])
    q2 = Quaternion(df_r[w])
    q3 = Quaternion.slerp(q1, q2, float(amount))
    df_b[w] = q3.elements.tolist()

f_out = open(out_pose, 'w')
f_out.write(json.dumps(df_b))
print("Output pose file is",out_pose)

pyquaternionというモジュールが必要です。
以下のようにしてインストールしてください。

python -m pip install pyquaternion

同じディレクトリに以下のポーズライブラリファイルを保存します。
 a-pose.json
 shojo_classic01.json

コマンドラインから以下を実行します。

python pose_slerp.py a-pose.json shojo_classic01.json 0.50 output.json

コマンドの意味は以下です。
python <実行スクリプト名> <ベースポーズファイル名> <ターゲットポーズファイル名> <補間の割合> <出力ポーズファイル名>

<補間の割合>は0~1の実数を指定してください。
0.5でちょうど中間の補間となります。

output.jsonという新しいポーズファイルができるので、MB-Labのポーズとしてloadすれば、生成したポーズを読み込むことができます。
次のアニメーションは0.00~1.00まで0.05刻みで変化させ、一枚ずつMB-Labに読み込ませたものです。

いかがでしょうか?
任意の二つのポーズから、二つのポーズを補完する新しいポーズを生成できるのです。
MB-Labにはたくさんの魅力的なポーズが用意されています。
※ただしfemaleに限る
更に新しく作ったポーズと別のポーズを組み合わせることも可能。
つまり組み合わせは無限。
「あのポーズとこのポーズを組み合わせれば」と夢が膨らむと思いませんか?

とはいえ、これでも自作小説に挿絵を欲する諸兄姉には満足いただけないかもしれません。
「ポーズは分かった。でも手が思うようにポージングできない」
「手指のボーンって、なにげに全体の半分以上あって収取つかないんですけれど」
そう思われるでしょう。

ごもっともです。
体のポーズに引きずられて、手を思うように変形させることができません。
手のポーズが思い通りにならないのは困ります。
手は口ほどにものをいうのですから。
指差し、ピース、サムアップ、ブーイング、グー、チョキ、パー。
フレミングの左手の法則。
シーンに応じて手のポーズを付けなければなりませんよね?

大丈夫です。
ソリューションを用意してあります。
Quaternion では部分の差し替えができるのです。
任意のポーズの任意のボーンだけの回転量を移植できるのです。
手はHand_R,Hand_Lを親とする一連のボーンツリーで構成されています。
よって他のポーズファイルの手の構成を移植することができます。
実際にやってみましょう。

次のスクリプトをpose_copy_hands.pyとして保存してください。
スクリプトの意味を理解する必要はとりあえずはありません。
ただすごくベタなスクリプトなので逆になにをやっているかは想像できると思います。

import sys
import json

if __name__ == '__main__':
    args = sys.argv
    if 2 <= len(args):
        base_pose = args[1]
    else:
        print("no base pose!")
        exit()
    if 3 <= len(args):
        reference_pose = args[2]
    else:
        print("no reference_pose!")
        exit()
    if 4 <= len(args):
        out_pose = args[3]
    else:
        out_pose = './output.json'

with open(base_pose) as f_b:
    print("Base pose",base_pose, "is loaded")
    df_b = json.load(f_b)

with open(reference_pose) as f_r:
    print("Reference pose",reference_pose, "is loaded")
    df_r = json.load(f_r)

df_b['hand_R']      = df_r['hand_R']      
df_b['thumb01_R']   = df_r['thumb01_R']   
df_b['thumb02_R']   = df_r['thumb02_R']   
df_b['thumb03_R']   = df_r['thumb03_R']   
df_b['index00_R']   = df_r['index00_R']   
df_b['index01_R']   = df_r['index01_R']   
df_b['index02_R']   = df_r['index02_R']   
df_b['index03_R']   = df_r['index03_R']   
df_b['middle00_R']  = df_r['middle00_R']  
df_b['middle01_R']  = df_r['middle01_R']  
df_b['middle02_R']  = df_r['middle02_R']  
df_b['middle03_R']  = df_r['middle03_R']  
df_b['ring00_R']    = df_r['ring00_R']    
df_b['ring01_R']    = df_r['ring01_R']    
df_b['ring02_R']    = df_r['ring02_R']    
df_b['ring03_R']    = df_r['ring03_R']    
df_b['pinky00_R']   = df_r['pinky00_R']   
df_b['pinky01_R']   = df_r['pinky01_R']   
df_b['pinky02_R']   = df_r['pinky02_R']   
df_b['pinky03_R']   = df_r['pinky03_R']   

df_b['hand_L']      = df_r['hand_L']      
df_b['thumb01_L']   = df_r['thumb01_L']   
df_b['thumb02_L']   = df_r['thumb02_L']   
df_b['thumb03_L']   = df_r['thumb03_L']   
df_b['index00_L']   = df_r['index00_L']   
df_b['index01_L']   = df_r['index01_L']   
df_b['index02_L']   = df_r['index02_L']   
df_b['index03_L']   = df_r['index03_L']   
df_b['middle00_L']  = df_r['middle00_L']  
df_b['middle01_L']  = df_r['middle01_L']  
df_b['middle02_L']  = df_r['middle02_L']  
df_b['middle03_L']  = df_r['middle03_L']  
df_b['ring00_L']    = df_r['ring00_L']    
df_b['ring01_L']    = df_r['ring01_L']    
df_b['ring02_L']    = df_r['ring02_L']    
df_b['ring03_L']    = df_r['ring03_L']    
df_b['pinky00_L']   = df_r['pinky00_L']   
df_b['pinky01_L']   = df_r['pinky01_L']   
df_b['pinky02_L']   = df_r['pinky02_L']   
df_b['pinky03_L']   = df_r['pinky03_L']   

f_out = open('out_pose', 'w')
f_out.write(json.dumps(df_b))

コマンドラインから以下を実行します。

python pose_copy_hands.py a-pose.json shojo_classic01.json output.json

コマンドの意味は以下です。
python <実行スクリプト名> <ベースポーズファイル名> <手のポーズを取り込むポーズファイル名> <出力ポーズファイル名>

出力結果ファイル output.json を MB-Labの少女キャラクターに読み込むと以下のようになります。

a-poseにshojo_classic01の手のポーズが移植されました。
つまり体のポーズを仕上げたあと、手のポーズだけを目的のポーズに差し替えることができるのです。
スクリプトを改造すれば右手だけ、もしくは左手だけ、もしくは人差し指だけというように任意の部位を差し替えることができるので応用が利きます。

ついでに右手のポーズを左手に移植、またはその逆を行う例を紹介しましょう。
次のスクリプトをpose_copy_hand_one2other.pyとして保存してください。
スクリプトの意味を理解する必要はとりあえずはありません。
ただこのスクリプトもベタです。
諸兄姉は何を行っているのか推測できるでしょう。

import sys
import json

if __name__ == '__main__':
    args = sys.argv
    if 2 <= len(args):
        base_pose = args[1]
    else:
        print("no base pose!")
        exit()
    if 3 <= len(args):
        print(args[2])
        if ((args[2] != 'l2r') and (args[2] != 'r2l')):
            print("sub-command must be l2r or r2l") 
            exit()

    if 4 <= len(args):
        out_pose = args[3]
    else:
        out_pose = './output.json'

def x_axis_mirrord(a):
    b = a[:]
    b[2] *= -1.0
    b[3] *= -1.0
    return(b[:])

with open(base_pose) as f:
    print("Base pose",base_pose, "is loaded")
    df = json.load(f)

if (args[2] == 'l2r'):
    df['hand_R']     = x_axis_mirrord(df['hand_L'])
    df['thumb01_R']  = x_axis_mirrord(df['thumb01_L'])
    df['thumb02_R']  = x_axis_mirrord(df['thumb02_L'])
    df['thumb03_R']  = x_axis_mirrord(df['thumb03_L'])
    df['index00_R']  = x_axis_mirrord(df['index00_L'])
    df['index01_R']  = x_axis_mirrord(df['index01_L'])
    df['index02_R']  = x_axis_mirrord(df['index02_L'])
    df['index03_R']  = x_axis_mirrord(df['index03_L'])
    df['middle00_R'] = x_axis_mirrord(df['middle00_L'])
    df['middle01_R'] = x_axis_mirrord(df['middle01_L'])
    df['middle02_R'] = x_axis_mirrord(df['middle02_L'])
    df['middle03_R'] = x_axis_mirrord(df['middle03_L'])
    df['ring00_R']   = x_axis_mirrord(df['ring00_L'])
    df['ring01_R']   = x_axis_mirrord(df['ring01_L'])
    df['ring02_R']   = x_axis_mirrord(df['ring02_L'])
    df['ring03_R']   = x_axis_mirrord(df['ring03_L'])
    df['pinky00_R']  = x_axis_mirrord(df['pinky00_L'])
    df['pinky01_R']  = x_axis_mirrord(df['pinky01_L'])
    df['pinky02_R']  = x_axis_mirrord(df['pinky02_L'])
    df['pinky03_R']  = x_axis_mirrord(df['pinky03_L'])
else :
    df['hand_L']     = x_axis_mirrord(df['hand_R'])
    df['thumb01_L']  = x_axis_mirrord(df['thumb01_R'])
    df['thumb02_L']  = x_axis_mirrord(df['thumb02_R'])
    df['thumb03_L']  = x_axis_mirrord(df['thumb03_R'])
    df['index00_L']  = x_axis_mirrord(df['index00_R'])
    df['index01_L']  = x_axis_mirrord(df['index01_R'])
    df['index02_L']  = x_axis_mirrord(df['index02_R'])
    df['index03_L']  = x_axis_mirrord(df['index03_R'])
    df['middle00_L'] = x_axis_mirrord(df['middle00_R'])
    df['middle01_L'] = x_axis_mirrord(df['middle01_R'])
    df['middle02_L'] = x_axis_mirrord(df['middle02_R'])
    df['middle03_L'] = x_axis_mirrord(df['middle03_R'])
    df['ring00_L']   = x_axis_mirrord(df['ring00_R'])
    df['ring01_L']   = x_axis_mirrord(df['ring01_R'])
    df['ring02_L']   = x_axis_mirrord(df['ring02_R'])
    df['ring03_L']   = x_axis_mirrord(df['ring03_R'])
    df['pinky00_L']  = x_axis_mirrord(df['pinky00_R'])
    df['pinky01_L']  = x_axis_mirrord(df['pinky01_R'])
    df['pinky02_L']  = x_axis_mirrord(df['pinky02_R'])
    df['pinky03_L']  = x_axis_mirrord(df['pinky03_R'])

f_out = open(out_pose, 'w')
f_out.write(json.dumps(df))
print("Output file is",out_pose)

コマンドラインから以下を実行します。

python pose_copy_hand_one2other.py output.json l2r output2.json

これは上で生成したoutput.jsonを入力に左手のポーズを右手にコピーし、output2.jsonとしてポーズファイルを生成します。
MB-Labの少女キャラクターにoutput2.jsonを読み込んでみましょう。

手にご注目ください。
左手のポーズが右手に移植されていることが分かります。
同様に以下を実行してください。

python pose_copy_hand_one2other.py output.json r2l output3.json

これは上で生成したoutput.jsonを入力に右手のポーズを左手にコピーし、output3.jsonとしてポーズファイルを生成します。
output3.jsonを読み込んでみましょう。

期待通りの結果となっています。
いかがでしょうか?
まったくキャラクターのポーズ編集なしで、かなり思い通りのポーズをとらせることができることをご理解いただけましたでしょうか?
後は自分なりのポーズライブラリを蓄積してゆけばよいわけです。
無論Blenderでのポーズ編集ができるようになればもっと自由度が増すでしょう。
微調整を行うのはそれほど難しいことではないので、どんどんとチャレンジしてください。

今回の記事はMB-Labの説明ではないばかりか、Blenderの機能ですらありませんでした。
MB-Labのデーターファイルはどれも取り扱いやすいjson形式となっています。
だからスクリプトで変化させることができてしまうのです。

実際にデーターファイルを弄るためにはスクリプト言語の知識が必要だったりしますので、その実ポーズの編集を覚えるのとどちらが早いかは微妙なところもあります。
しかし、苦労したポーズは取っておいて、ライブラリ化すると良いと思います。

今回はこれで終わりです。
時間があれば[その9]を書きたいと思います。



黒灰色の魔女と時の魔女 第五章第三話(九)更新しています


黒灰色(こっかいしょく)の魔女と時の魔女』、『第五章第三話(九)君、山登れ』更新しています。
砂漠に子供二人、赤ん坊付きでおっぽり出されて、頼れるのは怪しげな砂漠の声だけというシチュエーション。
読んで下さいね。

絵はマリアの幼少期です。
流石にこれ以上は誰も死なないはず。
マリアって将来的には二児の母ですし。

で背景はWord Cloudです。
twitterとかで小説の宣伝画像を作りたいなと思うじゃないですか?
でも絵を作るってメンドクサイですよね?
そんな時にWord Cloudですよ。
私もtwitterを始めたばかりの時はWord Cloud一本で宣伝絵を作っていました。

Word Cloudとは切り出した単語や文章を、重要なものを大きく、そうでもないものを小さく表示して、画面全体を埋める表現手法です。
どのようなキーワードが流行しているかを見える化するツールなわけです。
我々小説家になろうに投稿するものは、小説のキーワードやインパクトのあるフレーズを表示させると良いんじゃないかと思うわけです。

作り方は色々あるのですけれど、お勧めはPython3でword_cloudを使う方法です。

Pythonはスクリプト言語です。
Python3は現状最新版のPythonです。
Python2もまだ現役ですが日本語の取り扱い等でPython3は進化しています。
WINDOWS10 PCへのインストールは「このサイト」を参照してください。
Python3のインストール

環境変数等も設定してDOS窓からPythonが実行できるようにしてください。
DOS窓から

python --version

と打つとマイクロソフトストアが立ち上がってトホホとなる場合は「ここ」を見ると幸せになれるかもしれません。
windowsでpython3を実行するとストアが開く

world_cloudはPython3のモジュールです。
前提となるモジュールがあるのでいくつかDOS窓でインストールを行います。
具体的には以下をDOS窓で実行します。

python get-pip.py 
python -m pip install --upgrade pip
python -m pip install matplotlib
python -m pip install numpy
python -m pip install pillow
python -m pip install wordcloud

pipというのはPythonのモジュールを取得するためのスクリプトです。
pipを使うことにより様々なモジュールをインストールすることができます。
matplotlibと numpy は数値演算系のモジュールで、Pythonプログラマは皆お世話になっているものです。
pillow はPythonの画像系のモジュールでお絵かきする人は知っておいた方が良いモジュールです。
Pythonインストール時、インストールディレクトリとその下のScriptsフォルダにパスを通しておいてください。
例えばC:\Python37にインストールしたのなら以下を環境変数PATHに追加します。

C:\Python37
C:\Python37\Scripts

Pythonのモジュールと言いましたが、word_cloudを使う上ではPythonは単なるプラットフォームで意識する必要はありません。
実際に使うのはword_cloud_cli.exeというコマンドです。
以下のコマンドが実行できるか確かめてください。

c:\work>wordcloud_cli --help
usage: wordcloud_cli [-h] [--text file] [--regexp regexp] [--stopwords file]
                     [--imagefile file] [--fontfile path] [--mask file]
                     [--colormask file] [--contour_width width]
                     [--contour_color color] [--relative_scaling rs]
                     [--margin width] [--width width] [--height height]
                     [--color color] [--background color] [--no_collocations]
                     [--version]

A simple command line interface for wordcloud module.

optional arguments:
  -h, --help            show this help message and exit
  --text file           specify file of words to build the word cloud
                        (default: stdin)
  --regexp regexp       override the regular expression defining what
                        constitutes a word
  --stopwords file      specify file of stopwords (containing one word per
                        line) to remove from the given text after parsing
  --imagefile file      file the completed PNG image should be written to
                        (default: stdout)
  --fontfile path       path to font file you wish to use (default:
                        DroidSansMono)
  --mask file           mask to use for the image form
  --colormask file      color mask to use for image coloring
  --contour_width width
                        if greater than 0, draw mask contour (default: 0)
  --contour_color color
                        use given color as mask contour color - accepts any
                        value from PIL.ImageColor.getcolor
  --relative_scaling rs
                        scaling of words by frequency (0 - 1)
  --margin width        spacing to leave around words
  --width width         define output image width
  --height height       define output image height
  --color color         use given color as coloring for the image - accepts
                        any value from PIL.ImageColor.getcolor
  --background color    use given color as background color for the image -
                        accepts any value from PIL.ImageColor.getcolor
  --no_collocations     do not add collocations (bigrams) to word cloud
                        (default: add unigrams and bigrams)
  --version             show program's version number and exit

c:\work>

作業はc:\workで行うこととします。
必要になるのは以下。
・wordテキストファイル。
表示するキーワードを格納するファイルです。
半角スペースもしくは改行で区切ります。
抜粋ですが以下のような感じです。

黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
黒灰色の魔女と時の魔女
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第五章:傍に居てよ
第三話:ずっときみを見守っていたんだ
第三話:ずっときみを見守っていたんだ
第三話:ずっときみを見守っていたんだ
第三話:ずっときみを見守っていたんだ
第三話:ずっときみを見守っていたんだ
第三話:ずっときみを見守っていたんだ
第三話:ずっときみを見守っていたんだ
(九)君、山登れ
(九)君、山登れ
(九)君、山登れ
(九)君、山登れ
(九)君、山登れ
(九)君、山登れ
(九)君、山登れ
マリア
マリア
マリア
マリア
マリア
マリア
マリア
マリア
マリア
マリア
リリィ
リリィ
リリィ
リリィ
リリィ
リリィ
ヨシュア
ヨシュア
ヨシュア
ヨシュア
ヨシュア
ヨシュア
ヨシュア
ヨシュア
ヨシュア
齧りながら
頷く
頷く
呟きながら
麓
緑
稜線
稜線
了解
立ったまま
立ち上がる
立ち上がる

このファイルをC:\work\input.txtとして保存します。
漢字コードはUTF-8を選択します。
数が多いキーワードは大きくなります。
なので数で調整してください。

後、漢字をサポートしているフォントファイルを指定します。
C:\Windows\Fonts\ にある適当なフォントを選択します。
気に入っているフォントがあればそれを指定しても構いません。
私は大好きな「装甲明朝」を使います。
DOS窓で以下のように実行してください。

wordcloud_cli --width 1920 --height 1080 --text input.txt --fontfile C:\Windows\Fonts\SoukouMincho.ttf --no_collocations --imagefile planetext.png

planetext.pngが生成されます。
以下のような感じになります。

マスク画像を指定して文字のある部分と無い部分を作ることもできます。
例えば以下のような画像ファイルを用意します。
image_mask.png

黒の部分に文字が入り、白の部分はマスクされます。
DOS窓で以下のように実行してください。

wordcloud_cli --width 1920 --height 1080 --text input.txt --fontfile C:\Windows\Fonts\SoukouMincho.ttf --no_collocations --mask image_mask.png --imagefile text_w_mask.png

text_w_mask.png が生成されます。

マスクされました。
フォントの色を指定することもできます。
例えば赤を指定したければ以下のようにします。

wordcloud_cli --width 1920 --height 1080 --text input.txt --fontfile C:\Windows\Fonts\SoukouMincho.ttf --no_collocations --mask image_mask.png --color red --imagefile text_w_mask_red.png

カラーマスク画像を使って色調を管理することもできます。
どんな画像でも良いのですがグラデーションやノイズ交じりのものが良いと思います。
例えば次のような画像を用意します。
cmask2.png

DOS窓で以下のように実行してください。

wordcloud_cli --width 1920 --height 1080 --text input.txt --fontfile C:\Windows\Fonts\SoukouMincho.ttf --no_collocations --mask image_mask.png --colormask cmask2.png --imagefile text_w_mask_cmask.png

以下のような画像が生成されます。

後は画像を合成すれば完成です。

いかがでしょうか?
twitter用の画像として手軽で良いと思いませんか?

絵で困ったときはword_cloudの存在を思い出してあげてくださいね。


挿絵画家になろう(その7)


「挿絵画家になろう(その7)」です。
Blenderのアドオン、MB-Labの啓蒙です。
前回までで、MB-Labを使って少女キャラクターを生成し、VRoidStudioの髪をインポートして装着させ、そこそこの服を着せ、キャラクターのマテリアルも弄れるようになり、更に表情も変更できるようになりました。
今回もMB-Labの使い方に関して説明を試みたいと思います。
今回は表情の変更の続きです。

前回、MB-Labで表情を変更する方法にMB-Labが用意する[FACE EXPRESSIONS]を使う方法とシェイプキーを直接変更する方法があることを述べました。
[FACE EXPRESSIONS]は複数のシェイプキーのセットを持っていて、シェイプキーを同時に変化させる機能です。
表情は目や口、頬、眉などの組み合わせで表現されます。
MB-Labの考え方として、シェイプキーで個々のパーツの変化を用意し、シェイプキーの組み合わせを [FACE EXPRESSIONS] で用意してセットで変更できるようにしているわけです。

[FACE EXPRESSIONS] で用意されている表情で事足りるのならば [FACE EXPRESSIONS] のみを使うことが簡便です。
しかし [FACE EXPRESSIONS] で満足できない場合は、次の手段としてシェイプキー単体を変更すれば良いわけです。
勿論、シェイプキーは抽象度が下がるわけですから必要な組み合わせを自分で決めて全てコントロールする必要があります。
しかし抽象度が低いということは自由度が高いということなのでよりきめ細かい表情を作ることができます。

シェイプキーはプロパティウインドウのオブジェクトデータ(逆三角形のマーク)から見ることができます。
girl1_bodyのオブジェクトが選択されていることを確認してから、編集モードに切り替えます。
プロパティウインドウのオブジェクトデータ を選択し、[シェイプキー]の項目を見てください。
たくさんのシェイプキーが用意されていることが分かります。

シェイプキーのリストの下に[シェイプキーを編集モードで表示(メッシュのみ)]というボタンがあるので押下します。
これを押すとメッシュの変更ができなくなる代わりに、選択したシェイプキーのメッシュ変化を見ることができます。
前部のシェイプキーの変化をアニメーションにしてみました。

かなり細かい変化に関して作りこまれていることがわかります。
これらを組み合わせれば微妙な表情も表現できるのではないでしょうか?
尚シェイプキーは表情にだけ使うものではありません。
呼吸による胸の上下や嚥下による喉の変化など、細かい演出に用いられると思われるものも用意されています。

これでほぼ表情の作成は問題なくなったといえます。
凄いですねMB-Lab。
口を大きく開けた場合での歯が気になりますが、私たちの目的は小説の挿絵です。
それほど口を大きく開けたシーンは必要ないと思われますのであまり問題にはならないのではないでしょうか?

とはいえ、どうしてもなんとかしたい場合はシェイプキーのメッシュを弄ってしまえば解決はします。
実際にやってみましょう。

先ずは邪魔な髪と服を不可視にします。
オブジェクトモードにしてSendagaya_Shino_Hairを右クリックで選択し、3Dビューのプレーンにマウスカーソルを置いて[h]キーを押すと髪が不可視状態になります。

同様にOnepiece_Placeを選択し[h]キーで拭くを不可視にします。

girl1_bodyを選択して編集しやすいようにズームします。

編集モードに切り替えます。
[3Dビューのシェーディング]はソリッドにします。
プロパティウインドウのオブジェクトデータ を選択し、[シェイプキー]の項目のリストから[Basis]を選択してください。

シェイプキーのリストの下、[シェイプキーを編集モードで表示(メッシュのみ)]というボタンが解除されていることを確認します。

顔の上にマウスカーソルを当てて[a]キーを何回か押し、何も選択されていない状態にしてください。

顔の額あたりにマウスカーソルを当てて、[l]キーを押すと顔のメッシュが選択されます。
今回は歯のメッシュを弄るので顔は邪魔なので不可視化する意図です。

[h]キーを押下すると顔の表面が不可視になり顔の中身が剥き出しになります。

あとは目的の歯や歯茎のメッシュを編集すれば良いことになります。
注意しなければならないのは頂点の位置は変えても良いのですが、メッシュのトポロジー(頂点同士の繋がり)は変えるべきではないということです。
特に頂点を増やしたり減らしたりするとシェイプキーが意図しない変化となります。
またUVマップとの相関がとれなくなることも避けなければなりません。

編集しやすいように歯をズームします。

上の図の3Dカーソルがあるあたり(上下の歯の合わせ目左にある赤と白の丸)を[alt]キーを押しながら右クリックします。


上の歯の歯並びの選択が選択されます。

メッシュの操作ですが、Z方向(上下方向)のみの変更にとどめます。
理由は他の方向に動かすと収拾がつかなくなるからです。
変化量もキーボードで[↑]キー、[↓]キーの回数で管理し、必要最小限の変化になるよう管理します。
では実際にメッシュを弄ります。

マウスカーソルを歯茎に合わせた状態で[g]、[z]の順番でキー押下します。
選択頂点の上下移動となりますので[↑]キーを5回程度押して移動させます。
[enter]キーを押すと移動が確定します。

今度は範囲を広げます。
[ctrl]キーを押しながらテンキーの[+]キーを押します。
選択範囲が広がります。

マウスカーソルを歯茎に合わせた状態で[g]、[z]の順番でキー押下します。
選択頂点の上下移動となりますので[↑]キーを12回程度押して移動させます。
[enter]キーで移動が確定します。

同様の手順を繰り返し、上の歯を短くしてゆきます。

下の歯の歯並びの最上段が見えてきました。
下の歯の最上段のエッジを[alt]を押しながら右クリックして選択します。

下の歯は臼歯の上部が平たいので範囲を広げます。
[ctrl]キーを押しながらテンキーの[+]キーを押します。

マウスカーソルを歯茎に合わせた状態で[g]、[z]の順番でキー押下します。
選択頂点の上下移動となりますので[↓]キーを12回程度押して移動させます。
[enter]キーで移動が確定します。

同様にして範囲を広げ、歯を短くしてゆきます。

奥歯のエッジが残っているので選択します。

[g]キー、[z]キーを順番に押し、[↓]キーで見えなくなるまで下げます。

どこまで拘るのかによりますが、これまでの操作で歯を喰いしばる系以外のシェイプキーは歯の影響が緩和されることになります。
すこし見てみましょう。
不可視にしたメッシュやオブジェクトは[alt]+[h]で可視化させることができます。

Expressions_mouthOpenLarge_maxを0.5にした表情です。
歯が目立たなくなっています。

歯を喰いしばる系のシェイプキーは明らかに意図的に歯を強調しているものです。
アニメ的な表情表現では「い」行の発音の時に使うくらいでその他ではあまり用途がないでしょう。

上はExpressions_mouthSmileOpen_maxを0.5にした表情です。
シーンによっては使えるかもしれません。

アニメ的な表現では歯、特に下の歯は無い方が良いかもしれません。
そのような場合は設定するマテリアルを透明にすると実現できます。
下の歯だけを透明にするのは下の歯だけを頂点選択してマテリアルを設定します。

透明化の例として下睫毛を見えなくする方法を紹介しましょう。
アニメ的な表情表現では上睫毛は濃い色にして目の輪郭をはっきりさせ、下睫毛は省略して柔らかな表情になることを期待することが多いと思います。
しかしMB-Labでは眉毛、上睫毛、下睫毛がセットになっています。
下睫毛だけを透明化させます。

編集モードに切り替えます。
[3Dビューのシェーディング]はソリッドにします。
顔の上にマウスカーソルを当てて[a]キーを何回か押し、何も選択されていない状態にしてください。

右目の下睫毛にカーソルを当てて[l]キーを押します。
右の睫毛が選択されます。

同様に左目の下睫毛にカーソルを当てて[l]キーを押します。

右の睫両目の下睫毛が選択されました。

プロパティシェルフの[マテリアル]を選択します。

マテリアルスロットの右にある[+]ボタンをクリックして新しいマテリアルスロットを作成します。

マテリアルスロットの右にある[△]ボタンで新しいマテリアルスロットを一番上まで持ち上げます。

マテリアルの選択のセレクタにある[+]ボタンをクリックして新しいマテリアルを作成します。

[サーフェス]の項のセレクタから[透過BSDF]を選択します。

[サーフェス]の項、[カラー]の色部分をクリックするとカラーサークルが現れるので、完全な白にします。

割り当てをクリックして確定させます。

これで下睫毛に透明なマテリアルが設定されました。

いかがでしょうか?
下睫毛が消えたことによりかなり柔らかい表情になったことと思われます。

ポーズと表情をつけてレンダリングしてみました。

今回の記事はMB-Labの説明というよりはMB-Labで生成したキャラクターをBlenderの機能でどう弄るかの説明でした。
このようにMB-Labで生成したキャラクターは自由に弄ることができます。

ここまでMB-Labについて説明してきましたが、いかに素晴らしいものであるかお伝えできたでしょうか?
MB-Labはまだまだたくさんの機能がありますが、正直私は良く分かっていません。
しかし、ここまでの知識でだいたいのことはできると思います。
この一連の記事をご覧になって自作小説の挿絵を描かれる方が現れると幸甚です。

今回はこれで終わりです。
MB-Labを主題にするのは今回が最後だと思います。
時間があれば[その8]を書きたいと思います。


挿絵画家になろう(その6)


「挿絵画家になろう(その6)」です。
Blenderのアドオン、MB-Labの啓蒙です。
前回までで、MB-Labを使って少女キャラクターを生成し、VRoidStudioの髪をインポートして装着させ、そこそこの服を着せ、キャラクターのマテリアルも弄れるようになりました。
今回もMB-Labの使い方に関して説明を試みたいと思います。
今回は表情の変更です。

一般論として3D人体キャラクターの表情を変えることは非常にメンドクサイ仕事です。
特に私が求める絵作りはセルルックなアニメ調のものです。
アニメ的な表現文法でよくあるものは3Dと相性の悪いものも多く、3Dツールでの実現に拘るのは私たち素人にとってあまり良い選択ではないかもしれません。
私たち「小説家になろう」作家が求めているのは3Dアニメーションではなく挿絵です。
ある程度品質の良い3Dキャラクターを入手できたのならば、ポーズを変えてレンダリングし、後は2Dペイント系のツールで表情を書き換えるのが早くて簡単な良い方法だと私などは考えます。

とはいえ、MB-Labは優れた人体3D人体キャラクター生成のソリューションです。
当然キャラクターの表情を変える手段を用意してくれています。
しかも非常に使い勝手の良いものです。
MB-Labでどこまで表情がいじれるか知ることは重要です。
そして何ができるのか? 何ができないのか? を知り、自分の作品に反映させると良いでしょう。

オブジェクトモードであることを確認し、girl1_bodyオブジェクトを選択します。
ツールシェルフの[ManuelBastioneLab]タグ、[FACE EXPRESSIONS]を選択します。

沢山のパラメータが現れます。
このパラメータの一つ一つが表情の選択になります。
半分は発音の音韻に対応するものです。
残りは以下のようなプレフィックスが付いています。

angry: 怒り
annoyed: イライラ
anxious: 心配
attentive: 気配り
bored: 退屈
breathing_in: 息を吸う
breathing_out: 息を吐く
confused: 混乱
crying:泣き
curious: 好奇心
deglutition: 嚥下
disgusted: むかつき
drained: 疲れ
embarrassed: 当惑
evil: 悪い顔
excited: 興奮
flirty: 軽薄
furious: 激怒
grin: にやにや
happy: 幸せ
irritated: 荒れ
lazy: 怠惰
offended: 気分を害した
pain: 痛み
peaceful: 平安
posing: ポーズ
sad: 悲しみ
sarcastic: 皮肉
scared: 怖い
serene: 穏やか
shocked: 衝撃
shy: 内気
sleep: 睡眠
surprise: 驚き
tired: 疲れ
very_sad: 激しい悲しみ
wink: ウィンク

おおお、このパラメータたちを1に振ると、表情が変わるのですね。
試してみましょう

angry01: 怒り

確かに怒っているように見えます。
MB-Labの[FACE EXPRESSIONS]では内部的にBlenderのシェイプキーを用いて表情を変えているようです。
プロパティウインドウのオブジェクトデータ(逆三角形のマーク)の「シェイプキー」が切り替わっているのが確認できます。
変化点は以下。

 Expressions_browSqueezeL_max:1.000
 Expressions_browSqueezeR_max:1.000
 Expressions_browsMidVert_min:1.000
 Expressions_cheekSneerL_max:1.000
 Expressions_cheekSneerR_max:1.000
 Expressions_mouthOpenAggr_min:0.560

眉が吊り上がっているところが良いですね。

annoyed01: イライラ

イライラというほどでもないような……。
口が丁度「え」の発音くらいに開いています。

 Expressions_browOutVertR_max:0.660
 Expressions_browSqueezeL_max:0.960
 Expressions_browsMidVert_min:0.360
 Expressions_eyesVert_max:0.600
 Expressions_jawHoriz_max:0.120
 Expressions_mouthOpenO_max:0.360

anxious01: 心配

かなり複雑な表情です。
右唇を噛んでいる演出ですね。

 Expressions_browOutVertL_min:0.300
 Expressions_browOutVertR_min:0.240
 Expressions_browSqueezeL_max:0.760
 Expressions_browSqueezeR_max:0.420
 Expressions_browsMidVert_max:0.300
 Expressions_eyeClosedL_max:0.300
 Expressions_eyeClosedR_max:0.300
 Expressions_eyesHoriz_min:0.480
 Expressions_eyesVert_min:0.540
 Expressions_mouthBite_min:1.000

bored01: 退屈

退屈というよりはブーイングの表情でしょうか?
文字通りの膨れっ面。

 Expressions_browOutVertL_max:0.780
 Expressions_browOutVertR_max:0.720
 Expressions_browsMidVert_max:0.840
 Expressions_eyeClosedL_min:0.720
 Expressions_eyeClosedR_min:0.540
 Expressions_mouthInflated_max:1.000
 Expressions_mouthOpenO_min:0.480

confused02: 混乱

混乱? 迷いという感じですね。

 Expressions_browSqueezeL_max:1.00
 Expressions_browSqueezeR_max:0.960
 Expressions_browsMidVert_max:0.960
 Expressions_cheekSneerL_max:0.360
 Expressions_eyeClosedPressureL_max:0.060
 Expressions_eyeClosedR_max:0.060
 Expressions_eyeSquintL_max:0.180
 Expressions_eyeSquintR_max:0.120
 Expressions_eyesHoriz_max:0.900
 Expressions_mouthClosed_min:0.780
 Expressions_mouthSmileL_max:0.120

crying01:泣き

目を閉じている演出です。
眉と口を合わせて初めて泣き顔に見えます。

 Expressions_browOutVertL_min:0.360
 Expressions_browOutVertR_min:1.000
 Expressions_browSqueezeL_max:1.000
 Expressions_browSqueezeR_max:1.000
 Expressions_browsMidVert_max:1.000
 Expressions_eyeClosedL_max:0.200
 Expressions_eyeClosedPressureL_max:0.420
 Expressions_eyeClosedPressureR_max:0.420
 Expressions_eyeClosedR_max:0.180
 Expressions_eyeSquintL_max:0.120
 Expressions_eyeSquintR_max:0.120
 Expressions_eyesHoriz_min:0.420
 Expressions_eyesVert_min:0.420
 Expressions_mouthBite_min:0.360
 Expressions_mouthOpen_min:0.180

以下は巻きで紹介しますね。

crying02:泣き

disgusted: むかつき

drained01:疲れ

embarrassed01:当惑

evil01:悪い顔

evil02:悪い顔

excited01:興奮

eyes_rot_down:目を下に

eyes_rot_left:目を左に

eyes_rot_right:目を右に

eyes_rot_up:目を上に

flirty01:軽薄

furious01:激怒

furious03:激怒

grin01:にやにや

happy01:幸せ

irritated01:荒廃

kiss01:キス

lazy01:怠惰

offended01:気分を害した

pain01:痛み

peaceful01:平安

posing01:ポーズ

sad01:悲しみ

sad02:悲しみ

sarcastic01:皮肉

scared01:怖い

serene01:穏やか

shoked01:衝撃

shy01:内気

sleep01:眠り

surprise01:驚き

surprise02:驚き

surprise03:驚き

tired01:疲れ

very_sad01:激しい悲しみ

wink01:ウインク

如何でしょうか?
お気に入りの表情に巡り合えたでしょうか?
私の個人的な好みでは口を閉じている表情は良いものが多いです。
ただ、口を大きく開けている表情は多分このままでは使うことは無いでしょう。
目を閉じている表情でも、笑っている場合はもっと上弦の月のようになるように頬を持ち上げるのが漫画的表情表現なのですが、そのような表情はありません。
笑っている口は下向きのかまぼこのような半円を期待するのですが、それもないのです。
MB-Labの表情はphotorealisticな絵作り用で漫画的表現向けではないのでしょう。

ということで、「小説家になろう」として挿絵を考える場合は、ある程度表情を作ってレンダリングし、後は好みに合わせて2D系のペイントツールで画像加工すると良いのでは? という提案になります。

ちなみに MB-Labの[FACE EXPRESSIONS]を使わず、シェイプキーを直接変更しても表情は変わります。
注意しなければならないことは、 [FACE EXPRESSIONS] 使って シェイプキー で微調整、といった使い方はうまくいかないことですね。
[FACE EXPRESSIONS] でどのシェイプキーが変わるかを把握して、シェイプキーで改めて表情を作りこむといった方法が良いのではないでしょうか?

本記事、予想外に長くなってしまいました。
本当は別の事を書こうと思っていたのですが辿り着けそうにありません。
いったん切ります。
とはいえ、表情も作れるようになり、「挿絵画家になろう」という目的には近づけたのではないでしょうか?

時間があれば[その7]を書きたいと思います。