2018年8月27日月曜日

画像処理の演習を Python3 用の OpenCV3 / OpenCV4で実行する方法

0. はじめに

Pythonにはバージョン2 (Python2) とバージョン3 (Python3)の2系統があります。本書のプログラムは、原則的に両方のバージョンで実行できるように記述しています。

しかし、画像処理に用いるライブラリOpenCVだけは、Python2での利用に限定していました。2018年8月の時点の Raspbian Stretch で言えば、Python がバージョン2.7.13、OpenCVはバージョン2.4.9.1でした。

これは、2015年の本書執筆時はPython3でOpenCVを用いる簡単な方法が見つからなかったためです。

しかし、Python3でOpenCVを用いる方法が容易になりつつあることから、Python3で本書のOpenCVを用いたプログラムを実行する方法をここで紹介することにしました。

1. 準備

まず、本書でもインストールしたlibopencv-devをあらかじめインストールしておきます。下記の2つの命令を順に実行します。
sudo apt update
sudo apt install libopencv-dev
なお、このlibopencv-devは顔認識に用いるファイルhaarcascade_frontalface_alt.xmlのためだけにインストールします。

このあとは、用いているOSと利用したいOpenCVのバージョンによりコマンドが分かれます。

2. Rasppbian Buster または Bullseye + Python3 + OpenCV3 の場合

Raspbian Buster または Bullseye をお使いの場合、apt コマンドでインストールできるOpenCV3をインストールするのが最も簡単ですのでお勧めです。

下記のようにOpenCVをインストールします。
sudo apt install python3-opencv
以上で、Python3 用の OpenCV のインストールが終わりました。

2019年6月の時点で、Python3はバージョン3.7.3、OpenCV はバージョン3.2.0となりました。

3. Rasppbian Buster + Python3 + OpenCV4 の場合

Raspbian Busterをお使いの場合、pip3 コマンドでインストールするとOpenCV4がインストールされます。インストール中のネットワークトラブルによるエラーが多いので、上級者向けと考えています。

まず、必要なパッケージをインストールします。
sudo apt install libatlas-base-dev libjasper-dev libqtgui4 libqt4-test
最後に、Python3 用の OpenCV4 をインストールします。
sudo pip3 install opencv-python==4.5.1.48
最後に、以下のコマンドを実行します。それが終わったらRaspberry Piを再起動します。
echo "export LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1" >> ~/.bashrc
以上で、Python3 用の OpenCV4 のインストールが終わりました。

なお、OpenCVのバージョンを 4.5.1.48 に指定している理由は、それ以降 (4.5.3 など) では NumPy の新しいバージョン (1.21 など) を要求されるためです。
NumPy 1.20 以降では、機械学習用のライブラリ TensorFlow 2.x の動作に問題が出る場合があるため、Numpy 1.19 で使える OpenCV 4.5.1.48 を指定しているのです。
TensorFlow 2.x を使わない場合は OpenCV のバージョン指定は不要ですが、利用は自己責任でお願いします。

また、Raspberry Piでのpip(pip3)を用いたツールのインストールは、ネットワークのトラブルにより失敗することが多いようです。例えば、pip(pip3)コマンドを実行したときに下記のような40行程度のエラーが出ることがあります。
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
(中略)
  File "/usr/share/python-wheels/urllib3-1.19.1-py2.py3-none-any.whl/urllib3/util/retry.py", line 315, in increment
    total -= 1
TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'
これは、インストール時のネットワークに問題があるときに出るエラーです。 Raspberry Piがネットワークに接続していないとき、および、ファイルのダウンロード元であるサーバーに問題があるときの両方で上記エラーが出ます。
あるいは、同様のエラーで
THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE.
と出る場合もあります。

Raspberry Piのネットワーク接続に問題がある場合はその改善を試みてください。
一方、先方のサーバーに問題がある場合、時間をあけてからコマンドを再実行すると問題が解消される場合があります。Raspberry Pi上でpipを用いてツールをインストールする場合、サーバー側の問題なのか、何度もインストールを試みて初めてインストールに成功する、ということが多い印象があります。

4. Rasppbian Stretch + Python3 + OpenCV4 の場合

Raspbian Stretch上のPython3でOpenCV4を用いたい場合、以下のようにします。

