LoginSignup
4
1

More than 3 years have passed since last update.

夏じゃないけど)ゴーストを見つけるロボ

Last updated at Posted at 2019-12-03

うちの監視ロボ、人には見えない('_')を検知するらしいんです

これが実際に検知した写真...

image.png

あなたにも見えるでしょうか。

image.png
きゃーーーーー  ((((>_<)

image.png
うちの部屋にもーーーー   ((((>_<)

さて。今回作ったクラウドの構成です。

この構成ならクレジットカードが不要で、ずっと無料で使える IBM Cloud ライトプラン。オブジェクトストレージに画像を保管して、Cloud Foundryで可視化します。
image.png

その1.画像を保存するオブジェクトストレージを準備します

image.png

(1) IBM Cloud の Object Storage 無料のライトプランを選びます

image.png

バケット(入れ物)のパラメータを指定して[作成]を実行(ロケーションは東京 jp-tok)
image.png

(2) ファイルをバケットにアップロードできるか試します

image.png

WEBブラウザでオブジェクトストレージのファイルにアクセスします。
image.png

画像をダウンロードできました。
image.png

(3) ロボットから画像をアップロードするための「サービス資格情報」を作成します

image.png

作成した「サービス資格情報」は、画像アップロードに使うのでメモします
image.png

画像ダウンロードできない? 

それなら続きはこちら→ https://qiita.com/1Kano/items/4144be24c5168f9356f7

その2.「ゴーストセンサー・ロボ」から、オブジェクトストレージへ画像をアップロードします

image.png

めっちゃハマったところ(T_T)

アップロードの方法は幾つか用意されています。

  1. ロボットに入っているラズパイは[swiftコマンド]で動かしていた。
  2. オブジェクトストレージが[s3互換]になったので[AWS-CLIのs3コマンド]で動作確認した。
  3. 途中、pythonスクリプトには[AWS SDK for Python]が良さげなので[boto3]を使った。
  4. AWSの[boto3]ではなく、IBM Cloudの[IBM COS SDK for Python]があるじゃない。早速[ibm-cos-sdk]をダウンロード。あれー?[ibm_boto3]ファイルアップロード動かないよー、説明書足りないー。実行するとエラー。
  5. しゃーない。[cURL]でやろっと。動いた、pythonで組むなら[import requests]か。で、動いた。

動作確認ずみのpythonスクリプト

  1. ラズパイが5秒おきにカメラ撮影する
  2. 画像ファイルは、[openCV]で顔を検知する
  3. もしも画像ファイルに顔が見つからなければ(1に戻って5秒待つ)
  4. IBM Cloud の[認証トークン]をもらって、オブジェクトストレージへのアクセスを許可してもらう
  5. [認証トークン]を使って、オブジェクトストレージに画像をアップロードする(1に戻る)

image.png

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import cv2
import time
import requests
import json
import os

def run_capture_camera():
    # Haar-like特徴分類器ファイル(顔検出版)の読み込み。
    face_cascade = cv2.CascadeClassifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml")

    # USBカメラで画像を取得する。
    time.sleep( 0.2 )
    capture = cv2.VideoCapture(0)
    rtn, frame = capture.read()

    # カメラ画像を保存する
    if( rtn == True ):
        cv2.imwrite( "capture_input.jpg", frame )

        # 画像ファイルをグレースケールに変換する。
        gray = cv2.cvtColor( frame, cv2.COLOR_BGR2GRAY )
        # グレースケール画像から顔を検知する。
        faces = face_cascade.detectMultiScale( gray )
        for rect in faces:
            # 検知した顔を四角で囲む(rect[*]:0=x, 1=y, 2=width, 3=height)。
            color = (0,255,0)    # 緑色(BGR)。
            thickness = 2        # 枠線の太さ
            cv2.rectangle( frame, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), color, thickness )
        # 顔検知した画像ファイルを保存する。
        cv2.imwrite( "capture_output.jpg", frame )

    # 終了処理(ストリームを解放)
    capture.release()
    cv2.destroyAllWindows()

    # 顔を検知したか否かを返す
    if( len(faces) > 0):
        return True
    else:
        return False

def run_upload_file():
    # トークンを取得するための IBM Cloud 認証用エンドポイント
    auth_endpoint = "https://iam.cloud.ibm.com/identity/token"
    # ファイルをアップロードするときの IBM Cloud サービス用エンドポイント
    # (ラズパイからインターネット経由でアクセスするのでパブリック側エンドポイントを指定)
    service_endpoint = "https://s3.jp-tok.cloud-object-storage.appdomain.cloud"
    # IBM Cloud Object Storage のサービス資格情報で取得するapikeyは、OSの環境変数に登録しておき、コードには書かない。
    # $ export IBM_APIKEY=ddZgpr*********************************jGkB3
    ibm_apikey = os.environ['IBM_APIKEY']

    # IBM Cloud Object Storage 認証トークンを取得する
    headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    data = {
        'apikey': ibm_apikey,
        'response_type': 'cloud_iam',
        'grant_type': 'urn:ibm:params:oauth:grant-type:apikey'
    }
    response = requests.post(auth_endpoint, headers=headers, data=data)
    output = response.json()
    ibm_access_token = output['access_token']
    # トークン取得をデバッグするときに検査したいとき
    print("TOKEN STATUS:" + str(response))
    #print("TEXT  :" + json.dumps(output, indent=4))
    #print("TOKEN :" + str(ibm_access_token))

    # IBM Cloud Object Storage に、カメラ画像ファイルをアップロードする。
    # この例では[/robocamera]がバケット名、ghostpicture.jpgがファイル名(オブジェクトのキー名)です。
    headers = {
        'Authorization': 'bearer ' + ibm_access_token,
        'Content-Type': 'image/jpeg',
    }
    f = open('capture_output.jpg', 'rb')
    img_data = f.read()
    f.close()
    response = requests.put(service_endpoint + '/robocamera/ghostpicture.jpg', headers=headers, data=img_data)
    # トークン取得をデバッグするときに検査したいとき
    print("UPLOAD STATUS:" + str(response))

if __name__=="__main__":

    try:
        while True: # 永久に繰り返し
            rtn = run_capture_camera()
            if( rtn == True ): 
                print("顔を検知したのでクラウドに保存しました")
                run_upload_file()
            else:
                print("No face, no upload")
            time.sleep(5)
    except KeyboardInterrupt: # CTRL+Cで終了
        print "Exit"

    sys.exit()

cURLとpythonでファイルアップロードするなら

 それなら続きはこちら→ https://qiita.com/1Kano/items/c3c7e0400dd2384f8058

IBM Cloud Object Storage SDK

参考 https://ibm.github.io/ibm-cos-sdk-python/

その3.IBM Cloud Cloud Foundry に画像可視化アプリを準備します

image.png

(1) IBM Cloud Foundry を準備します

image.png
image.png
アプリのURLをメモして、WEBブラウザで[Hello world!]と空のアプリが起動するのを確認する。
image.png

(2) 自分PCのアプリ開発環境を準備します(Windowsの場合)

(2)-1. [IBM Cloud CLI] を自分PCにダウンロード。

参考 https://cloud.ibm.com/docs/cli?topic=cloud-cli-install-ibmcloud-cli&locale=ja

image.png

(2)-2. Windows PC の IBM Cloud コマンドで IBM Cloud API にログインする

E:\>ibmcloud login
API エンドポイント: https://cloud.ibm.com
地域: us-south

Email> (自分のIBM ID)

Password> (自分のIBM IDのパスワード)
認証中です...
OK

ターゲットのアカウント 個人利用(鹿野) (9d7f******************830)

API エンドポイント:      https://cloud.ibm.com
地域:                    us-south
ユーザー:                (自分のIBM IDが表示されます)
アカウント:              個人利用(鹿野) (9d7f********************830)
リソース・グループ:      リソース・グループがターゲットになっていません。'ibmcloud target -g RESOURCE_GROUP' を使用してください
CF API エンドポイント:
組織:
スペース:

(2)-3. Windows PC の IBM Cloud コマンドで Cloud Foundry の組織やリソースを登録する

E:\>ibmcloud target --cf
ターゲットの Cloud Foundry (https://api.ng.bluemix.net)

ターゲットの組織 <自分の組織名>

ターゲットのスペース <自分のスペース名>

API エンドポイント:      https://cloud.ibm.com
地域:                    us-south
ユーザー:                <自分のユーザー名(IBM id)>
アカウント:              個人利用(自分) (9d7f****************e830)
リソース・グループ:      リソース・グループがターゲットになっていません。'ibmcloud target -g RESOURCE_GROUP' を使用してください
CF API エンドポイント:   https://api.ng.bluemix.net (API バージョン: 2.142.0)
組織:           <自分の組織名> 
スペース:                <自分のスペース名>

(2)-4. 空っぽの Cloud Foundry アプリを作ってみる

ファイルを2つ作ります。

E:\cfproject
  ├ [manifest.yml] デプロイするアプリのPathや、
  │         デプロイ先のプロジェクト/リソースを指定します
  └\test
    └ [index.html] テスト用HTML

以下、サンプル
[manifest.yml]

---
applications:
- name: projectx2
  path: E:\cfproject\test
  random-route: true
  instances: 1

[index.html]

<!doctype html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <title>CF デプロイ テスト</title>
  </head>
  <body>
    <h1>この画面が表示されたら成功</h1>
  </body>
</html>

(2)-5. Cloud Foundry アプリをパブリックURLにデプロイしてみる

[manifest.yml]があるディレクトリでIBM CLIを実行する

E:\cfproject>ibmcloud  cf push

'cf push' を起動しています...

  <中略>

Waiting for app to start...

name:              projectx2
requested state:   started
routes:            projectx2.mybluemix.net
last uploaded:     Sat 30 Nov 14:35:11 JST 2019
stack:             cflinuxfs3
buildpacks:        staticfile

type:            web
instances:       1/1
memory usage:    64M
start command:   $HOME/boot.sh
     state     since                  cpu    memory         disk          details
#0   running   2019-11-30T05:35:30Z   0.2%   13.8M of 64M   22.6M of 1G

E:\cfproject> _

WEBブラウザで Cloud Foundry アプリにアクセスしてみる
image.png

Cloud Foundry アプリが動かない? 

続きはこちら→「IBM Cloud Foundry トラブルシューティング」(予定)

(3) 画像を可視化するCloud Foundry アプリを作ります

自分の好きな言語を選びます。私の場合は Angularフレームワークも勉強するので言語は Type Script です。ランタイムは node.js です。
image.png

(3)-1. 自分PCの環境にAngular CLIを準備します

  • Windows 10
  • Visual Studio Code (Windows版) 1.39.2
  • C:\Users\Kano>ng --version

参考 https://angular.jp/cli ※Angular CLIのインストールを参照方

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/

Angular CLI: 8.1.1
Node: 10.16.0
OS: win32 x64
Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.801.1
@angular-devkit/core         8.1.1
@angular-devkit/schematics   8.1.1
@schematics/angular          8.1.1
@schematics/update           0.801.1
rxjs                         6.4.0

(3)-2. Angularプロジェクトを新規作成します

Windowsコマンドプロンプトを開いて、プロジェクトを作成するフォルダに移動して[ng new プロジェクト名]を実行する。

E:\Source\Angular> ng new projectx
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
CREATE projectx/angular.json (3441 bytes)
CREATE projectx/package.json (1281 bytes)
CREATE projectx/README.md (1025 bytes)

 以下、projectxディレクトリにひな形のソースファイルがつくられる、たくさん。

CREATE projectx/e2e/tsconfig.json (214 bytes)
CREATE projectx/e2e/src/app.e2e-spec.ts (637 bytes)
CREATE projectx/e2e/src/app.po.ts (251 bytes)

added 1082 packages from 1045 contributors and audited 17199 packages in 127.449s

E:\Source\Angular> cd projectx
E:\Source\Angular\projectx> _

作成された新規プロジェクトのフォルダ・ファイル
image.png
[manifest.yml]は自分で作成します。私の場合(↓)こうなりました

---
applications:
- name: projectx2
  path: E:\Source\Angular\projectx\dist\projectx
  random-route: true
  disk_quota: 512M
  memory: 64M
  instances: 1
  buildpacks:
    - https://github.com/cloudfoundry/staticfile-buildpack.git

(3)-3. Angularでアプリを作成

大幅省略しますが、下記はCloud Foundry アプリがオブジェクトストレージの画像を参照する最小限のコンポーネント、ファイル名は[app.component.html]です。[index.html]の app-root から呼ばれるコンポーネントです。

<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">

<div class="box1">
    <h1>ゴーストセンサー</h1>
</div>
<img width=95% src="https://robocamera.s3.jp-tok.cloud-object-storage.appdomain.cloud/ghostpicture.jpg">

</div>
<h2>KANO 2019/11/30</h2>

<router-outlet></router-outlet>

(3)-4. Angularでアプリをビルドします

アプリをビルドすると \dist\フォルダに新しいビルド済みフォルダが再作成されます


E:\Source\Angular\projectx>ng build

chunk {main} main-es2015.js, main-es2015.js.map (main) 9.79 kB [initial] [rendered]
chunk {polyfills} polyfills-es2015.js, polyfills-es2015.js.map (polyfills) 251 kB [initial] [rendered]

  <中略>

chunk {styles} styles-es5.js, styles-es5.js.map (styles) 16.8 kB [initial] [rendered]
chunk {vendor} vendor-es5.js, vendor-es5.js.map (vendor) 3.81 MB [initial] [rendered]
Date: 2019-11-30T06:31:27.033Z - Hash: c76ae6e4ddd7162549d0 - Time: 6327ms

E:\Source\Angular\projectx> _

(3)-5. Angular で作ったアプリを Cloud Foundry にデプロイします

デプロイは、再び、Windowsコマンドプロンプトで [ibmcloud cf push] です。

E:\Source\Angular\projectx>ibmcloud cf push

'cf push' を起動しています...

Pushing from manifest to org <IBM ID> / space KANO as <IBM ID>...
Using manifest file E:\Source\Angular\projectx\manifest.yml

  <中略>

type:            web
instances:       1/1
memory usage:    64M
start command:   $HOME/boot.sh
     state     since                  cpu    memory         disk            details
#0   running   2019-11-30T06:37:58Z   0.2%   10.5M of 64M   22.6M of 512M

E:\Source\Angular\projectx> _

その4.遊ぶ

image.png

(1) WEBブラウザでアプリにアクセス。

ほらほら、うちのロボが心霊(-.-)を認識したって...
image.png

(2) ちゃんと顔認識しますよ

20才の時の自分写真
image.png

(3) 自宅警備ロボ化してみようかな

自宅内のリアルタイム写真をインターネットに公開しちゃダメ。Basic認証でWEBを保護しよう。オブジェクトストレージ側も公開制限をしなきゃね。
image.png

工夫したこと

オブジェクトストレージの無料条件は25GBまで保存できるなど凄いのだが「最大 2,000 PUT要求/月」とある。自宅警備カメラが1分毎に画像をアップロードすると 44,640回(= 60分 x 24時間 x 31日)。最大PUT回数足りない!毎分アップロードできないー!!となったので、ラズパイが1分間隔で撮影した画像は、侵入者を検知した画像のみ、オブジェクトストレージに保存することとした(検索の効率も良いし)。

まとめ

IBM Cloud ライトプランの無料で出来る範囲の構成を作ってみました。クラウドサービスがどんどん新旧更新されているので、最新のドキュメントを見つけることに想定より時間がかかってしまいましたが、動いたときの達成感は良かった(燃え尽き感もあるが)。

本記事に含まれるもの
1. IBM Cloud Object Storage
2. IBM Cloud Foundry
3. Raspberry Pi 3
4. Python
5. Angular TypeScript

4
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
4
1