パスコンパスの日記

何か色々作るのが好きです

【NT京都(実質)】Maix Bitで顔認識して3つのサーボで扇子を動かすマスク

目次

背景

NT京都(実質)とは

 NT京都2020という電子工作等の展示会のイベントに出展予定でしたが、
昨今の状況でリアルイベントが中止になってしまったため急遽動画投稿という形でオンライン上でイベントを行うことになりました。
詳細は nod(YモードP) (@nod_Y) | Twitterさんのツイートをご参照ください。

動機

 akira_you (@akira_you) | Twitterさんから昨年こんなアナウンスが出ていたので
ぼんやりとウェアラブルで面白いものが作れないかと考えていました。
何も縛りがなく自由に作るのも楽しいですが、ゆるい条件があるのも経験上何かしら面白いアィディアに繋がるケースがあるので好きです。

 また、Maker Faireというイベントでも最近ウェアラブルな展示を持ってゲリラ的に会場を練り歩く「メイカーパレード」というものが行われており、参加してみたいという憧れも後押しし、お面を作ってみたというのが今回の経緯です。
それと本格的(?)な動画編集は初めてだったのですが、とても楽しかったです。
こちらのブログでは動画に載せきれなかった情報を書きたいと思います。

動画

人生初、ニコニコとYouTubeに投稿してみました。 見ていただけたらとても嬉しいです。
※ほぼ一緒なのでどちらかお好きな方でご覧ください。

niconico

YouTube

www.youtube.com

Maix Bit関連

セットアップ

 Firmwareはこの記事を参考に入れました。ありがとうございます。
また、顔認識のモデルもDLしておきます。
IDEは今までm5stickVでも使っていたMaixPyIDEを使いました。

qiita.com

Frimware https://dl.sipeed.com/MAIX/MaixPy/release/master/

Model https://dl.sipeed.com/MAIX/MaixPy/model

プログラム

 こちらの顔認識のサンプルを改造していきます。

https://maixpy.sipeed.com/en/libs/Maix/kpu.html

github.com

クリックすると展開します

import sensor
import image
import lcd
import KPU as kpu

from machine import Timer,PWM   #add
import time #add

tim0 = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM)
tim1 = Timer(Timer.TIMER1, Timer.CHANNEL1, mode=Timer.MODE_PWM)
tim2 = Timer(Timer.TIMER2, Timer.CHANNEL2, mode=Timer.MODE_PWM)

ch0 = PWM(tim0, freq = 50, duty = 5, pin = 6)
ch1 = PWM(tim1, freq = 50, duty = 5, pin = 7)
ch2 = PWM(tim2, freq = 50, duty = 5, pin = 8)


d0_count = 0
d1_count = 0
d2_count = 0


duty0 = 5
duty1 = 5
duty2 = 5

lcd.init()
lcd.rotation(2) #add

sensor.reset()

sensor.set_hmirror(0)   #add

sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
#task = kpu.load(0x300000) # you need put model(face.kfpkg) in flash at address 0x300000
task = kpu.load("/sd/facedetect.kmodel")
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)

print(lcd.width())  #320 x
print(lcd.height()) #240 y

def ChangeDuty(duty_count):
    if duty_count > 0: #and duty_count < 1000:
        duty_val = 12
    else:
        duty_val = 2.5
    return duty_val


while(True):
    img = sensor.snapshot()
    code = kpu.run_yolo2(task, img)
    if code:
        for i in code:
            #print(i)
            a = img.draw_rectangle(i.rect())
            if i.x() < 80 :
                print("right")
                d0_count += 2
                if d0_count > 10:
                    d0_count = 10

            if i.x() >= 80 and i.x() < 160 :
                print("mid")
                d1_count += 2
                if d1_count > 10:
                    d1_count = 10

            if i.x() >= 160 :
                print("left")
                d2_count += 2
                if d2_count > 10:
                    d2_count = 10

    d0_count -= 1
    if d0_count < 0:
        d0_count = 0
    d1_count -= 1
    if d1_count < 0:
        d1_count = 0
    d2_count -= 1
    if d2_count < 0:
        d2_count = 0


    duty0 =ChangeDuty(d0_count)
    duty1 =ChangeDuty(d1_count)
    duty2 =ChangeDuty(d2_count)
    print(d1_count)

    ch0.duty(duty0)
    ch1.duty(duty1)
    ch2.duty(duty2)

    a = lcd.display(img)
a = kpu.deinit(task)

 SDカードに上記のコードを書き込んだmain.pyとfacedetect.kmodelの拡張子のファイルを保存したため本体のメモリにはアップロードはしていません。 この方法をとる場合のハマりどころですが、上記のface_model_at_0x300000.kfpkgをそのままSDカードに入れるのではなく、face_model_at_0x300000.kfpkgの拡張子をzipに変えて解凍して出てきた.kmodelのファイルを入れることにご注意ください。

サーボの動作に関して

 また、今回気が付いたのですが、今までのキョロキョロVのサーボの動かし方は本来の動かし方と違っていました。

