Image Recognition


Introduction

 この事例はどのようにして、ビューファインダーの中の画像を認識して、画像で知れをオーバーレイするのかを示します。さらに、それがどのように複数の異なった画像を認識するのか、そして、オーバーレイされたエレメンツ上へのユーザークリックにどのように反応するのかを示します。

 

よりよい理解のために、ここでは、続く章と、他の章でARに関したドキュメンテ―ションで、いくつかの述語がつかわれます。

 

・Target ターゲット画像、そしてそれに関連した抽出されたデータは画像を認識するトラッカーで使われます。

・Traget collection  ターゲットのコレクションを収集したアーカイブ、それはトラッカーで認識されます。

 ターゲットコレクションは2つの異なったリソースタイプから来ます。

 ・何もされてないもの: 無垢のJPGまたはPNGフォーマットの画像を格納した通常のZIPファイル

 ・事前にプロセスされたもの: オフラインでより多くの画像を早いプロセスとストアーするための、

  WTCファイル(Wikitude Target Collection)にコンバートされた通常の画像

・Image Tracker: トラッカーがライブカメラ画像を分析し、それに関連したターゲットコレクションの中にストアーされたターゲットを見つけます。 複数のトラッカーを生成することができます。しかしながら、唯一1つのトラッカーだけが、どのように与えられた時間内でも、認識するために有効稼働します。

重要:どのように画像ターゲットを作成するのか

あなた自身の画像認識をする前に chapter on how to create Image Targets を確実に読んでください。

ターゲット上の画像(Image on Target)

これらの観点を心にとめて、実際に何が認識されなければならないターゲットか定義し、そして、トラッカーが使える、一致するターゲットコレクションを生成することから始めましょう。この場合、ターゲットコレクションは以下の単独マガジンのページを含みます。

 

サンプルを見るために、あなたはこのページ(on this page)の画像を使うことができます。

 

これは、ARchitect で画像認識をすることとすべて同じプロセスです。あなたはあなたのターゲットを定義し、それから、それのためにターゲットコレクションを生成する必要があります。では、画像認識ができるようにするために、JavaScript コードを見てみましょう。

// Initialize ImageTracker
// Important: If you replace the tracker file with your own, make sure to change the target name accordingly.
// Use a specific target name to match only a certain target or use a wildcard to match any or a certain group of targets.

this.targetCollectionResource = new AR.TargetCollectionResource("assets/magazine.wtc", {
});
this.tracker = new AR.ImageTracker(this.targetCollectionResource, {
    onTargetsLoaded: this.worldLoaded
});

// Create overlay for page one
var imgOne = new AR.ImageResource("assets/imageOne.png");
var overlayOne = new AR.ImageDrawable(imgOne, 1, {
    translate: {
        x: -0.15,
    }
});

var pageOne = new AR.ImageTrackable(this.tracker, "*", {
    drawables: {
        cam: overlayOne
    }
});
view source code on GitHub

最初に、認識エンジンをスタートさせるためにAR.ImageTrackerが生成されることが必要です。それは、ターゲットコレクションに特有のAR.TargetCollectionResourceによってイニシャライズされます。オプションのパラメーター(複数)は最後のARのObjectとして渡されます。この場合、onLoaded triggerの呼び戻し機能はセットされています。一旦、トリガーがすべてロードされれば、worldLoaded()の機能が呼び出されます。

 

次のステップはARの生成です。この例の中では、画像のリソースが生成され、AR.ImageDrawable.に渡されます。

ドローアブルは、AR.ImageTrackable や地図上に配置されるAR.GeoObjectなどのターゲット画像に接続される、目に見えるコンポーネントです。AR.ImageDrawableは画像とそのサイズでイニシャライズされます。オプションのパラメーターは認識されたターゲットに関連した位置につくことを許可します。

 

最後の行は、その前に生成されたトラッカーと、画像ターゲットの名前、そして、認識された画像をARにするドローアブルを持ったAR.ImageTrackable を生成することで、全てのものを結合させます。このケースでは、ターゲット名はWildcardですが、Wildcardは、ターゲットコレクションの中でどんなターゲットにも合うように使うことができることを記憶して下さい。もし、あなたが具体的なターゲットを特別な AR.ImageTrackable にのみ合わせようとするならば、単純にターゲットコレクションの中で定義されたターゲット名を与えて下さい。

