クラウド認識
このサンプルは、クラウド上の画像を認識して、AR.ImageTracker
クラスを使用しイメージをオーバーレイする方法を示します。
このサンプルは、ワインラベルを認識し拡張する事例に基づきます。世界中から集めたワインラベルのターゲットを含むターゲットコレクションがWikitudeサーバーにすでにセットアップされています。
単一画像の認識
対応するサンプルタイトル名「Basic Recognition On: Click」
このセクションで説明するサンプルは、以下にあるワインラベルを認識し、拡張します。これら3つのサンプルはすべて、概ね同様の実装となっていますが、サンプル毎に部分的に機能がカスタマイズされています。
このセクションでは公開されているクラウドアーカイブを使用することに注意してください。Wikitude SDKで使用できるクラウドアーカイブを独自に作成する方法については、Manager APIのドキュメントを参照してください。
地域サーバーのエンドポイント
最初に、SDKの接続対象となるWikitudeの地域分散型サーバーを選択する必要があります。
以下のいずれかの定数でAR.context.setCloudRecognitionServerRegion
関数を呼び出すことによってCloud Recognitionサーバーの地域を選択することができます。
AR.CONST.CLOUD_RECOGNITION_SERVER_REGION.AMERICAS
AR.CONST.CLOUD_RECOGNITION_SERVER_REGION.EUROPE
デフォルト値は、Europe
です。正しくない値が設定されている場合、SDKはEurope
を選択します。
それでは、最初のサンプルのJavaScriptコードの最初の部分 - init
関数から見ていきます。
init: function initFn() {
this.createTracker();
this.createOverlays();
},
ワインが認識されたら、その評価、ワインラベル、および認識されたワインの名前(後のパート)をエンドユーザーに示すバナーを表示します。処理をシンプルにするため、すべてのターゲットで同じバナー画像を再利用します。そのため、バナー画像を一度ロードするだけで何度も再利用できます。これはcreateOverlays
関数(上記のinit
関数で2番目に呼び出す関数)で行います。
createOverlays: function createOverlaysFn() {
this.bannerImg = new AR.ImageResource("assets/banner.jpg");
this.bannerImgOverlay = new AR.ImageDrawable(this.bannerImg, 0.4, {
translate: {
y: -0.6
}
});
},
まず画像リソースを作成し、それをAR.ImageDrawable
に渡します。AR.ImageDrawable
は、画像認識型AR(AR.ImageTrackable
)またはロケーションベース型AR(AR.GeoObject
)で使用できる2D拡張オブジェクトです。画像とそのサイズを指定してAR.ImageDrawable
を初期化します。さらに、オプションパラメーターを使用して、ターゲットに対する相対的な位置を指定します。
これらの下準備が済んだら、init
関数で最初に呼び出すcreateTracker
関数に進みます。
createTracker: function createTrackerFn() {
World.cloudRecognitionService = new AR.CloudRecognitionService("b277eeadc6183ab57a83b07682b3ceba", "54e4b9fe6134bb74351b2aa3", {
onInitialized: this.trackerLoaded,
onError: this.trackerError
});
World.tracker = new AR.ImageTracker(this.cloudRecognitionService, {
onError: this.trackerError
});
},
上記のコードを見るとわかるように、AR.CloudRecognitionService
に3つのパラメーターを渡しています。最初のパラメーターはClient API認証トークンを表しており、上のサンプルでは公開されているWikitude認証トークンを使用しています。認証トークンの詳細については、このセクションを参照してください。2番目のパラメーターはターゲットコレクションIDを表します。この一意のIDは、AR.CloudRecognitionService
が、認証トークンに接続されているすべてのクラウドアーカイブの中からどのクラウドアーカイブを使用するかを識別します。オプションパラメーターは、最後の引数でオブジェクトとして渡します。このケースでは、onLoaded
トリガーとonError
トリガーのコールバック関数を設定しています。
AR.CloudRecognitionService
のロードが完了すると、onInitialized()
関数が呼び出されます。AR.ImageTracker
の初期化中に問題が発生した場合は、trackerError()
関数が呼び出されます。特に大規模なクラウドアーカイブを扱うときは、初期化に数秒かかる場合があります。
onInitialized()
関数の呼び出しが完了したら、[Scan]ボタンをユーザーに表示します。このボタンをクリックすると画像認識処理が始まり、現在のカメラビューがCloud Recognitionサーバーに送信されます。このボタンのonClick
トリガー関数は以下のとおりです。
scan: function scanFn() {
World.cloudConnection.recognize(this.onRecognition, this.onRecognitionError);
},
ユーザーが[Scan]ボタンをクリックすると、上で作成したAR.CloudRecognitionService
のrecognize関数が呼び出されます。このrecognize関数には2つのコールバック関数を渡します。最初のコールバック関数は、毎回認識サイクルが終わるたびにSDKによって呼び出されます。2番目のコールバック関数は、指定されたクラウドアーカイブで問題が発生した場合に呼び出されます。
最初のコールバック関数、onRecognition
を以下に示します。
onRecognition: function onRecognitionFn(recognized, response) {
if (recognized) {
if (World.wineLabel !== undefined) {
World.wineLabel.destroy();
}
if (World.wineLabelOverlay !== undefined) {
World.wineLabelOverlay.destroy();
}
World.wineLabel = new AR.ImageResource("assets/" + response.targetInfo.name + ".jpg");
World.wineLabelOverlay = new AR.ImageDrawable(World.wineLabel, 0.3, {
translate: {
x: -0.5,
y: -0.6
},
zOrder: 1
});
if (World.wineLabelAugmentation !== undefined) {
World.wineLabelAugmentation.destroy();
}
World.wineLabelAugmentation = new AR.ImageTrackable(World.tracker, response.targetInfo.name , {
drawables: {
cam: [World.bannerImgOverlay, World.wineLabelOverlay]
}
});
} else {
document.getElementById('errorMessage').innerHTML = "<div class='errorMessage'>Recognition failed, please try again!</div>";
setTimeout(function() {
var e = document.getElementById('errorMessage');
e.removeChild(e.firstChild);
}, 3000);
}
},
このコールバック関数の最初のパラメーターは、サーバーがターゲットを認識できたかどうかを示すブール値です。その値は、認識結果に応じて0
または1
になります。2番目のパラメーターは、認識されたターゲットに関するメタデータを含むJSONオブジェクトです。ターゲットが認識された場合、このJSONオブジェクトにはtargetInfo
という名前の別のJSONオブジェクトが含まれます。このオブジェクトには、ターゲット名(targetName
)、その星評価(rating
)、および物理的な高さ(オプション)が格納されています。ターゲットが認識されなかった場合、JSONオブジェクトは空になります。responseオブジェクトについては、次のパートで詳しく説明します。
認識が成功した場合、バナーを拡張表示します。認識されたワインラベルをすでに作成したバナーの前面に表示するため、別の拡張オブジェクトを定義しています。responseオブジェクトに含まれるtargetInfo.name
プロパティを読み取って、同じ名前の画像ファイルをロードします。バナーの前面に配置するため、zOrder
プロパティを1(デフォルト値は0)に設定します。
その後で、ImageTracker、ターゲットの名前(targetInfo.name)、および拡張オブジェクトを使用して、すべてのものを集約したAR.ImageTrackable
を作成します。
認識が失敗した場合は、エラーメッセージをユーザーに表示します。
連続認識モードと随時認識モードの比較
対応するサンプルタイトル名「Continuous Recognition VS On: Click」
このパートのサンプルは、最初のパートを基に作成します。関係のある変更箇所のみを示します。先に進む前に前のパートを読み返してください。
前のパートのサンプルでは、画像の認識を随時手動で起動しました(ユーザーが[Scan]ボタンをクリック)。この方法が便利な場合もありますが、このパートで説明する連続認識モードを使用したいこともあります。大きな違いは、認識が手動のクリックによって1回だけ起動されるのではなく、定義された時間間隔で連続的に起動されることです。
この機能を有効にするために必要な変更を見ていきます。
最初の変更は'trackerLoaded'関数にあります。前のサンプルではユーザーに指示を表示するだけでしたが、今回は連続認識モードの起動も行います。
trackerLoaded: function trackerLoadedFn() {
this.startContinuousRecognition(750);
this.showUserInstructions();
},
startContinuousRecognition
関数をパラメーター750
を指定して呼び出します。このパラメーターは、認識を開始する頻度を示す時間間隔を表します。startContinuousRecognition
関数のコードを以下に示します。
startContinuousRecognition: function startContinuousRecognitionFn(interval) {
this.cloudRecognitionService.startContinuousRecognition(interval, this.onInterruption, this.onRecognition, this.onRecognitionError);
},
上記の関数では、AR.CloudRecognitionService
のstartContinuousRecognition
関数を呼び出して連続認識モードを開始しています。4つのパラメーターを渡しており、最初のパラメーターは前述したとおり、新しい認識を開始する時間間隔です。単位はミリ秒で、最小値は500
です。2番目のパラメーターは、認識間隔が現在のネットワーク速度に対して高すぎる場合、SDKによって呼び出されるさらに別のコールバック関数を定義します。3番目のパラメーターは、認識サイクルが完了したときのonRecognitionError
コールバックを定義します。最後の4番目のパラメーターは、さらにもう1つコールバック関数を定義します。この関数は、設定された認識間隔が現在のネットワーク速度に比べて短すぎる場合にSDKによって呼び出されます。
次に、コールバック関数に対する変更を示します。onRecognition
関数の変更はごくわずかで、onRecognitionError
関数には変更はありません。onInterruption
は新しいコールバック関数です。
最初にonRecognition
関数を示します。
onRecognition: function onRecognitionFn(recognized, response) {
if (recognized) {
if (World.wineLabel !== undefined) {
World.wineLabel.destroy();
}
if (World.wineLabelOverlay !== undefined) {
World.wineLabelOverlay.destroy();
}
World.wineLabel = new AR.ImageResource("assets/" + response.targetInfo.name + ".jpg");
World.wineLabelOverlay = new AR.ImageDrawable(World.wineLabel, 0.27, {
translate: {
x: -0.5,
y: -0.6
},
zOrder: 1
});
if (World.wineLabelAugmentation !== undefined) {
World.wineLabelAugmentation.destroy();
}
World.wineLabelAugmentation = new AR.ImageTrackable(World.tracker, response.targetInfo.name , {
drawables: {
cam: [World.bannerImgOverlay, World.wineLabelOverlay]
}
});
}
},
唯一の変更は、認識が失敗したときのエラーメッセージを除去したことです。連続認識モードでは、ユーザーが実際のターゲットにカメラを向けていないときなど、認識の失敗はかなり頻繁に起こります。
次のonInterruption
関数は、前のサンプルでは必要ありませんでした。この関数のコードは以下のとおりです。
onInterruption: function onInterruptionFn(suggestedInterval) {
World.cloudRecognitionService.stopContinuousRecognition();
World.cloudRecognitionService.startContinuousRecognition(suggestedInterval);
},
現在のネットワーク速度が設定された時間間隔に比べて十分でない場合、現在のネットワーク速度に見合った推奨される時間間隔を指定してこのコールバック関数が呼び出されます。新しい時間間隔を設定するため、連続認識モードが再起動されます。
このサンプルでは、AR.CloudRecognitionService
の連続認識モードを有効にする方法を示しました。次のサンプルでは、サーバーのresponseオブジェクトとカスタムメタデータを使用する方法を説明します。
応答に含まれるメタデータの使用
対応するサンプルタイトル名「Using Response Metainformation」
前のパートと同様に、このパートのサンプルも前回のパートを基に作成します。このパートに進む前に、もう一度前の2つのパートを読み返してください。
このパートでは、エンドユーザー向けの拡張オブジェクトをもう1つ追加します。今回も基となる拡張オブジェクトははどのターゲットの場合も同じなので、createOverlays
関数で一度だけ作成します。この関数のコードは以下のとおりです。
createOverlays: function createOverlaysFn() {
this.bannerImg = new AR.ImageResource("assets/bannerWithNameField.jpg");
this.bannerImgOverlay = new AR.ImageDrawable(this.bannerImg, 0.4, {
translate: {
y: 0.6
}
});
this.orderNowButtonImg = new AR.ImageResource("assets/orderNowButton.png");
this.orderNowButtonOverlay = new AR.ImageDrawable(this.orderNowButtonImg, 0.3, {
translate: {
y: -0.6
}
});
},
新しく表示する拡張オブジェクトは、[Order Now]ボタンです。このボタンは、これまでの拡張オブジェクトと同じように作成します。
さらに、'onRecognition'関数を以下のように変更します。
onRecognition: function onRecognitionFn(recognized, response) {
if (recognized) {
if (World.wineLabelOverlay !== undefined) {
World.wineLabel.destroy();
}
if (World.wineLabelOverlay !== undefined) {
World.wineLabelOverlay.destroy();
}
World.wineLabel = new AR.ImageResource("assets/" + response.targetInfo.name + ".jpg");
World.wineLabelOverlay = new AR.ImageDrawable(World.wineLabel, 0.2, {
translate: {
x: -0.37,
y: 0.55
},
zOrder: 1
});
World.wineName = new AR.Label(response.metadata.name, 0.06, {
translate: {
y: 0.72
},
zOrder: 2
});
if (World.wineLabelAugmentation !== undefined) {
World.wineLabelAugmentation.destroy();
}
World.wineLabelAugmentation = new AR.ImageTrackable(World.tracker, response.targetInfo.name , {
drawables: {
cam: [World.bannerImgOverlay, World.wineLabelOverlay, World.wineName]
}
});
World.orderNowButtonOverlay.onClick = function() {
AR.context.openInBrowser(response.metadata.shop_url);
}
if (World.orderNowAugmentation !== undefined) {
World.orderNowAugmentation.destroy();
}
World.orderNowAugmentation = new AR.ImageTrackable(World.tracker, response.targetInfo.name, {
drawables: {
cam: World.orderNowButtonOverlay
}
});
}
},
クラウドアーカイブを作成したとき、すべてのターゲットのカスタムメタデータが定義されました。メタデータの内容は必要に応じて自由に定義することができます。ターゲットのメタデータを追加する方法については、Manager APIのAPIリファレンスを参照してください。このサンプルでは、以下の2つのフィールドを作成しました。
metadata.name
: ワインの実際の名前。metadata.shop_url
: そのワインを販売しているオンラインショップのURL。
上記のメタデータを含むターゲットを、Manager APIでターゲットを作成するときのJSONは以下のようになります。
"metadata":{
"name":"Lote 43 Cabernet Sauvignon-Merlot",
"shop_url":"http://loja.miolo.com.br/ch/index.aspx"
}
ワインの名前をバナーに表示するため、AR.Label
を作成します。最初のパラメーターはラベルのテキスト、2番目のパラメーターはSDU単位の高さ、3番目のパラメーターセットは任意指定のオプションです。AR.Label
の最初のパラメーターを設定するため、カスタムメタデータオブジェクトから前述のname
を読み取ります。サーバーから返されたresponseオブジェクトはJSONオブジェクトなので、ドット記法を使用できます。
作成したAR.ImageDrawable
オブジェクトと同様に、AR.Label
をAR.ImageTrackable
に追加して、バナーに表示するものすべてを集約します。
次に、orderNowButtonOverlay
にonClick
トリガーを追加し、そこでAR.context
クラスを使用してブラウザでオンラインショップ開きます。この場合もサーバーのresponseオブジェクトとカスタムメタデータを使用して、shop_url
からオンラインショップのURLを読み取っています。