SG-90 PDFデータシート http://akizukidenshi.com/download/ds/towerpro/SG90_a.pdf

 上記データシート本来50Hz固定でduty比を変えることで角度を変えるのですが、周波数を変えてしまっていました。
それでも動いてはいたのですが、dutyを0.025~0.12に変更する方が良さそうです。
昔の記事にも追記予定です。

yoichi-41.hatenablog.com

メカ関連

Adventurer3のノイズ詰まり対応

 動画では触れていませんが、3Dプリンタが不調になってだいぶ苦労しました。
湿気が原因か、コンコンとフィラメントを送るプーリが滑ってしまいノズルの手入れを何度か行いました。
公式FAQにある温度を上げてノズルの中のフィラメントを何度も押す方法と0.25㎜の針金をホームセンターで買ってきて先端から差し込む方法、ラフトの時に特に音がひどかったので厚みを上げたり、スピードを落としたりフィラメントが出やすくする調整を行いました。 f:id:yoichi_41:20200315133922p:plain

機構設計

 最初は紐を使って引く方法も検討していたのですが、煩雑になりそうなので途中でシンプルな方式に変えました。Fusion360でラックを使うのは初めてでしたがアドインを使ったら非常に簡単でした。おすすめです。

okayamalabo.hatenablog.com

f:id:yoichi_41:20200315134810p:plain

最初の試作で扇子の反対側が長いのは扇子を展開後に更に伸ばそうとしていた名残です。
ラックの長さを延長する必要があり、スペースの都合で諦めました。

f:id:yoichi_41:20200315140547p:plain

今は上の画像の真ん中位までで止めています。

ハード(エレキ)関連

 GPIOから信号を引き出して、サーボの電源をバッテリから取るように分けました。
皮膜線を使わない様に実装図は書いてみました。

f:id:yoichi_41:20200315141326j:plain

動画では説明しすぎてもくどいかと思い、ポップな感じで構成図を書いてみました。割と気に入っています。

f:id:yoichi_41:20200320001538p:plain

サーボのUSBからの電源供給はこちらのパーツを使っています。

電源用マイクロUSBコネクタDIP化キット: 組立キット 秋月電子通商-電子部品・ネット通販

動画編集関連

 使ってみたいと思って入れたものの放置してしまっていたBlenderで動画編集もできることを知り、ちょうど良いので試してみました。
以前Aviutlを少しだけ使ったことがあったのですが、そちらに比べるとblenderの動画編集機能Video Editingは日本語の情報が少な目で苦労しました。
実はエンドロール等文字をスクロールするのがきれいにできずに諦めたりしています。

アドオンに関して

デフォルトでは動画のテロップの位置などを画面上でドラッグできないのですが、以下のアドオンを入れるとできるようになります。

github.com

Intro Movieに関して

 Blenderの恩恵を受けられた点は任意の文字列のIntro Movieのテンプレートが大量にあることです。
読み込んで表示したい文字列に書き換えるだけで簡単にIntro Movieが作れます。
曲の使用許可が怪しかったりかっこよすぎたので一部いじりましたがこんなに手軽に作れるというのは衝撃的でした。

topfreeintro.com

レンダリングにノイズが乗ったときはレンダー画面のSamplesの数値を増やしたら解決しました。
Blenderモデリングしたものを今後動かしてみたいです。

BGM作曲

 数年前にゲームを作ってみたいと思い、ペンタブを買ってドット絵を描きDominoというフリーソフトでBGMを作曲してしばらくしてポシャったことがありました。
 今回ふと動画を作るにあたってBGMも自分でつけてみたいと思って作曲(?)してみました。ちなみに私は高校でも美術選択で楽譜も読めず猫ふんじゃったがギリギリ弾けるレベルです。
 その後AIきりたんでも遊んでみたので曲単体の動画をTwitterYouTubeにあげようと思います。

サムネ作成

 動画を見てもらうにはサムネが大事とどこかで聞いたのでニコニコ用とYouTube用にサムネを作ってみました。
f:id:yoichi_41:20200315154607p:plain YouTubeの方とは何となく文化が違うかなと思って微妙に変えています。右下は再生時間が表示されるとのことでスペースを開けておきました。 f:id:yoichi_41:20200315154915p:plain

今後できたら実装したいもの

  • 目を光らせる部分 完成を優先して省略してしまいました。
  • スピーカ Maix Bitにはマイクも載っているので口の部分にスピーカを埋め込みたいです。ロボット声を出したり、逆再生をしたりFFTで何やかんややってみたいですがいかんせん情報が少ないのでできるかは分かりません。

感想

 やはり〆切と出す場が決まっていると作品に対する気持ちの入れ方が全然違うと感じました。
また、動画を投稿する時はブログやTwitterとは比べ物にならない位緊張しました。
Maker Faire Kyoto 2020が中止にならなければメカトロ同好部エルチカの一員として出展予定ですので持っていく予定です。
もしその時「動画で見ました」と言ってもらえたらめちゃくちゃ嬉しいのが今からでも想像できます。 来年のNT京都では被って参加したいなぁと思います。
 かなり長文でしたが、読んでくださりありがとうございました。 当日の感想等は別途書こうと思っています。