あなた自身の画像を認識する
  1. あなたの画像を Wikitude Studio (log-in required)にアップロードする 
  2. あなたのターゲットコレクションファイル (.wtc)を起動する
  3.  あなたのコードで AR.ImageTracker を生成し、前のステップからターゲットコレクションファイルをロードする 
  4. AR.ImageTrackable を生成し、ターゲット名を付ける
ARで使うターゲット名を明確にします。 AR.ImageTrackableはあなたのターゲットコレクションの中でターゲット名の一つを一致させます。あなたは同じく、どのようなターゲットでも、または、唯一の具体的な目的をもったターゲットでも、合わせるためにWildcardを使用できます。Wildcardについての情報のための更なる詳細はAR.ImageTrackableメインドキュメンテ―ション参照してください。

異なったターゲット

ターゲットコレクションに異なったターゲットを追加するのは容易です。単純に Target Managementでガイドに従ってください。ターゲットコレクションの中のそれぞれのターゲットはその targetNameによって定義されています。この targetNameを使うことによって、ターゲットコレクションの中のすべてのターゲットのためにAR.ImageTrackable を生成することが可能です。

 

サンプルを見ることによって、あなたはこのページon this pageの画像を使うことができます。

// Create overlay for page two
var imgTwo = new AR.ImageResource("assets/imageTwo.png");
var overlayTwo = new AR.ImageDrawable(imgTwo, 0.5, {
    translate: {
        x: 0.12,
        y: -0.01
    }
});
var pageTwo = new AR.ImageTrackable(this.tracker, "pageTwo", {
    drawables: {
        cam: overlayTwo
    }
});

view source code on GitHub

最初の部分に似て、2番目のオーバーレイのための画像リソースとAR.ImageDrawable が生成されます。2番目のページのための AR.ImageTrackable は同じトラッカーを、違うターゲット名で使用します。

拡張認識範囲(Extended Recognition Range)

Wikitude 7.0で紹介された、Wikitude SDK画像認識エンジンは、遠くの画像を見つけるために、HDカメラフレームを使えるようにしました。遠距離、この意味は、このモードがない場合に比べて3倍の遠距離のことです。(例えば、A4サイズのターゲットが2.4mの範囲内で認識されます)。この機能は Image Recognition Extended Range と呼ばれAR.ImageTracker classの中でセットされることで起動されます。extendedRangeRecognition をセットすることはオプションで、下記の3つの決まった項目を受け入れます。

・ON  AR.CONST.IMAGE_RECOGNITION_RANGE_EXTENSION.ON

・OFF AR.CONST.IMAGE_RECOGNITION_RANGE_EXTENSION.OFF

・AUTO  AR.CONST.IMAGE_RECOGNITION_RANGE_EXTENSION.AUTO (デフォルト)

パイプラインの中でHDカメラフレームの操作を進めることはコンピュータ的にはより費用がかかります。このことは、もし、電話機がユーザーの動作を犠牲にすることなくこの追加の効果を扱う場合は、この機能のみが稼働するという意味です。AUTOセットは、可能なCPUパワーとカメラアクセス( 例えばアンドロイド向け Camera2 API  )をベースとして、それを決定します。そしてそれはSDKでのデフォルトセットです。

双方向性(Interactivity)

最後のステップは画像ターゲットに双方向性を付け加えることです。この例は、ウエブページを開くボタンがそれぞれのターゲットに付け加えられます。

 

ボタンは、オーバーレイ機能と同じように生成されます。AR.ImageResourceはボタンの形を定義します。そして、両方のボタンを再利用します。

this.imgButton = new AR.ImageResource("assets/wwwButton.jpg");
view source code on GitHub

それぞれのターゲットのために、ボタンのための AR.ImageDrawableがヘルプ機能createWwwButton(url, options).を使うことで生成されます。戻されたドローアブルはそれから、AR.ImageTrackableの生成で drawables.camアレーに付け加えられます。

