📖

⑨[android][vuforia][ar]Vuforia(Image Target)を独自マーカーで複数検出させてみた。

に公開

第1回 VuforiaでARの初めの一歩
第2回 Vuforiaのサンプルコード(Image Targetのみ)を動かしてみた。
第3回 動画再生を板ポリ上で実行するサンプルコードを作ってみた。
第4回 Vuforiaで動画再生ARを実装してみた。
第5回 Vuforia11.4.4の公式サンプルコードを動かしてみた。
お薦めしません: 第6回 VuforiaのVuMarkを動かしてみた。
お薦めしません: 第7回 Vuforiaで独自VuMarkを作ってみた。←挑戦中 ←無理ゲーすぎた
第8回 Vuforia(Image Target)を独自マーカーで動かしてみた。
第9回 Vuforia(Image Target)を独自マーカーの複数検出させてみた。


左画像は青枠の中で3Dモデル表示 右画像は赤枠の中で動画再生が出来ている。


画像の同時検出もできている。

いったんここが区切りかな。一応動くので。
まだ データセット(xml/dat) をSDカードから読み込めるようにするとか、動画再生をストリーム再生に対応するとかやりたいことあるので、そこは気が向いたらやります。

ソースコードはここ↓
https://github.com/aaaa1597/AndKot-OriginalMultipleImageMarkerVideoPlayBack

Abstruct

  • 独自マーカーでImage Targetを複数検知させてみた。
  • Vuforiaのバージョン 11.4.4。
    ※とはいえ、同時に両方検知とはいかないみたい。たぶん制限してんだろうな。

背景

第8回で言ってた通り、複数のARマーカーの検知をします。

ざっくり手順

  1. 2つ目のマーカを作成(Vuforiaサイトで)※1つ目は第8回で使ったマーカーです。
  2. githubからソースコード取得
  3. プロジェクトに組み込み → ビルド

準備

  • android端末
  • 開発用PC(Android Studioのインストールは済ませておく。)
  • android端末をつないで、デバッグができる様にしておく。
  • SDKと公式サンプルコードは今回一緒にgithubにコミットしたんで不要。
  • Vuforiaのアカウント作成 前回の説明の準備1をやっておく。
  • Vuforiaのライセンスキー取得 前回の説明の準備2をやって取得しておく。

手順1. 2つ目のマーカを作成(Vuforiaサイトで) → データセット(xml/dat)取得

  1. 2つ目のマーカーを準備
    2つ目のマーカーは、下記画像を準備した。
    MS Paintのクレヨンで適当に線を引いただけ。

    ※中身はいつでも差し替えれる様に枠だけ。

  2. Vuforiaサイトで画像の追加登録 → データセット取得
    このあたりは、第8回の手順2.3.と同じなのでそっち参照してください。

偶然の発見だけど、MS PaintのクレヨンはVuforiaの特徴認識アルゴリズムと相性がいいらしい。


びっくりするんだけど、認識精度星5つ!!


特徴点ビッシリ!!

手順2. githubからソースコード取得

下記コードをClone(or zipダウンロード)。
https://github.com/aaaa1597/AndKot-OriginalMultipleImageMarkerVideoPlayBack

手順3. プロジェクトに組み込み → ビルド

  1. Android Studioでプロジェクトを開く。
    cloneしたAndKot-VuforiaVideoPlaybackを開く。

  2. 認証情報を設定した後、ビルドする。
    Vuforiaのライセンス画面を開いて license Key をコピー。

            ↓
Android Studioで、"AppController.cpp"を開き、licenseKeyに、準備2でコピーしたライセンスを貼り付けます。
そして、ビルド。

※もし、この手順を飛ばしたら、アプリ起動時に下記エラーが発生します。

  1. 手順1でDLしたvuforiaのデータセット(.xml/.dat)をプロジェクトに組み込む

ゲットした bbb.zip は解凍するとbbb.xml / bbb.datの2ファイルが出来るので、その2つをAndroid プロジェクトに追加する。

app/
└── src/
    └── main/
        └── assets/
            └── original/
                ├── bbb.dat
                └── bbb.xml

ちなみにbbb.xmlの中身は、name="002_cleyon"とname="001_stones_jpg"の2つ登録されているのが分かる。

<?xml version="1.0" encoding="UTF-8"?>
<QCARConfig>
  <Tracking>
    <ImageTarget name="002_cleyon" size="0.100000 0.069915" />
    <ImageTarget name="001_stones_jpg" size="0.100000 0.069915" />
  </Tracking>
</QCARConfig>
  1. ソース修正。
    createImageTargetList()を新規追加。
    getImageTargetResult()に引数追加。
AppController.h(102-103)
+   std::pair<std::unique_ptr<VuObservationList, decltype(&vuObservationListDestroy)>, int> createImageTargetList();
-   bool getImageTargetResult(VuMatrix44F& projectionMatrix, VuMatrix44F& modelViewMatrix, VuMatrix44F& scaledModelViewMatrix, VuVector2F& markerSize);
+   bool getImageTargetResult(const VuObservation* observation, VuMatrix44F& projectionMatrix, VuMatrix44F& modelViewMatrix, VuMatrix44F& scaledModelViewMatrix, VuVector2F& markerSize, std::string& targetName);