まず、必要なパッケージをインストールします。
sudo apt install libatlas-base-dev libjasper-dev libqtgui4 python3-pyqt5 libqt4-test
次に、Python3 用の OpenCV4 をインストールします。
sudo pip3 install opencv-python==4.5.1.48
以上で、Python3 用の OpenCV4 のインストールが終わりました。

5. 本書のOpenCVを用いた演習の実行

執筆当時のプログラムではいくつかのプログラムに修正が必要だったので、 2019/6/25にサンプルファイル(raspi2-sample.zip)を更新しました。 それ以前にダウンロードされた方は公式サイトから raspi2-sample.zip をダウンロードしなおしてください。

更新済のプログラムを用いる場合、実行方法は解説ページに記した内容と変わりません。

2018年2月3日土曜日

Raspberry Pi + Google Assistant API + LIRCによりテレビを音声認識で操作する

0. はじめにのはじめに

2019年6月にGoogle自身がこの方法はdeprecated(廃止予定)であるとしました。2020年3月31日にRaspberry Pi 4 で動作を確認しましたが、いずれ動作しなくなる可能性はありますのでそのつもりでご覧ください。

1. はじめに

本サイトでは以前、「Raspberry Pi + Julius + LIRC により家電製品を音声認識で操作する」という記事を紹介しました。

これは、Juliusという音声認識エンジンをRaspberry Piにインストールして音声認識を実現し、その結果に基づいて家電を操作するものでした。

それに対し、本ページでは音声認識をRaspberry Piにインストールしたソフトウェアではなく、クラウド上のサービスで行う例を紹介します。

この方法は、Raspberry Piが常にインターネットに接続していなければならないという欠点があるものの、音声認識の精度が高いというメリットがあります。両方試してみて比較するのも良いでしょう。

下図は、それを実現している様子を示したものです。


また、動作中の動画が下記になります。



2. 本ページの内容を実現するために必要なもの

本ページで解説する内容はクラウドサーバーとの連携が必要なため、書籍やサイトで解説してきた内容の中で最も難易度が高くなっております。ご注意ください。

また、実行には下記のものが必要です。
  • Googleのアカウント(GmailやAndroidスマートフォンで利用するもの)
  • Raspberry Piを常時インターネットに接続する環境
  • マイク(後述)
  • スピーカー(後述)
Googleアカウントの作成方法や利用方法は本サイトでは解説できませんのでご注意ください。

3. 音声入力(マイク)と音声出力(スピーカー)の設定

本ページの内容を実現するためには、マイクとスピーカーが必要です。どのような機器を用意すればよいか解説します。

まず、マイクからです。Raspberry Piにはマイクの接続端子がありませんので、利用できる機器をあらかじめ調べておく必要があります。
本ページでは、マイクを接続するためのデバイスとして「USBマイク系」と「USBサウンドデバイス系」の2系統を試しました。

「USBマイク系」としては下記の2種類を試しました。
「USBサウンドデバイス系」としては下記の3種類を試しました。
ただし、USBサウンドデバイスを用いる場合、さらにミニプラグ接続のPC用マイクも必要となります。これはどのようなマイクでも問題ないと思いますが、例えば
のようなものがあります。

以上の「USBマイク系」と「USBサウンドデバイス系」のどれかからお好みの方法を選んでください。なお、上に示した動画では「SANWA SUPPLY MM-MCU02BK USBマイクロホン」を用いています。

一方、スピーカーについては、ミニプラグで接続可能なものであれば何でも構いません。ただし、ミニプラグでのスピーカーの接続先については3通りの選択肢があります(後述します)。

以上の物品を用意し接続した後、それらを利用可能にする設定を行います。これは、「用いるOSのバージョン」および「用いるマイクとスピーカーの組み合わせ」により計6パターンの選択肢がありますので、下記のうち該当する内容を実行してください。

3.1 (2020年2月までのOS) USBマイク+Raspberry Pi本体のミニプラグ端子へのスピーカー接続

ターミナルで以下の3コマンドを順番に実行してください。
$ amixer cset numid=3 1
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/asoundrc
$ mv asoundrc .asoundrc

3.2 (2020年2月までのOS) USBマイク+HDMIディスプレイへのスピーカー接続

ターミナルで以下の3コマンドを順番に実行してください。
$ amixer cset numid=3 2
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/asoundrc
$ mv asoundrc .asoundrc

3.3 (2020年2月までのOS) USBサウンドデバイスへのマイクとスピーカーの接続