var pageOneButton = this.createWwwButton("http://www.wikitude.com/pageone", 0.1, {
    translate: {
        x: -0.25,
        y: -0.25
    }
});
var pageOne = new AR.ImageTrackable(this.tracker, "pageOne", {
    drawables: {
        cam: [overlayOne, pageOneButton]
    }
});
view source code on GitHub

ボタンをクリックできるようにするonClick トリガーはAR.ImageDrawableの渡されるオプションの中に定義されます。一般的に、それぞれのドローアブルはそのonClick トリガーを定義することによってクリックできるようになります。

createWwwButton: function createWwwButtonFn(url, size, options) {
    options.onClick = function() {
        AR.context.openInBrowser(url);
    };
    return new AR.ImageDrawable(this.imgButton, size, options);
},
view source code on GitHub

クリックトリガーにアサインされた機能は 、AR.context.openInBrowserと呼ばれます。それは、ブラウザーで開く定義されたURLを持っています。

HTMLコンテンツを付け加える

 AR.HtmlDrawableを使うことは、画像が表示されると同じように、ARの風景の中にHTMLコンテンツを表示することが可能になります。この例の中では、気象ウイジットが画像ターゲットの上に、ハワイのマウイ島のリアルタイムの天気を表すために加えられています。

 

一般的には、HTMLコンテンツは関連した、またはそのもののURLを渡されることによってロードされることが可能になります。さらに、HTMLコンテンツはストリング(列)として渡されることが可能です。ドローアブルが生成される時に、どのようににコンテンツを定義するのか、さらに詳細を見たい時は、APIリファレンスを見てください。この例は関連したURLを気象ウイジットとして使っています。それは.htmlファイルとして事例アセットのサブホルダーにストアーされています。

 

一旦、コンテンツが選択されると、コンテンツが正しく置かれるために必要なビューポートについて考えることが重要です。ビューポートはHTMLコンテンツが描写された時に使用可能になるエリアです。それは、AR.HtmlDrawable がAR風景の中におかれた時にスクリーンの上に必要となる、独立した実際のエリアです。

 

ビューポートの幅と高さは、 AR.HtmlDrawableを作ると時にセットされる必要があります。そして、同じく、使われるHTMLコンテンツの内部にメタタグとしてセットされる必要があります。これはHTML描写エンジンに、描写中にある特定のビューポートサイズを使うことを告げます。

<meta name="viewport" content="target-densitydpi=device-dpi, width = 320, user-scalable = 0">
view source code on GitHub

幅の値がHTMLコンテンツが必要とする大きさ(解像度)にセットされたことを確認しましょう。それはまたAR.HtmlDrawableを生成する過程で定義された、viewportWidth の値と一致しなければなりません。

 

viewportWidthと同じように、viewportHeightがコンテンツを描写している過程で可能な解像度(画素)の高さを規定するために明確にされます。もし、その時あなたがHTMLの解像度のサイズを確信できない場合、測るために流行りのブラウザー(WebInspectorなど)の中の開発ツールを使うことができます。

 

下記のコード例の中に、私達は稼働するAR.HtmlDrawableをすべて一緒に押しこめました。生成されたドローアブルはAR.ImageTrackable ドローアブルのリストに他のドローアブルと同様に付け加えられました。

var weatherWidget = new AR.HtmlDrawable({
    uri: "assets/weather.html"
}, 0.25, {
    viewportWidth: 320,
    viewportHeight: 100,
    backgroundColor: "#FFFFFF",
    translate: {
        x:0.36,
        y: 0.5
    },
    horizontalAnchor: AR.CONST.HORIZONTAL_ANCHOR.RIGHT,
    verticalAnchor: AR.CONST.VERTICAL_ANCHOR.TOP,
    clickThroughEnabled: true,
    allowDocumentLocationChanges: false,
    onDocumentLocationChanged: function onDocumentLocationChangedFn(uri) {
        AR.context.openInBrowser(uri);
    }
});
var pageOne = new AR.ImageTrackable(this.tracker, "pageOne", {
    drawables: {
        cam: [overlayOne, pageOneButton, weatherWidget, sparkles]
    }
});
view source code on GitHub

