実践したこと
QRコードカメラプレビューの記事を参考に、Pepperのカメラの映像をディスプレイで確認出来るようにしました。ソースコードの一部を書き換えただけなので、GitHubからサンプルコードを入手して来ることをおすすめします。
手法
詳しいことは先程のリンクに丁寧に記載されているので、ここではざっくりとした手法の解説をしたいと思います。
- ALTabletServiceからindex.htmlを表示しqimessageingを使用
- ALVideoDeviceで値を引き出すハンドラ(self.subscriberId)をALMemoryに格納
- ALMemoryに格納したハンドラを用いてALVideoDeviceから画像の値を取得
- 値をディスプレイに描画
コードの書き換え部分
まずchoregraphe/QR Preview/Subscribe Camera
の一部を書き換えます。
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)
self.subscriberId = self.videoDevice.subscribeCamera("QRPreview",
0, # TopCamera
7, # AL:kQQQVGA
11, # AL::kYuvColorSpace >> AL::kRGBColorSpace
fps)
この3つ目の数値をPepperの2Dカメラ-公式ドキュメントのリンクを参考に変更します。今回は画像のRGB値が欲しいので11とします。(サンプルコードだと0)
次にhtml/scripts/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文を用いてそれぞれの値を取得出来るように変更します。
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;
}
その他、ディスプレイに描画される範囲をもう少し大きくしたかったので`html/main.css`の`canvas`の値を変更しました。
#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;
}
実行結果
雑談
Pepperのディスプレイに色付きでカメラ画像を描画するためには、画像の解像度をかなり落としてあげないと動作しません。色付きで見るか、モノクロでもう少し高解像度で見てあげるかのどちらがいいのかは正直難しいところがありますね...