ターミナルで以下の2コマンドを順番に実行してください。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/asoundrc2
$ mv asoundrc2 .asoundrc

3.4 (2020年5月以降のOS) USBマイク+Raspberry Pi本体のミニプラグ端子へのスピーカー接続

ターミナルで以下の2コマンドを順番に実行してください。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/asoundrc3
$ mv asoundrc3 .asoundrc

3.5 (2020年5月以降のOS) USBマイク+HDMIディスプレイへのスピーカー接続

ターミナルで以下の2コマンドを順番に実行してください。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/asoundrc4
$ mv asoundrc4 .asoundrc

3.5 (2020年5月以降のOS) USBサウンドデバイスへのマイクとスピーカーの接続

ターミナルで以下の2コマンドを順番に実行してください。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/asoundrc5
$ mv asoundrc5 .asoundrc


3.4 マイクとスピーカーの動作チェック

さて、3.1~3.3のどれかの方法でマイクとスピーカーの接続および設定が終わったら、動作チェックしてみましょう。

まずはスピーカーのチェックです。ターミナルを起動して下記のコマンドを実行してみましょう。既に述べたように、本ページのコマンドはコピーと貼り付けによる実行を推奨します。
$ speaker-test -t wav
「Front, Left, …」という音声がスピーカーから流れるはずです。止めるにはターミナル上でキーボードのCtrlキーを押しながらcキーを押します(Ctrl-cといいます)。

次に、マイクの動作チェックを行いましょう。下記のコマンドを実行すると、5秒間の音声がour.rawというファイル名で保存されますので、マイクに向かって話しかけてみましょう。
$ arecord --format=S16_LE --duration=5 --rate=16000 --file-type=raw out.raw
録音が終わったら、下記のコマンドで再生してみます。
$ aplay --format=S16_LE --rate=16000 out.raw
マイクに話しかけた音声が再生されたら動作チェックは成功です。

なお、機器のボリュームの調節は下記のコマンドで起動するアプリケーションを用いるのですが、操作方法にかなり癖があります。
$ alsamixer
alsamixerの終了コマンドとして[ESC]キーは覚えておきましょう。まず、[F6]キーでサウンドカードを選択します。USBマイクの場合、矢印の上下キーで「1 USB PnP Audio Device」を選択してEnterを押します。2020年5月以降のOSならば「2 USB PnP Audio Device」となっているでしょう。 その後、[TAB]キーを繰り返し押すことで再生/録音/全てのどれかに選択肢を合わせ、上下キーで音量を調節します。調節が終わったら[ESC]キーでalsamixerを終了します。

4. サーバー側の準備

Googleの提供する方法で音声認識を実現する場合、下記の3つの方法が知られています。
  • Google Speech API v.2を用いる方法…古くからある方法。開発用途および個人用途のみ。1日50認識限定。
  • Google Cloud Speech APIを用いる方法…2017年4月にリリース。利用時の登録にクレジットカードが必要。
  • Google Assistant APIを用いる方法…Google Homeなどのようにコンピュータと対話するためのライブラリ。開発用途でのみ無料利用可能。一日500リクエストまで。
執筆時点では、3つめのGoogle Assistant APIの利用がお手軽に思えましたので、今回はこちらを試してみます。

ここからは、Raspberry Piが通信する相手となるサーバーの準備を行います。非常に長い手順となりますので、一つずつ確実に実行していきましょう。

なお、以下の手順は「Introduction to the Google Assistant Library」の解説に基づいています。

まず、Raspberry PiのChromiumブラウザを起動してGoogleにアクセスし、お持ちのGoogleアカウントでログインしておきましょう。下図の「ログイン」ボタンから行えます。


すると、下図のようなログイン画面が現れますので、IDとパスワードを入力してログインします。


ログインが済んだら、Google Assistant APIを用いるためのプロジェクトを作成していきましょう。まず、Chromiumブラウザで「Welcome to Actions on Google」のリンクをクリックして移動してください。

リンク先に下図のようなボタンがありますので、クリックしてプロジェクトを作成します。


ここでは、プロジェクトの名前を「Google Assistantのテスト」の意味で「gatest」とし、デフォルト言語を「Japanese」に、国を「Japan」にしましょう。特に、言語をJapaneseにしないと、Google Assitant APIは日本語を認識してくれません。

記入と設定が終わったら「CREATE PROJECT」をクリックします。