AR.HtmlDrawable の相互作用はclickThroughEnabled allowDocumentLocationChanges プロパティでコントロールされます。clickThroughEnabled のセットすることは、クリックする動作を、リンクをフォローしたりボタンをクリックすることを可能にするHTMLコンテンツに進めます。もしHTML ドローアブルのコンテンツが変更されなければ、allowDocumentLocationChangesが失敗falseにセットされます。そうするとリンクはできません。それでもなお、onDocumentLocationChangedトリガーを使うことでクリックされたリンクに再チャレンジできます。事例は、クリックしたリンクをブラウザーでフルスクリーンで開くために、このトリガーを使っています。その結果はこの様です。

HTML ドローアブル リアルタイム天候ウイジット

特別提供:スパークルス

このセクションは上記の事例へのちょっとした特別提供(ボーナス)です。スプライトシートアニメーションは、アニメートされたGIFsと似たように画像をアニメーションするために使われます。そして、この事例の中ではスパークルスを加えてオーバーレイしています。

 

スプライトシートはアニメーションに要求されるすべてのキーフレーム画像を含んでいる画像ファイルです。キーフレーム画像のサイズ(幅と高さ)は生成時に現れ、すべてのキーフレーム画像は同じでなければなりません。キーフレーム画像はアレイの中で管理され、エントリー0でスタートします。キーフレーム画像アレイは左から右に連続で埋められます。スプライトシートの端でキーフレームで一杯になったどの部分も無視されます。

この事例のスパークルのスプライトシート

最初の画像リソースは、それがAR.AnimatedImageDrawableを生成するために使われるために生成されます。スプライトシートの幅と高さは512でそれは16個のキーフレームを持ちます。一つの画像の幅と高さは128です。そのため、私達は128を AR.AnimatedImageDrawableの幅と高さとしてセットします。

// Sparkles
var imgSparkles = new AR.ImageResource("assets/imageSparkles.png");
var sparkles = new AR.AnimatedImageDrawable(imgSparkles, 0.25, 128, 128, {
    translate: {
        x: -0.2,
        y: 0.5
    },
    rotate: {
        z: 75
    }
});
view source code on GitHub

アニメーションをスタートするために、キーフレームの命令がアレイとして渡される必要があります。さらに、それぞれのフレームの時間はmsで表示されます。そしてループカウントが定義される必要があります。このケースでは、それぞれの画像は、ー1のループカウントに変わり、それが無限ループでアニメーションを作動する前に、100ms表示されます。

