Pepperのカメラ映像をディスプレイに描画する

### 実践したこと
[QRコードカメラプレビュー](https://qiita.com/Atelier-Akihabara/items/b58901802eaaa1ef0df3)の記事を参考に、Pepperのカメラの映像をディスプレイで確認出来るようにしました。ソースコードの一部を書き換えただけなので、GitHubから[サンプルコード](https://github.com/Atelier-Akihabara/pepper-qrpreview-example)を入手して来ることをおすすめします。

### 手法
詳しいことは先程のリンクに丁寧に記載されているので、ここではざっくりとした手法の解説をしたいと思います。
1. ALTabletServiceからindex.htmlを表示しqimessageingを使用
2. ALVideoDeviceで値を引き出すハンドラ(self.subscriberId)をALMemoryに格納
3. ALMemoryに格納したハンドラを用いてALVideoDeviceから画像の値を取得
4. 値をディスプレイに描画
### コードの書き換え部分
まず`choregraphe/QR Preview/Subscribe Camera`の一部を書き換えます。


```python:
def onInput_onStart(self):
        fps = 10
        if self.subscriberId is None:
            self.subscriberId = self.videoDevice.subscribeCamera("QRPreview",
                    0, # TopCamera
                    7, # AL:kQQQVGA
                    0, # AL::kYuvColorSpace 
                    fps)
        self.memory.raiseEvent("ProgrammingPepperSample/PreviewMode", self.subscriberId)
        self.onSubscribed(self.subscriberId)

```
```Python
self.subscriberId = self.videoDevice.subscribeCamera("QRPreview",
                    0, # TopCamera
                    7, # AL:kQQQVGA
                    11, # AL::kYuvColorSpace >> AL::kRGBColorSpace
                    fps)

```
この3つ目の数値を[Pepperの2Dカメラ-公式ドキュメントのリンク](http://doc.aldebaran.com/2-0/family/juliette_technical/video_juliette.html)を参考に変更します。今回は画像のRGB値が欲しいので11とします。(サンプルコードだと0)
<br><br>
次に`html/scripts/main.js`を書き換えていきます。

```javascript:main.js
function getImage(ALVideoDevice, subscriberId) {
    ALVideoDevice.getImageRemote(subscriberId).then(function (image) {
        if(image) {
            var imageWidth = image[0];
            var imageHeight = image[1];
            var imageBuf = image[6];
            console.log("Get image: " + imageWidth + ", " + imageHeight);
            console.log(image);

            if (!context) {
                context = document.getElementById("canvas").getContext("2d");
            }
            if (!imgData || imageWidth != imgData.width || imageHeight != imgData.height) {
                imgData = context.createImageData(imageWidth, imageHeight);
            }
            var data = imgData.data;

            for (var i = 0, len = imageHeight * imageWidth; i < len; i++) {
                var v = imageBuf[i]; 
                data[i * 4 + 0] = v;
                data[i * 4 + 1] = v;
                data[i * 4 + 2] = v;
                data[i * 4 + 3] = 255;
            }

            context.putImageData(imgData, 0, 0);
        }
        
        if(previewRunning) {
            setTimeout(function() { getImage(ALVideoDevice, subscriberId) }, 100)
        }
    })
}
```
取得する画像情報がモノクロからRGB値に変更になりました。image[6]のimageBuf配列に格納されている一次元配列にR値、G値、B値の3つの値が順に格納されています。そこでfor文を用いてそれぞれの値を取得出来るように変更します。

```javascript:main.js
for (var i = 0, len = imageHeight * imageWidth; i < len; i++) {
                var r = imageBuf[3*i];
                var g = imageBuf[3*i+1];
                var b = imageBuf[3*i+2];
                data[i * 4 + 0] = r;
                data[i * 4 + 1] = g;
                data[i * 4 + 2] = b;
                data[i * 4 + 3] = 255;
            }
```
<br>
その他、ディスプレイに描画される範囲をもう少し大きくしたかったので`html/main.css`の`canvas`の値を変更しました。

```css:main.css

#canvas {
    position: relative;
    display: inline-block;
    width: 960px;
    height: 820px;
    margin: 10px 10px;
    padding: 0;
}
.canvas-background {
    position: static;
    display: inline-block;
    width: 980px;
    height: 840px;
    margin: 0;
    padding: 0;
    background-color: #555555;
}

```


### 実行結果
色付きでディスプレイに描画することができました！！
![IMG_6231.JPG](https://qiita-image-store.s3.amazonaws.com/0/216564/fb0a34e1-322f-0eab-1ad7-f547bf7465b9.jpeg)
![IMG_6232.JPG](https://qiita-image-store.s3.amazonaws.com/0/216564/24c22562-c505-5072-bff8-d8eebe15f7e7.jpeg)

### 雑談
Pepperのディスプレイに色付きでカメラ画像を描画するためには、画像の解像度をかなり落としてあげないと動作しません。色付きで見るか、モノクロでもう少し高解像度で見てあげるかのどちらがいいのかは正直難しいところがありますね...