YU2TA7KA's BLOG ~take one step at a time~

派生開発、組み込み開発周りのこと。

Raspberry Piカメラで撮影した画像をGoogleフォトへ自動アップロードする【おうちカメラ】

やったこと

おうちカメラに、ラズパイのカメラで定点定期撮影した画像をGoogleフォトへ自動アップロードする機能を実装しました。Qiitaに投稿いただいていた記事、ソースコードを利用させていただいております。認証部分が不慣れで理解不足ですが、とりあえず動かせている状態です。

システム構成

システム構成図(ver3)

f:id:yuji-tanaak:20190810071025j:plain

ハードウェア

ver2と同じです。

ソフトウェア

名前 用途
MJPG-streamser ストリーミング配信
cron 定期撮影、定期温度取得、定期撮影画像の定期アップロードの実行
systemd ラズパイ起動時にアプリケーションを実行開始する
Node.js 取得した温度値をブラウザに表示するサーバープログラミング環境
Google フォト 定期撮影したデータをAPIで自動でアップロードする

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.9 (stretch)
Release:	9.9
Codename:	stretch
$ uname -a 
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux
$ nodejs -v  
v8.11.1  
$ npm -v  
1.4.21  
$ python --version
Python 2.7.13
$ python3 --version
Python 3.5.3

Google APIのAccess Token取得のお試し

qiita.com
上記を参考にアルバム一覧の取得までを確認できました。

googleサービス上(ブラウザ)での操作

  1. APIの有効化
  2. 認証情報の作成(CLIENT_IDとCLIENT_SECRETを生成)
  3. 認証コードの取得*1

端末上(ラズパイ)での操作

1. Access Tokenの取得

$ CLIENT_ID=<認証情報の作成で作成した文字列>
$ CLIENT_SECRET=<認証情報の作成で作成した文字列>
$ REDIRECT_URI=urn:ietf:wg:oauth:2.0:oob
$ AUTHORIZATION_CODE=<ブラウザアクセスで取得した認証コード>
$ curl -s --data "code=$AUTHORIZATION_CODE" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "redirect_uri=$REDIRECT_URI" --data "grant_type=authorization_code" --data "access_type=offline" https://www.googleapis.com/oauth2/v4/token

{
 "access_token": "***",
 "token_type": "Bearer",
 "expires_in": 3600,
 "refresh_token": "***"
}

2. アルバム一覧の取得

curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://photoslibrary.googleapis.com/v1/albums

3. Refresh Tokenの取得

$ REFRESH_TOKEN=<取得済みのrefresh_token>
$ curl -s --data "refresh_token=$REFRESH_TOKEN" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token

Googleフォトへ自動アップロードする

qiita.com
上記のソースコードを利用させていただきました。python3.5.3で動作しています。

必要なパッケージのインストール

$ pip3 install --upgrade google-api-python-client
$ pip3 install --upgrade oauth2client

ソースコード、テストファイルの準備

$ tree 
.
├── google_photos_client_secrets.json #参考記事のコメント部分参考に作成。client_id、project_id、client_secretを環境に合わせる。
├── google_photos_token.json #google_photos_upload.pyを実行すると自動生成されるファイル
├── google_photos_upload.py #参考記事のコード
└── img_test
    ├── 201908070500.jpg #テストファイル
    └── 201908070600.jpg #テストファイル

プログラムの実行

$ python3 google_photos_upload.py --noauth_local_webserver img_test/
/home/pi/.local/lib/python3.5/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access google_photos_token.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))

Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?client_id=<認証情報のものが表示される>&response_type=code&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fphotoslibrary&access_type=offline

Enter verification code: <上記URLにブラウザでアクセスし、取得した認証コード>を手動入力する。
Authentication successful.
INFO:__main__:album: img_test not exists
DEBUG:__main__:create album: img_test
DEBUG:__main__:id: ABHiPZkYbSr82hwbSHQ7eHGG-nwVA804JNx6mnhMljfp_IO9TTUgK62looBOTZOvGzrPALRPCg8j, title: img_test
INFO:__main__:album: img_test created
DEBUG:__main__:  1 201908070500.jpg uploading... 
DEBUG:__main__:batchCreate status: {'message': 'Success'}
DEBUG:__main__:  2 201908070600.jpg uploading... 
DEBUG:__main__:batchCreate status: {'message': 'Success'}

これでgoogle photoに「img_test」というアルバムが作成され、img_test/以下にあったファイルがアップロードされました。
また、2回目以降は認証コードの手動入力不要でアルバムに無いファイルに対してアップロードが実行されます。

エラー対応

認証コードを取得して、Enter verification codeに入力すると下記エラーが発生しました。

Authentication has failed: invalid_clientUnauthorized

原因は、google_photos_client_secrets.jsonファイル内でclient_secretの情報の末尾にスペースが入っているコピペミスでした。。

おわりに

これで定期撮影した画像をGoogleフォト経由でいつでもどこでも確認できるようになりました。おうちカメラでやりたいことがほぼできました。当初ではここから表情分類をしたいと思っていたのですが、そもそも撮影画像に赤ちゃんが写っていない場合も多々あることに気づきました。なので、次は赤ちゃんが撮影画像にいる/いないの2値判別を行う機能を実装したいと思います。VGG16を使った画像分類の学習モデルを自作したら面白そうですが、ラズパイしかローカルマシンはないので学習時間が大変なことになりそうです。自作できるクラウドサービスも別途探してみようかなと思います。

f:id:yuji-tanaak:20190810071438j:plain