3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

スマートスピーカーを写すと「アレクサ」とかしゃべるAIカメラ

Last updated at Posted at 2020-01-04

いま流行りのAIカメラ M5StickVを使って、
スマートスピーカーを画像認識して、ウェイクワードをしゃべらせてみました。

(デモ動画の3番目のはFire HD(amazonタブレット)です。Alexa用に使用しているのでウェイクさせようとしました。出来ていませんが)

Niwatori wake-word speaker
gray__bird_niwatori_chabo.jpg

概要

カメラ画像に対して画像判別を行い、スマートスピーカーと認識されれば、ウェイクワードをスピーカーから再生します。([Open JTalk] (http://open-jtalk.sp.nitech.ac.jp/index.php)を使用して音声ファイルを予め用意しておく)
Google Homeを写すと「OK Google」としゃべり、
Clovaなら「ねえ Clova」、
Fire HD(amazonタブレット)なら「アレクサ」と言います。
M5StickV単体で動作します。

何に役立つかは…とくに考えていませんが、
メガネに組み込んで、「しばらく見つめると、ウェイクワードを代わりに言ってくれる」というのは便利かも?(「アイズフリー(見る必要がない)」という音声UIのメリットを台無しにする使い方ですが)

画像認識や音声読み上げを試したくて作ったものです。

AIカメラ M5StickV

2019年夏ごろに発売された、"AIカメラ"です。いろいろすごくて話題になっています。

  • CNNを高速に実行できる"AIチップ"を搭載
  • カメラ、ディスプレイ、バッテリー、スピーカーなどが一体
  • 基板むき出しじゃなくケース入り
  • たったの3,000円

既にスマホという高性能な"AIカメラ"があるので、スマホには出来ない使い方を考えてみたいですね。

  • 大量に買って、いろんな場所に取り付ける(安いので)
  • 子供(ちびっこ)のおもちゃにする
  • 機器に組み込んだり、建物に固定で設置する

とかでしょうか。

画像認識のモデル

認識対象が一般的なものなら、既にあるモデルをそのまま使えばOKです。
例えば、MobileNet v1の1,000クラスのモデルが公開されています。(https://www.maixhub.com/index.php/index/index/detail/id/2.html たぶんM5StickVでそのまま使える)
しかし、今回の認識対象は、「Google Home」とか、「Clova Friends Sally」とかです。そのようなものは用意されていませんので、自分でモデルをつくる必要があります。
ここが腕の見せ所であり、私のようなAIビギナーのがんばりどころなのですが・・・
**今回は[V-Training] (https://docs.m5stack.com/#/en/related_documents/v-training)というツールを使いました。**今回使用するAIカメラのメーカーが提供しているものです。
認識させたいものそれぞれ35枚ずつ写真を撮ってアップロードすれば、学習済みモデルをつくってくれるというものです。お手軽。
写真はM5StickVを使用して撮影します。撮影時に使うプログラムも用意されていて、とっても簡単です。
AIの開発の敷居がどんどん低くなっていることを感じますね。

コード

V-Trainingを使うと、学習済みモデルとともにそれをM5StickVで動作させるためのコードも送られておきます。
これは、単に認識されたラベルを画面上に表示させる程度のものです。
今回は、そのラベルに応じて読み上げをさせたい。
読み上げの部分は[Brownie] (https://github.com/ksasao/brownie)のコードを参考にさせていただきました。
(そもそも、読み上げさせるというアイデア自体がBrownieの真似のようなものですが)

boot.py
import image
import lcd
import sensor
import sys
import time
import KPU as kpu
from fpioa_manager import *

import KPU as kpu

import audio
import gc
import uos
from machine import I2C
from Maix import I2S, GPIO

lcd.init()
lcd.rotation(2)
i2c = I2C(I2C.I2C0, freq=400000, scl=28, sda=29)

fm.register(board_info.SPK_SD, fm.fpioa.GPIO0)
spk_sd=GPIO(GPIO.GPIO0, GPIO.OUT)
spk_sd.value(1) #Enable the SPK output

fm.register(board_info.SPK_DIN,fm.fpioa.I2S0_OUT_D1)
fm.register(board_info.SPK_BCLK,fm.fpioa.I2S0_SCLK)
fm.register(board_info.SPK_LRCLK,fm.fpioa.I2S0_WS)

wav_dev = I2S(I2S.DEVICE_0)

fm.register(board_info.BUTTON_A, fm.fpioa.GPIO1)
but_a=GPIO(GPIO.GPIO1, GPIO.IN, GPIO.PULL_UP) #PULL_UP is required here!

fm.register(board_info.BUTTON_B, fm.fpioa.GPIO2)
but_b = GPIO(GPIO.GPIO2, GPIO.IN, GPIO.PULL_UP) #PULL_UP is required here!

fm.register(board_info.LED_W, fm.fpioa.GPIO3)
led_w = GPIO(GPIO.GPIO3, GPIO.OUT)
led_w.value(1) #RGBW LEDs are Active Low

fm.register(board_info.LED_R, fm.fpioa.GPIO4)
led_r = GPIO(GPIO.GPIO4, GPIO.OUT)
led_r.value(1) #RGBW LEDs are Active Low

fm.register(board_info.LED_G, fm.fpioa.GPIO5)
led_g = GPIO(GPIO.GPIO5, GPIO.OUT)
led_g.value(1) #RGBW LEDs are Active Low

fm.register(board_info.LED_B, fm.fpioa.GPIO6)
led_b = GPIO(GPIO.GPIO6, GPIO.OUT)
led_b.value(1) #RGBW LEDs are Active Low


def play_sound(filename):
    try:
        player = audio.Audio(path = filename)
        player.volume(100)
        wav_info = player.play_process(wav_dev)
        wav_dev.channel_config(wav_dev.CHANNEL_1, I2S.TRANSMITTER,resolution = I2S.RESOLUTION_16_BIT, align_mode = I2S.STANDARD_MODE)
        wav_dev.set_sample_rate(wav_info[1])
        while True:
            ret = player.play()
            if ret == None:
                break
            elif ret==0:
                break
        player.finish()
    except:
        pass


try:
    from pmu import axp192
    pmu = axp192()
    pmu.enablePMICSleepMode(True)
except:
    pass

try:
    img = image.Image("/sd/startup.jpg")
    lcd.display(img)
except:
    lcd.draw_string(lcd.width()//2-100,lcd.height()//2-4, "Error: Cannot find start.jpg", lcd.WHITE, lcd.RED)


task = kpu.load("/sd/model/vtraining_smartspeakers_1.kmodel")

labels=["G_Home","clove_sally","fire_hd","G_Home_mini"] #You can check the numbers here to real names.

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_windowing((224, 224))
sensor.run(1)

lcd.clear()


# isButtonPressedA = 0

while(True):
    img = sensor.snapshot()
    fmap = kpu.forward(task, img)
    plist=fmap[:]
    pmax=max(plist)
    max_index=plist.index(pmax)
    a = lcd.display(img)
    if pmax > 0.95:
        lcd.draw_string(40, 60, "Accu:%.2f Type:%s"%(pmax, labels[max_index].strip()))
        # if but_a.value() == 0  and isButtonPressedA == 0:
        if but_a.value() == 1:
            play_sound("/sd/voice/ja/"+str(max_index)+".wav")
            # isButtonPressedA = 1
    # if but_a.value() == 1:
    #     isButtonPressedA = 0
a = kpu.deinit(task)

Brownieでは(物体が認識されている状態で)ボタンを押すと読み上げですが、
今回は見つけた瞬間に読み上げとしてみました。
黙らせたいときにはボタンを押します。

課題と今後

スマートスピーカー以外のものを写したときの誤認識が多いです。
ざっくり言うと「とりあえず白ければGoogle Home」、「黄色のはClova Friends Sally」という感じです。
「どのスマートスピーカーでもない」という学習用データを与えていないので当然でしょうか。

やはり学習用データやモデルの工夫が重要そうです。
V-Trainingにおまかせでなく、自分で色々と試してみようと思います。
こちらのcolab notebookが詳しそうです:
Creating an Image Classification Model for M5StickV by Transfer Learning

参考

セットアップなどは、[M5StickVで超お手軽エッジAI画像認識(からあげ様)] (https://karaage.hatenadiary.jp/entry/2019/08/14/073000)が参考になりました。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?