プロジェクト作成が終わったら、Chromium上のタブは閉じずにそのまま残しておきます。

そして、そのまま今度は「Google Assistant API」のリンクをクリックしてください。

このとき、下図の赤い四角に記されているように、作成したプロジェクト「gatest」が選択されていることを確認してください。

選択されていない場合、まずその部分をクリックしてプロジェクト「gatest」を見つけて選択します(現れるまでに時間がかかることがあります)。その後、そのタブを一旦閉じ、もう一度上「Google Assistant API」のリンクをクリックすると、下図の状態が実現すると思います。

そして、そのまま「有効にする」ボタンをクリックします。


次に、「OAuth consent screen」のリンクをクリックします。すると下記のようなページが開きますので、「メールアドレスを選択してください」の部分をクリックします。選択肢として、お使いのGoogleのメールアドレスが現れますので、それを選択します。

そして、ページ下部にある「保存」ボタンをクリックします。


ここまでの作業が終わったら、今度は「デバイスモデルの登録」の作業に移ります。

さきほど閉じずに残しておいたタブに戻り、一番下にある下記のボタンをクリックします。


すると、次のような画面に遷移しますので、「REGISTER MODEL」をクリックします。


現れたウインドウに、例えば下記のように記入します。上の2つは
  • Assistant SDK light
  • Assistant SDK developer
です。3つ目の「Light」は選択式となっています。

これらは、本来は何を入力しても良いのですが、チュートリアルページのサンプルに合わせてこのような内容にしています。

なお、ここで表示されている「Device Model id」の内容は、以下で多用しますので、コピーしてテキストエディタなどに記して控えておきましょう。


記入やメモが終わったら「REGISTER MODEL」ボタンをクリックします。

すると、遷移した先のページで以下のようなボタンが現れますので、クリックしましょう。


すると、「client_secret_XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com.json」という形式の、非常に長い名前のファイルがダウンロードされます。保存先はデフォルトで /home/pi/Downloads となります。

このファイルを、Downloadsディレクトリからホームディレクトリ (/home/pi) に移動しておきましょう。