新規追加のcreateImageTargetList()を実装。

AppController.cpp(384-402)
+std::pair<std::unique_ptr<VuObservationList, decltype(&vuObservationListDestroy)>, int>
+AppController::createImageTargetList() {
+    VuObservationList* observationList = nullptr;
+    REQUIRE_SUCCESS(vuObservationListCreate(&observationList));
+
+    if (vuStateGetImageTargetObservations(mVuforiaState, observationList) != VU_SUCCESS) {
+        LOG("Error getting image target observations");
+        REQUIRE_SUCCESS(vuObservationListDestroy(observationList));
+        std::unique_ptr<VuObservationList, decltype(&vuObservationListDestroy)> _null_ptr_(nullptr, &vuObservationListDestroy);
+        return std::make_pair(std::move(_null_ptr_), 0);
+    }
+
+    int numObservations = 0;
+    REQUIRE_SUCCESS(vuObservationListGetSize(observationList, &numObservations));
+
+    std::unique_ptr<VuObservationList, decltype(&vuObservationListDestroy)> retptr(observationList, &vuObservationListDestroy);
+    return std::make_pair(std::move(retptr), numObservations);
+}

引数追加したgetImageTargetResult()に引数にセットする処理を追加。
あとは処理を簡潔にした。

AppController.cpp(384-402)
bool
-AppController::getImageTargetResult(VuMatrix44F& projectionMatrix, VuMatrix44F& modelViewMatrix, VuMatrix44F& scaledModelViewMatrix, VuVector2F& markerSize)
+AppController::getImageTargetResult(const VuObservation* observation, VuMatrix44F& projectionMatrix, VuMatrix44F& modelViewMatrix, VuMatrix44F& scaledModelViewMatrix, VuVector2F& markerSize, std::string& targetName)

+   targetName = imageTargetInfo.name;

それら関数の呼び元を修正。
認識マーカ数だけloopする様に実装。だけど認識数は1つだけみたいだ。

VuforiaWrapper.cpp(311-336)
+       auto [imageTargetList, CNT] = controller.createImageTargetList();
+       for (int idx = 0; idx < CNT; idx++) {
+           VuObservation* observation = nullptr;
+           if (vuObservationListGetElement(imageTargetList.get(), idx, &observation) != VU_SUCCESS)
+               continue;
+
+           assert(observation);
+           assert(vuObservationIsType(observation, VU_OBSERVATION_IMAGE_TARGET_TYPE) == VU_TRUE);
+           assert(vuObservationHasPoseInfo(observation) == VU_TRUE);
+
            VuMatrix44F trackableProjection;
            VuMatrix44F trackableModelView;
            VuMatrix44F trackableModelViewScaled;
            VuImageInfo modelTargetGuideViewImage;
            VuBool guideViewImageHasChanged;
            VuVector2F markerSize;
+           std::string tergetName;
-           if (controller.getImageTargetResult(trackableProjection, trackableModelView, trackableModelViewScaled, markerSize))
+           if (controller.getImageTargetResult(observation, trackableProjection, trackableModelView, trackableModelViewScaled, markerSize, tergetName))
            {
+               if(tergetName == "001_stones_jpg")
                    gWrapperData.renderer.renderVideoPlayback(trackableProjection, trackableModelView, trackableModelViewScaled, markerSize);
+               else if(tergetName == "002_cleyon")
                    gWrapperData.renderer.renderImageTarget(trackableProjection, trackableModelView, trackableModelViewScaled);
            }
        }
+       imageTargetList.reset();

で、実行。

出来た!!

25.09.24 更新 同時検出、出来た!!

マーカーの同時検出、できないと思ってたら出来た!!
設定関数があってそれを呼出す必要があった。実行関数は下記。

AppController.cpp(730-755)
        for(int lpct = 0; lpct < 2; lpct++) {
            auto imageTargetConfig = vuImageTargetConfigDefault();
            imageTargetConfig.databasePath = "orignal/image.xml";
            if(lpct == 0)
                imageTargetConfig.targetName = "001_stones_jpg";
            else
                imageTargetConfig.targetName = "002_cleyon";
-           imageTargetConfig.activate = VU_TRUE;
+           imageTargetConfig.activate = VU_FALSE;

            VuObserver* observer = nullptr;
            VuImageTargetCreationError imageTargetCreationError;
            if (vuEngineCreateImageTargetObserver(mEngine, &observer, &imageTargetConfig, &imageTargetCreationError) != VU_SUCCESS)
            {
                LOG("Error creating image target observer: 0x%02x", imageTargetCreationError);
                mErrorMessageCallback("Error creating image target observer");
                return false;
            }

+           /* 同時認識数の設定*/
+           REQUIRE_SUCCESS(vuEngineSetMaximumSimultaneousTrackedImages(mEngine, 5));
+
+           /* Observerをアクティベート */
+           vuObserverActivate(observer);
+
            mObjectObservers.push_back(observer);
        }


画像の同時検出もできている。
無事同時検出も出来た!!

Discussion