Help us understand the problem. What is going on with this article?

Pepperで画像を撮影してタブレットに画像表示

More than 5 years have passed since last update.

Choregrapheには Take Pictureというボックスがあり、Pepperが見ている画像をファイルとしてPepper内のファイルシステムに保存することができます。
このファイルをどう処理するかとしては、Eメール送信ボックスでの添付ファイルとしたり、タブレットに画像表示するボックスで参照するなどさまざまなことが考えられますが、それぞれのボックスでファイルを参照するときに重要になるのが、Pepper内でのパスの考え方です。

ここでは、画像を撮影して、それをタブレットに表示する例の作成を通じて、パスの考え方をいくつか説明していきます。

Take Pictureボックスにおける画像保存先パス

Choregrapheの[ボックスライブラリ]パネルで、standardボックスライブラリ > Vision > Take Pictureボックスを選択すると、以下のような説明が表示されます。

take-picture-desc.png

store it in his memory in ~/recordings/cameras. とあるので、撮影された画像はPepper内のファイルシステムの (ホームディレクトリ)/recordings/cameras/ に保存されます。画像ファイル名はパラメータに File Name という項目があり、ここで指定することができます。

take-picture-param.png

タブレットShow Imageボックスにおける画像読み込み元パス

タブレットに画像を表示するためには tabletボックスライブラリ > tablet > Show Imageボックスが利用できますが、このボックスのImage Urlの説明は以下のようになっています。

show-image-desc.png

Pepperチュートリアル (5):タブレットを使う で詳しく説明していますが、アプリケーションを構成するファイル([プロジェクトの内容]パネルで示されるファイル構成ツリ)ーのうち、 html ディレクトリ以下のファイルがタブレットに表示することができるようになっています。

project-content-html.png

つまり、Take Pictureボックスで撮影した内容を、アプリケーションの html ディレクトリに保存することができれば、Show Imageボックスで表示できるようになります。

実装例

では、Take Pictureボックスで画像を撮影し、Show Imageボックスでタブレットに表示するアプリケーションを作ってみます。

なお、Pepperのタブレットに動的に作成したファイルを表示する際は、キャッシュを回避する工夫が必要になりますので、これは別に説明します。

つくってみる

  1. 以下のボックスを配置します

    • standardボックスライブラリ > Vision > Take Picture
    • tabletボックスライブラリ > tablet > Show Image

    boxes.png

  2. ボックスを以下のように接続します

    connections.png

  3. Take Pictureボックスの保存先が、アプリケーションの html ディレクトリになるように変更します。Take Pictureボックスをダブルクリックし、以下のようにコードを変更します。
    a. onLoadメソッドの先頭に ALFrameManager へのアクセス用オブジェクトを生成するコードを追加します

    def onLoad(self):
        # 追加コード: ここから
        self.framemanager = ALProxy("ALFrameManager")
        # 追加コード: ここまで
        self.bIsRunning = False
        ...
    

    b. onInput_onStartメソッドの先頭に、htmlディレクトリのパスを取得するコードを追加します

    def onInput_onStart(self):
        # 追加コード: ここから
        import os
        self.recordFolder = os.path.join(
                    self.framemanager.getBehaviorPath(self.behaviorId), "../html")
        # 追加コード: ここまで
        if( self.bIsRunning ):
            return
        ...
    
  4. Show Imageボックスのパス問題回避のため、Show Imageボックスをダブルクリックし、_getAppNameメソッドに以下のコードを追加します

    def _getAppName(self):
        import os
        if self.frameManager:
            behaviorPath = os.path.normpath(self.frameManager.getBehaviorPath(self.behaviorId))
            appsFolderFragment = os.path.join("PackageManager", "apps")
            if not (appsFolderFragment in behaviorPath):
                self.logger.error("appsFolderFragment is not in behaviorPath")
            fragment = behaviorPath.split(appsFolderFragment, 1)[1]
            # 追加コード: ここから
            fragment = fragment.split('/')[1]
            # 追加コード: ここまで
            return fragment.lstrip("\\/")
        else:
            self.logger.warning("No ALFrameManager")
    
  5. 各ボックスの保存先ファイル名を設定します。Take Pictureボックスのほうは拡張子なし、Show Imageボックスのほうは拡張子あり(.jpg)である必要があります

    take-picture-box-param.png

    show-image-box-param.png

  6. 画像の保存先となる html ディレクトリを作成し、適当なダミーファイルをインポートしておきます
    a. プロジェクトの内容パネルの追加ボタンをクリックし、[ディレクトリの作成...] をクリックします
    create-html-directory.png

    b. [ファイルのインポート...] をクリックすると、ファイル選択ダイアログが開きます。適当なダミーファイルを選択します。
    add-image.png

    c. ダミーファイルをドラッグし、htmlディレクトリ内に移動します
    move-image.png
    これで画像ファイルがタブレットで表示可能な状態になりました。

これで、タブレット表示用の html ディレクトリに対して撮影したデータを保存するTake Pictureボックス、この撮影したデータを表示するShow Imageボックスの準備ができました。

動作確認

Pepperに接続し、[ロボットにアップロードして再生]ボタンを押すと、Pepperのカメラが撮影した内容がタブレットに表示されます。

タブレットのキャッシュの回避

このアプリケーションを複数回実行しても、タブレットの内容が更新されないという現象が発生します。

これは、タブレットのWebブラウザが画像をキャッシュしてしまっているためです。これを回避する方法としては、実行時の時間をURLのクエリに含めてあげる方法があります。
Show Imageボックスの onInput_onStart メソッドに以下のようなコードを追加することで、この問題を回避することができます。

    def onInput_onStart(self):
        # 追加コード: ここから
        import time
        # 追加コード: ここまで
        # We create TabletService here in order to avoid
        # problems with connections and disconnections of the tablet during the life of the application
        tabletService = self._getTabletService()
        if tabletService:
            try:
                url = self.getParameter("ImageUrl")
                if url == '':
                    self.logger.error("URL of the image is empty")
                if not url.startswith('http'):
                    url = self._getAbsoluteUrl(url)
                # 追加コード: ここから
                url += "?" + str(time.time())
                # 追加コード: ここまで
                tabletService.showImage(url)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away