ターミナルを起動し、下記のコマンドを実行してください。なお、先頭の「$」はコマンドの先頭を表す記号ですので、コマンドには含めないでください。また、最後の「.」(ピリオド)にも意味はありますので、忘れずにコマンドに含めてください。
$ mv Downloads/*.json .
拡張子 json のファイルを、Downloadsディレクトリからカレントディレクトリ (.) に移動しています。以下、コマンドはブラウザ上でコピーし、ターミナルへ貼り付けて実行することを推奨します。

ここまで終わったらブラウザで「NEXT」ボタンをクリックします。

次に、traitsを保存(SAVE TRAITS)するためのページに遷移しますが、ここでは「SKIP」をクリックしてスキップします。

最終的に、下記のようにModel IDが確定します。先ほどメモしたModel IDが再掲されていますね。


Model IDとともに、Project IDも以下で必要となりますので、ここで調べてメモしておきましょう。Chromiumブラウザでリソース管理ページに移動すると、先ほど作成したgatestに対する Project ID(プロジェクトID)が表示されていますのでこれもメモしておきましょう。

恐らく、Model IDとProject IDは先頭が 「gatest-xxxxx」の形式で共通となっていることでしょう。

次に、Chromiumブラウザで「アクティビティ管理」のページに移動し、下記の4点の設定を確認してください。
  • 「ウェブとアプリのアクティビティ」を有効(青色)に
  • 「Chrome の閲覧履歴と Google サービスを使用するウェブサイトやアプリでのアクティビティを含める」にチェック
  • 「端末情報」を有効(青色)に
  • 「音声アクティビティ」を有効(青色)に
以上でサーバーの設定は完了です。しかし、そのほかの設定はまだまだ続きます。

5. 様々なソフトウェアのインストール

まず、ターミナルを起動し、下記の5つのコマンドを順に実行してください。なお、先頭の「$」はコマンドの先頭を表す記号ですので、コマンドには含めないでください。 長いコマンドが続きますので、ブラウザ上でコマンドをCtrl-cでコピーし、ターミナル上の「編集」→「貼り付け」によりコマンドを貼り付けて実行することを推奨します。
$ sudo apt update
$ sudo apt install python3-dev python3-venv
$ python3 -m venv env
$ env/bin/python -m pip install --upgrade pip setuptools
$ source env/bin/activate
3つめのコマンドでは、/home/pi/env にpython3の仮想実行環境を用意しています。Google Assistant SDKのチュートリアルでは、仮想環境でのインストールと実行を行っていますので、本ページでもそれに従います。

また、最後のコマンド「source env/bin/activate」では作成した仮想環境を優先して利用するよう設定しています。それにより、コマンドプロンプトは下記のように変化します。
(env) pi@raspberrypi:~ $
本ページではこれを以下のように略記し、これの後に記されたコマンドは仮想環境で実行すべきコマンドであるものとします。
(env) $
さて、Pythonの仮想環境において下記の4つのコマンドを引き続き実行していきます。これまで通りコマンドのコピーと貼り付けにより実行しましょう。実行すべきコマンドは「$」の後ろの部分のみですので注意してください。
(env) $ sudo apt install portaudio19-dev libffi-dev libssl-dev
(env) $ python -m pip install --upgrade google-assistant-library==1.0.0
(env) $ python -m pip install --upgrade google-assistant-sdk[samples]
(env) $ python -m pip install --upgrade google-auth-oauthlib[tool]
以上でツールのインストールは完了です。次は引き続きツールとサーバーの連携作業となります。途中で作業をやめず、一気に最後まで進めた方が良いです。

6. サーバーとの連携の設定

引き続き、下記のコマンドをターミナルで実行するのですが、これはこのまま実行してもうまくいきません。
(env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --scope https://www.googleapis.com/auth/gcm --save --headless --client-secrets /path/to/client_secret_client-id.json
最後の「/path/to/client_secret_client-id.json」の部分を、皆さんが「サーバー側の準備」でダウンロードしたファイル「client_secret_XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com.json」で読み替えて実行しないといけないのです。

それを、下記の手順で実現しましょう。まず、上のコマンドをから末尾の「/path/to/client_secret_client-id.json」を省いた下記のコマンドをコピーし、ターミナルに貼り付けましょう。
(env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --scope https://www.googleapis.com/auth/gcm --save --headless --client-secrets 
そして、そのコマンドの末尾にスペースを入力し、さらに「client」まで書きます。すなわち、下記のようになります。
(env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --scope https://www.googleapis.com/auth/gcm --save --headless --client-secrets client
そこで、キーボードの[TAB]キーを押します。すると、ファイル名が補完され、下記のようにコマンドが完成します。そこでEnterを押して実行します。
                
(env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --scope https://www.googleapis.com/auth/gcm --save --headless --client-secrets client_secret_XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com.json
なお、ファイル名の「XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx」の部分は人により異なりますので、「XXXXXXXXXXXX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx」をそのままコピーしても正しい実行結果は得られませんので注意してください。 また、[TAB]キーを押したときにファイル名が補完されるのは、「サーバー側の準備」で、
  • ファイルをDownloadsディレクトリに保存したこと
  • 保存したファイルをDownloadsディレクトリからホームディレクトリに移動したこと
の二点が正しく行われたときのみですので良く確認してください。

基本的に本ページの内容は一つでも正しく実行されていない項目があればうまくいかないとお考え下さい。

さて、コマンドが正しく実行されると、下図のように、ブラウザでアクセスすべきアドレスが現れます(図を拡大表示して形式を良く観察してください)。


このアドレスの部分(「https://」から「consent」まで)をマウスでなぞり、ターミナル上で「編集」→「コピー」を選択してコピーします(Ctrl-cでコピーしようとするとコマンドが終了してしまいますので注意しましょう)。

そして、chromiumブラウザのアドレス欄にコピーされたアドレスを貼り付けてEnterし、ブラウザでページを移動します。

すると、アカウントの選択が求められた後、さらに下図のようにブラウザ上にgatestからのリクエストが表示されますので、許可ボタンをクリックしてください。


すると、ブラウザで下記のように長いコードが表示されますので、マウスでなぞってCtrl-cでコピーしてください。


そして、先ほどのターミナルに戻り、「編集」→「貼り付け」で貼り付け、Enterキーを押します。

すると、下図のように「credentials saved: /home/pi/.config/google-oauthlib-tool/credentials.json」と表示されて処理が完了します。


7. 動作確認

以上で動作確認を行う準備が整いました。 まず、動作確認および音声認識用のファイルをダウンロードします。ダウンロードは通常環境と仮想環境のどちらで行っても構いません。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/controlTV-ga.py
次に、動作確認を行います。もしこの時点でPythonの仮想環境に入っていなければ、次のコマンドで仮想環境に入ります。
$ source env/bin/activate
そして、実行すべきコマンドは下記になります。斜体部は上で確認した皆さんのProject IDとModel IDで置き換えて実行してください。
$(env) $ python controlTV-ga.py --project_id project-id --device_model_id model-id
実行したら、マイクに向かって「オーケー グーグル」と話しかけてください。


認識されれば上図のように「ON_CONVERSATION_TURN_STARTED」と表示されますので、そのまま「今何時?」などと話しかけてみてください。スピーカーから返答が出力されるはずです。

なお、AndroidスマートフォンやiPhoneなどをお持ちの場合、Googleのアプリケーションで「設定」→「設定」→「Assistant SDK light」とたどり、以下のように「アカウントに基づく情報」をオンにすると、「私は誰?」や「今日の予定」など、アカウントの個人情報に基づく質問にも答えてくれるようになります。なお、Googleのアプリケーションは、Android用iPhone/iPad用があります。





最後に、このサンプルプログラムを終了するには、キーボードでCtrlキーを押しながらcキーを押してください(Ctrl-cといいます)。

8. 音声でのテレビの操作

この状態で、冒頭の動画のように「オーケーグーグル、テレビつけて」などとマイクに話かけると、 テレビをオンにする信号赤外線LEDより出力される、という流れです。

ダウンロードしたプログラム controlTV-ga.py のうち、テレビの操作に関わる部分を一部抜きだしたのが以下の部分になります。
    if event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED:
        s = event.args['text']
        print(s)
        if 'テレビ' in s and  ('つけて' in s or 'オン' in s):
            args = ['irsend', '-#', '1', 'SEND_ONCE', 'TV', 'power']
            try:
                subprocess.Popen(args)
            except OSError:
                print('command not found.')
            assistant.stop_conversation()
        elif 'テレビ' in s and  ('消して' in s or 'オフ' in s):
            args = ['irsend', '-#', '1', 'SEND_ONCE', 'TV', 'power']
            try:
                subprocess.Popen(args)
            except OSError:
                print('command not found.')
            assistant.stop_conversation()
        elif 'NHK 教育' in s or 'Eテレ' in s:
            args = ['irsend', '-#', '1', 'SEND_ONCE', 'TV', 'ch2']
            try:
                subprocess.Popen(args)
            except OSError:
                print('command not found.')
            assistant.stop_conversation()
少し解説しましょう。

この部分は、「オーケーグーグル」と話しかけた後に発した言葉が「Google Assistant API」により音声認識された後の処理を表しています。「s」という変数に音声認識結果が格納されています。

そこで、「if 'テレビ' in s」と書くと、「文字列 s に'テレビ'という語句が含まれていたら」という条件となります。

さらに、and (なおかつ)、or (または)を組み合わせて条件を作成しています。

結果的に「'テレビ' in s and ('つけて' in s or 'オン' in s)」という条件で、
「sに’テレビ'と'つけて'が含まれている場合」または「sに’テレビ'と'オン'が含まれている場合」にテレビの電源がつくという動作になります。
条件文を作る際のカッコ「()」の使い方にも注意しましょう。

なお、テレビの電源を入れるための信号は、「irsend -# 1 SEND_ONCE TV power」という命令を実行することで行っています。この命令を有効にする方法は本書5章で解説されていますので、参照してください。赤外線LEDを用いた回路の作成方法も解説しています。

それらの準備を済ませると、冒頭の動画のように音声に応じてテレビを操作することができます。

なお、音声認識の結果に基づいてテレビを操作した後、「assistant.stop_conversation()」という命令を実行してGoogle Assistantとの会話をそこで打ち切っています。そうしないと、テレビへの命令を受け付けるたびにGoogle Assistantが「申し訳ありません、お役に立てそうにありません」と音声を発してしまうためです。

9. Google Assistantでのテレビ操作についての注意

以上のように、Google Assistantによる音声認識結果を直接if文で判定させることでテレビの制御を行いました。

実は、Google Assistantには、家電などのオンオフを制御する公式な方法があります。例えば、こちらのページではRaspberry Piに接続したLEDをオンオフする方法が解説されています。

しかし、この方法を用いてテレビのチャンネルを変える方法が思いつかなかったので、本ページでは音声認識結果を直接if文で判定する方法を取りました。

10. 仮想環境上のPythonを利用する際の注意

なお、本ページではGoogle Assistant SDKの公式ページで行われているのに合わせ、Python3の仮想環境を作成してその上でプログラムを実行しました。

この方法を用いると、デフォルトでは電子工作用のライブラリを用いることができません。本書ではGPIOにアクセスするためにRPi.GPIOというライブラリを用いましたが、そのままではそれを利用することができないのです。

既存ライブラリをPythonの仮想環境でも利用可能にするには、設定が必要です。
設定ファイル /home/pi/env/pyvenv.cfg 内にある
include-system-site-packages = false
という行を
include-system-site-packages = true
に変更して保存すると、既存ライブラリが仮想環境でも利用可能になります。

11. Google Assistant APIの利用制限について

Google Assistant APIは無制限に使えるわけではなく、
  • 1日当たり500リクエスト
  • 100秒当たり100リクエスト
という制限があります。ですから、何度も会話をしているとその制限を超え、結果が返ってこないことがあり得ます。

どの程度Google Assistant APIを利用しているかを確認する方法を以下に記します。

リソースの管理」ページに行き、プロジェクト名をクリックします。 現れるページの左のカラムで「割り当て」をクリックします。 そして、現れた右の表示エリアで「Google Assistant API」を見つけてクリックすると、利用状況のグラフを見ることができます。

「太平洋時間(PT)の午前 0 時にリセット」と書かれておりますので、 その時間が過ぎればリクエスト数がリセットされてまた利用可能になるはずです。

13. Raspberry Pi起動時にプログラムを自動起動する

ここで紹介したcontrolTV-ga.pyは、実行するためのコマンドがやや複雑でした。

このコマンドをシンプルに実行できるようにし、さらにRaspberry Pi起動時に自動で実行する方法を解説します。

まず、コマンドをシンプルにする方法です。ターミナルを起動し、以下の2つのコマンドを順に実行しましょう。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/start-assistant.sh
$ chmod 755 start-assistant.sh
以後実行するのはstart-assistant.shというコマンドになるのですが、その前にこのファイルの中身を編集する必要があります。まず、下記のコマンドを実行することでテキストエディタleafpadでstart-assistant.shを編集用に開きます。
$ leafpad start-assistant.sh
このファイルの中身は下記のようになっています。
#!/bin/bash

source /home/pi/env/bin/activate

# set if you are inside firewall
#export http_proxy=http://(proxy server):(port)/
#export https_proxy=http://(proxy server):(port)/
#export ftp_proxy=http://(proxy server):(port)/

python /home/pi/controlTV-ga.py --project_id gatest-xxxxx --device_model_id gatest-xxxxx-assistant-sdk-light-xxxxxx
この最後の行の「gatest-xxxxx」と「gatest-xxxxx-assistant-sdk-light-xxxxxx」の部分を皆さんが使っているモデルのIDに変更してください。この行が、いつも実行しているcontrolTV-ga.pyを実行しているコマンドが記されていることはわかるでしょう。
さらに、controlTV-ga.pyの位置がユーザpiのホームディレクトリ (/home/pi) であることを前提とされていることにも注意してください。
変更が終わったら、ファイルを上書き保存してleafpadを閉じましょう。
その後ターミナルを起動して、下記のコマンドを実行しましょう。これは仮想環境に入らずに実行して構いません。このファイル内部で仮想環境の利用設定とcontrolTV-ga.pyの実行が両方行われるので、プログラムの実行が容易になるというわけです。
$ ./start-assistant.sh
ここまでが実現できたら、Raspberry Pi起動時の自動実行が下記のように実現されます。
まず、下記のコマンドを実行してください。必要なファイルをダウンロードし、適切な場所に配置しています。
$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/assistant.service
$ sudo mv assistant.service /etc/systemd/system
その後、下記のコマンドを実行すると、再起動時にcontrolTV-ga.pyが自動で起動します(ターミナルの表示がないのでわかりにくいですが…)。
$ sudo systemctl enable assistant
上記の動画では、Raspberry Pi本体にキーボードとマウスが取り付けられていませんが、これはこの自動起動が行われていたからです。

自動起動を無効にするには下記のコマンドを実行します。
$ sudo systemctl disable assistant