sparkles.animate([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 100, -1);
view source code on GitHub

最後のステップはドローアブルとしてAR.ImageTrackable に追加されます。そうして、それは最初のページの上にかぶさります。

var pageOne = new AR.ImageTrackable(this.tracker, "pageOne", {
    drawables: {
        cam: [overlayOne, pageOneButton, weatherWidget, sparkles]
    }
});
view source code on GitHub

Solar Syetem(IR)

このデモでは、私達は、私達のユニークなソーラシステムの可視化のためにビジョンベースのARの能力と3Dモデルを結合します。この事例は見る人にソーラシステムのいくつかの惑星を見せます。そして、それぞれの惑星の基本情報を提供します。

完全なデモのスクリーンショット

ARはバックドロップから成り立ちます。それはオーバーライドされた画像と私達のソーラシステムの惑星を暗くするのに使われます。(冥王星まで含んでいます)。それぞれの惑星は、お互いに独立してアニメーションされたようにするため、分割された3Dモデルとしてロードされます。

惑星の3Dモデル 木星

事例のコードを見れば、価値がかかれたわずかなコンポーネントがあります。それぞれの惑星の詳細情報はplanetsInfoアレイに内蔵されています。それはそれぞれの惑星のAR.Model Objectを作成するために使われます。大きさと太陽からの距離によって、それぞれの惑星はtranslatescaleのプロパティを使うターゲットに位置しています。

 

バックドロップは単純なAR.ImageDrawableです。それは惑星(複数)を一緒にしてAR.ImageTrackable ドローアブルに追加されています。

var backdropImg = new AR.ImageResource("assets/backdrop.png");
var backdrop = [new AR.ImageDrawable(backdropImg, 2)];
view source code on GitHub

太陽の周りの円上に惑星をアニメーションするのは、複数のAR.PropertyAnimationを使うことで完成します。それはAR.AnimationGroupのなかに包含されています。createOrbitAnimation(planet, info)機能はこのアクションに必要なアニメーションを生成します。円は4分割されます。それはxとy軸のために異なったアニメーションを要求します。xとy軸のためのアニメーションは並行したアニメーションの中に結合されます。そして、要求された円運動を実現するために順番に稼働します。

 

最初に、惑星は静止し動きません。一旦、ユーザーがアニメーションボタンをクリックすれば、toggleAnimatePlanets() 機能が呼び出されます。それはアニメーションの現在の状態をチェックし、それに応じてアニメーションをスタート、停止、または再開をします。

 

別のデモの部分では、惑星の選択と選択された惑星の情報表示をします。それぞれの惑星のAR.Model onClickトリガーセットを持っています。それはplanetClicked()機能を呼び出します。このコールはHUD上の選択された惑星の情報を表示します。ヘルパー機能selectPlanet() screenClicked()は選択したアニメーションをアクティブとディアクティブし、以前に選択された惑星のscale propertyをリセットします。

ターゲット画像

サンプルを見るために、このページon this pageの画像を使うことができます。


ジェスチャー(Gesture)

Wikitude SDKは多くのジェスチャーをサポートしています。それによりARで相互の作用をすることができます。

この事例は、AR風景の中で、メガネ、ヒゲ、帽子の画像を取りだし(Drag)、回転し、測るために、3つのジェスチャーをどのように使うのか、そしてどのようにそれらを顔の上に張り付けることができるのかを示します。

ターゲット画像

AR.ImageDrawableが生成される時いつでも、あなたはどのジェスチャーが反応すべきか定義することができます。

 

このサンプルは3つの異なったジェスチャーのタイプを使います。:引き出す、回転させる、そして測る、そのどれもがジェスチャーのためのAR.ImageDrawableのリアクションを定義するため、3つの呼び出し機能(例えば、onDragBeganonDragChanged そして onDragEnded)を持っています。

 

この事例の中で、私達はAR.ImageDrawableがすべての3つのジェスチャータイプに反応することを望みます。

var overlay = new AR.ImageDrawable(imageResource, 1, {
    onDragBegan: function(x, y) {
        return true;
    },
    onDragChanged: function(x, y) {
        return true;
    },
    onDragEnded: function(x, y) {
        return true;
    },
    onRotationBegan: function(angleInDegrees) {
        return true;
    },
    onRotationChanged: function(angleInDegrees) {
       return true;
    },
    onRotationEnded: function(angleInDegrees) {
       return true;
    },
    onScaleBegan: function(scale) {
        return true;
    },
    onScaleChanged: function(scale) {
       return true;
    },
    onScaleEnded: function(scale) {
       return true;
    }
});

もし、あなたが、ただ一つのAR.ImageDrawable 割り当て表作りたいなら、これは基礎のインプリメンテーションです。

onRotationBegan: function(angleInDegrees) {
    return true;
},
onRotationChanged: function(angleInDegrees) {
   this.rotate.z = previousRotationValue + angleInDegrees;

   return true;
},
onRotationEnded: function(angleInDegrees) {
   previousRotationValue = this.rotate.z;

   return true;
}

すべてのonChanged コールバックは私達にジェスチャーが始まる時の値とその現在の値の間の違いを告げます。これがなぜ私達が AR.ImageDrawableの最後のローテーションの値を、ローテーションを正しく行うために、ジェスチャー(previousRotationValuの前にセーブしなければならない理由です。

 

私達は掴む(Drag)、測る(Scale)、そして移し替える(Rotate)、のただ一つだけを望みません、よって、私達はそれらAR.ImageDrawable の多くの例のそれぞれの値をセーブしなければなりません。

onRotationBegan: function(angleInDegrees) {
    return true;
},
onRotationChanged: function(angleInDegrees) {
   this.rotate.z = previousRotationValue[index] + angleInDegrees;

   return true;
},
onRotationEnded: function(angleInDegrees) {
   previousRotationValue[index] = this.rotate.z;

   return true;
}

いま、すべての単一のAR.ImageDrawable は、一致するアレイの中にその最後の大きさ、位置そして回転値を持っています。あなたはAR.ImageDrawableのサンプルを風景に付け加えた後で、あなたは一つの数値でそれらを周りに引きだし、2つの数値でそれらを交代させ、または、つねるジェスチャーでそれらを計測することができます。

オーバーレイされたターゲット画像

サンプルの中で、私達は変更可能なoneFingerGestureAllowed をどちらのジェスチャーが現在有効かよりよい決定のために使います。dragは、ただ一つの数値を使う唯一のジェスチャーです。そのため、二つの数値がスタートしたら直ちに停止する必要があります。このイベントに反応するコールバック機能はAR.context.on2FingerGestureStartedと呼ばれます。私達はoneFingerGestureAllowed を、この機能が呼び出されるどんな時の失敗falseにも備えて、セットします。

onDragBegan: function(x, y) {
    oneFingerGestureAllowed = true;

    return true;
},
onDragChanged: function(x, y) {
    if (oneFingerGestureAllowed) {
        this.translate = {x:previousDragValueX[index] + x, y:previousDragValueY[index] - y};
    }

    return true;
},
onDragEnded: function(x, y) {
    previousDragValueX[index] = this.translate.x;
    previousDragValueY[index] = this.translate.y;

    return true;
}

onDragChangedoneFingerGestureAllowedが本当true ならば、それがサポートされていることを唯一行います。そのことが私達が新しいドラッグが始まる時はいつでもそれをtrue にセットする理由です。

ターゲットへの距離

この章では、与えられたターゲットまでの距離をどのように計測するのかを示します。そして、計測された値でどのように変更に対応するのかを示します。

 

ARの風景は、ただ一つのターゲットを内蔵しているターゲットコレクションによる、先進的な画像認識サンプルのコードをベースにしています。

 

AR.ImageTrackerが生成されたならば、私達はターゲットの物理的なサイズを定義します。

 

ターゲットコレクションがすべてのターゲットの物理的なサイズの定義を含むことができるとしても、これはいつも必要なわけではありません。(さらに詳しくはTarget Managementをご覧ください)。

 

それぞれのターゲットのミリメートルの値とともに、physicalTargetImageHeightsオプションはこの目的のために使われます。

 

この事例のために、私達はターゲットが高さ252㎜の標準のA4サイズの紙に印刷されていることを確認しています。もしあなたのターゲットのサイズが違っていれば値をこれに変更してください。一方で、計測は非常な正確さは求めていません。

this.targetCollectionResource = new AR.TargetCollectionResource("assets/magazine.wtc");
this.tracker = new AR.ImageTracker(this.targetCollectionResource, {
    onTargetsLoaded: this.worldLoaded,
    physicalTargetImageHeights: {
        pageOne:    252
    }
});
view source code on GitHub

そうして、私達は、距離が変更された場合に呼び出されるコールバック機能と、イベントのトリガーとなる変更の始点をミリ単位で公表します。

var pageOne = new AR.ImageTrackable(this.tracker, "*", {
            drawables: {
                cam: overlayOne
            },
            distanceToTarget: {
                changedThreshold: 1,
                onDistanceChanged: function(distance) {
                    document.getElementById('distanceDisplay').innerHTML = "Distance from target: " + distance / 10 + " cm";
                    overlayOne.rotate.z = distance;
                }
            },
            onImageRecognized: this.removeLoadingBar,
            onImageLost: function() {
                document.getElementById('distanceDisplay').innerHTML = "Distance from target: unknown";
            },
            ...
view source code on GitHub

ドローアブルの定義は最初の章と全く同じです。

 

オプションのdistanceToTargetは、どのようにトラッカーが変更に対応するのかを記述しています。始点は1mmにセットされます。そして、コールバック機能がスクリーンのボタン上に値を表示します。そして、ユーザーがターゲットに向かって動く、または、それから離れるとARを変更します。

 

私達は同じく ImageLostトリガーを定義します。なぜならば、ターゲットが見えないと時は、私達はどんな情報も望まないからです。

拡張トラッキング(Extended Tracking)

拡張トラッキングはあなたがそれぞれのAR.ImageTrackable に分離してセットできるオプションです。このモードではWikitude SDKはユーザーの環境をスキャンし、オリジナルのターゲット画像がこれ以上見えない状況でも風景の追跡を維持しようとします。そのため、トラッキングはオリジナルターゲット画像の限界を超えて拡張されます。この機能の性能は、機器のコンピューティングパワー、バックグラウンドの質感、そしてObjectなど、色々な要素に依存します。

 

もし、ターゲットが拡張トラッキングできるとしても、ImageLostトリガーは、オリジナルターゲット画像がこれ以上見えないか、いったん、拡張トラッキングが妨げられると、呼び出されません。

 

もし、あなたがこの機能を必要としないのならば、高いCPUロードを避けるために、それを機能できないようにすることをお勧めします。

 

サンプルの中で、AR.ImageTrackableは、通常は、オプションenableExtendedTrackingtrueにセットされるという違いを定義されています。

 

もし、拡張トラッキングの品質について情報が必要ならば、下記の例のようなコールバック機能onExtendedTrackingQualityChangedを定義する必要があります。

var pageOne = new AR.ImageTrackable(this.tracker, "*", {
    drawables: {
        cam: [pipes]
    },
    enableExtendedTracking: true,
    onExtendedTrackingQualityChanged: function (targetName, oldTrackingQuality, newTrackingQuality) {
        var backgroundColor;
        var trackingQualityText;

        if ( -1 == newTrackingQuality ) {
            backgroundColor = '#FF3420';
            trackingQualityText = 'Bad';
        } else if ( 0 == newTrackingQuality ) {
            backgroundColor = '#FFD900';
            trackingQualityText = 'Average';
        } else {
            backgroundColor = '#6BFF00';
            trackingQualityText = 'Good';
        }
        var cssDivInstructions = " style='display: table-cell;vertical-align: middle; text-align: middle; width: 50%; padding-right: 15px;'";
        var messageBox = document.getElementById('loadingMessage');
        messageBox.style.backgroundColor = backgroundColor;
        messageBox.innerHTML = "<div" + cssDivInstructions + ">Tracking Quality: " + trackingQualityText + "</div>";
        messageBox.style.display = 'block';
    }
});

もし、ターゲット画像が消えても、これが可能なことで、トラッキングは続きます。


複数のターゲット(Multiple Targets)

kの事例は、複数の画像を同時にどのように認識しトラックするかを示します。さらに、どのようにしてトラックする画像間の、距離、移動、そして交代をするのかを示します。

 

よく理解するために、Image Recognition 3D Models のドキュメンテーションを先に読むことを進めます。

 

このページon this page 下記の画像をテストするために使ってください。恐竜の間の相互作用を見るために、画像を印刷し、別のカードに分けることをお勧めします。

var targetCollectionResource = new AR.TargetCollectionResource("assets/dinosaurs.wtc");

var tracker = new AR.ImageTracker(targetCollectionResource, {
    // To enable simultaneous tracking of multiple targets 'maximumNumberOfConcurrentlyTrackableTargets' has to be set.
    maximumNumberOfConcurrentlyTrackableTargets: 5, // A maximum of five images can be concurrently tracked.

    //Disables extended range recognition. The reason for this is that extended range recognition requires more processing power and with multiple targets the SDK is trying to recognize targets until the maximumNumberOfConcurrentlyTrackableTargets is reached and it may slow down the tracking of already recognized targets.
    extendedRangeRecognition: AR.CONST.IMAGE_RECOGNITION_RANGE_EXTENSION.OFF,
    ...
});

ドローアブルDrawablesを個別のImageTargetsに追加するためにImageTrackable.addImageTargetCamDrawables が使えます。

new AR.ImageTrackable(tracker, "*", {
    onImageRecognized: function (target) {
        var model = new AR.Model("assets/models/" + target.name + ".wt3");

        // Adds the model as augmentation for the currently recognized target.
        this.addImageTargetCamDrawables(target, model);
    }
    ...
});

ターゲット間の距離

この事例はターゲット間の距離をどのように使うのか示します。

 

ターゲット間の距離を得るには2つの方法があります。

1.ImageTarget.getDistanceTo はこの ImageTarget から通過した ImageTargetへ戻ります。

2.ImageTarget.onDistanceChanged は、トリガーになるこのImageTargetから、起点よりさらに変更された他の現在のトラックされた ImageTargetまでのどの距離でも得ます。起点は、(距離変更された起点上の)ImageTrackerのオプションで定義されます。パラメーター(複数)は距離と距離が計測されている ImageTargetを含んでいます。

var tracker = new AR.ImageTracker(targetCollectionResource, {
    maximumNumberOfConcurrentlyTrackableTargets: 5,
    onDistanceChangedThreshold: 10 // By setting this to 10, the distance between two targets has to change by 10mm before ImageTarget.onDistanceChanged is triggered again.
    ...
});

new AR.ImageTrackable(tracker, "*", {
    onImageRecognized: function (target) {
        var model = new AR.Model("assets/models/" + target.name + ".wt3");

        var idleAnimation = new AR.ModelAnimation(model, "Idle");
        idleAnimation.onFinish = idleAnimation.start;
        idleAnimation.start();

        this.addImageTargetCamDrawables(target, model);

        var jumpAnimation = new AR.ModelAnimation(model, "Jump");
        jumpAnimation.onFinish = jumpAnimation.start;

        // Trigger callback whenever the distance between the currently recognized target and another target change by more than the threshold defined in the AR.ImageTracker.
        target.onDistanceChanged = function (distance, otherTarget) {
            // start the jumpAnimation when the distance between this and another target gets below 150 mm
            if (distance < 150) {
                 jumpAnimation.onFinish = jumpAnimation.start;
                 idleAnimation.onFinish = function() {
                        jumpAnimation.start();
                 };
            }
        }
    }
});

ターゲット間の移動(Transformation Between Targets)

この事例はターゲット間の移動を示します。

 

この機能はターゲット間の移動と交代を含んでいます。

 

ターゲット間の移動には方法が2つあります。

1.ImageTarget.getTranslationToはこのImageTargetから通過したImageTargetへ移動を戻します。

2.ImageTarget.onTranslationChanged は、トリガーになるこのImageTargetから、起点よりさらに変更された他の現在のトラックされた ImageTargetまでのどの移動でも得られます。起点は、(移動変更された起点上の)ImageTrackerのオプションで定義されます。パラメーター(複数)は移動と移動が計測されている ImageTargetを含んでいます。

 

ターゲット間の交代には方法が2つあります。

1.ImageTarget.getRotationToはこのImageTargetから通過したImageTargetへ交代を戻します。

2.ImageTarget.onRotationChanged  は、トリガーになるこのImageTargetから、起点よりさらに変更された他の現在のトラックされた ImageTargetまでのどの交代でも得られます。起点は、(交代変更された起点上の)ImageTrackerのオプションで定義されます。パラメーター(複数)は交代と交代が計測されている ImageTargetを含んでいます。

注:移動と交代は、だれのonTranslation/-RotationChanged コールバックがトリガーされ、またはだれのgetTranslation/-Rotationが呼び出されるのか ImageTarget の調整するシステムがベースになっています。これは imageTarget1からimageTarget2 への移動は、imageTarget2から imageTarget1へのそれよりおそらく違います。

var tracker = new AR.ImageTracker(targetCollectionResource, {
    maximumNumberOfConcurrentlyTrackableTargets: 5,
    onRotationThreshold: 10 // By setting this to 10, the distance between two targets has to change by 10mm before ImageTarget.onDistanceChanged is triggered again.
    ...
});

new AR.ImageTrackable(tracker, "*", {
    onImageRecognized: function (target) {
        var model = new AR.Model("assets/models/" + target.name + ".wt3");

        var idleAnimation = new AR.ModelAnimation(model, "Idle");
        idleAnimation.onFinish = idleAnimation.start;
        idleAnimation.start();

        this.addImageTargetCamDrawables(target, model);

        // Trigger callback whenever the distance between the currently recognized target and another target change by more than the threshold defined in the AR.ImageTracker.
        target.onRotationChanged = function (rotation, otherTarget) {

            // If dinosaurs are facing each other and are within 150mm one should attack.
            if (rotation.z > 170 && rotation.z < 190 && target.getDistanceTo(destinationTarget) < 150) {
                ... // attacking animations
            }
        }
    }
});