2021年10月22日
【ARFoundation】撮影した写真をそのままARマーカーに設定する
はじめに
この記事では、Unityで使うことのできるフレームワーク、ARFoundationを使って撮影した画像をマーカーにする方法を書いていきます!
ARFoundationとは?
unityで提供されているフレームワークの一つで、IOSとAndroidの区別をあまり意識することなく、簡単にAR体験をすることのできるものです。このフレームワーク一つで画像(マーカー)の認識、顔認識、平面認識などさまざまなARプロジェクトを構築することができます。
プロジェクトの準備
ProjectにARFoundationを入れる
環境
- Unity 2020.3.11f
- ARFoundation 4.1.7
- Google Pixel 3a XL(Androidバージョン 11)
まずはUnityの3Dプロジェクトを立ち上げ、Window> PackageManagerから、ARFoundationと(今回使用するのはAndroid端末なので)ARCoreXR PluginをInstallしましょう。
ビルド設定
次に、FIle>BuildSettingsより、PlatformをAndroidにします。プラットフォームの切り替えが終わったらPlayerSettings>Playerに移動し、Androidの設定項目を下記のように変更します。
– RenderlingのColorSpaceをGammaに変更
- IdentifivationのMinimum APILevelをAndroid7.0以上に変更
- ConfigrationのScripting BackendをIL2CPPに変更
- ConfigrationのTarget ArchitecturesのARM64にチェック
最後に、PlayerSettings>XR Plug-in Managementに移動し、ARCoreにチェックを入れます。
これで基本的なプロジェクト設定は完了です。
コンポーネントを追加する
AR表示のために必要なオブジェクトを配置
Unity内のヒエラルキー内で右クリック>XRより、AR Session OriginとAR Sessionを追加します。
追加したAR Session Originを選択し、Add ComprnentからAR Tracked Image Managerを追加します。
また、Main Cameraは削除しましょう。
ここまででARを表示するためのオブジェクトは配置できました。
ARで表示するオブジェクトの設定
ARでマーカーを読み込んだ際に表示するオブジェクトは、先ほど追加したAR Tracked Image Managerに設定します。
AR Tracked Image Managerには3つの設定箇所があります。
Serialized Libralyは通常であれば参照するマーカーの設定をする「ReferenceImageLibrary」を設定しますが、今回は空欄のままで構いません。
Max Number Of Moving Imagesはトラッキングする画像の数を設定しますが、今回は1にします。
最後にTracked Image Prefabには実際に表示するプレハブを設定します。今回は3D Object内に用意されているCubeをプレハブ化し設定しました。
ただし、そのままでは大きすぎるのでScaleは(0.1, 0.1, 0.1)にしています。
UIの配置
写真を撮影するためのボタンと、撮影した写真を確認するビューを配置します。
ヒエラルキービューで右クリック>UIより、Buttonと、RawImageを配置します。
ボタンの大きさや配置はお好みですが、今回は下記のように設定しています。
RawImageも同様ですが、撮影する画像の比率と合わせた方が、画像の確認がしやすいです。
今回は撮影を800*800の大きさで行うことにしましたので設定は下記のようにしました。
配置の確認
これでオブジェクトの設定は概ね完了です。最終的な配置は下記のようになります。
コードを書く(撮影部分)
それではいよいよコーディングをしていきましょう!!
プロジェクトビューで右クリック>Create>C# Scriptからスクリプトを作成します。名前は任意ですが、この例では「TakePhoto」にします。
作成したスクリプトをAR Session Originに設定します。
今回、撮影の流れは下記のようになります。
1. ボタンなど、UIの非表示
2. 撮影
3. UIの再表示
4. 撮影した画像をRawImageとマーカーに設定
UIの非表示
今回UIとして配置しているのはButtonとRawImageの2つです。
あらかじめ参照させておき、ボタンを押した時にSetActiveをfalseにすることで非表示にします。
publicまたは[SerializeField] private で宣言することで、unity上で設定することができます。
また、ここで定義する InActiveateUI()はボタンから呼び出すものになるため、publicで定義します。
public class TakePhoto : MonoBehaviour
{
[SerializeField] private GameObject button;
[SerializeField] private GameObject rawImage;
public void InActiveateUI()
{
button.SetActive(false);
rawImage.SetActive(false);
}
}
ButtonとRawImageそれぞれをunity上で設定します。
撮影
次に撮影部分を実装します。
先ほどUIを非表示にしましたが、そのまま撮影に入ると、非表示になりきれずに撮影される場合があります。
そのため、コルーチンのWaitForEndOfFrame()を使用して1フレーム分待機することで非表示になるのを待ちます。
POINT!!
撮影はUIが非表示になるのを待ってから
その後スクリーンショットを撮影します。
unityにはCaptureScreenshotというスクリーンショットのためのメソッドが用意されているのですが、今回は解像度を細かく設定したいのと、撮影した画像を保存するわけではないため別の方法で撮影しています。
撮影する画像は画面全体ではなく、800*800の大きさにしました。画面全体だとマーカーとしての判定がシビアになってしまい、スムーズな判定ができなくなってしまったためです。画面に表示されているものをTexture2Dに変換する形にしました。
ここまでの記述は下記のようになります。
private Texture2D screenShot;
public class TakePhoto : MonoBehaviour
{
public void InActiveateUI()
{
~~中略~~
StartCoroutine(ScreenShot());
}
private IEnumerator ScreenShot()
{
//UIが消えるまで待つ
yield return new WaitForEndOfFrame();
//スクリーンショット撮影
int width = 800;
int height = 800;
screenShot = new Texture2D(width, height, TextureFormat.RGB24, false);
screenShot.ReadPixels(new Rect(0, 0, width, height), 0, 0);
screenShot.Apply();
}
}
UIの再表示
再表示の際はフレームを待つ必要はなく、単純にSetActiveをtrueにすれば良いです。
private IEnumerator ScreenShot()
{
~~中略~~
button.SetActive(false);
rawImage.SetActive(false);
}
撮影した画像をRawImageとマーカーに設定
撮影した画像をRawImageに追加するのは簡単で、RawImageを取得し、その中のテクスチャを置き換えれば良いだけです。
この記述はScreenShot()の末尾に追加しておきましょう。
private IEnumerator ScreenShot()
{
~~中略~~
//画像をRawImageに設定
RawImage imageTarget = rawImage.GetComponent<Rawimage>();
imageTarget.texture = screenShot;
}
さて、いよいよマーカーに設定してみましょう!
今回はプロジェクト内でマーカーを登録するための「ReferenceImageLibrary」を作成していないため、ここで作成していく必要があります。CreateRuntimeLibrary()というメソッドが用意されていますので、こちらを使います。
作成したライブラリーにスクリーンショットを登録し、トラッキングを開始する記述を書けばスクリプトは完成です!
ここで使用するScheduleAddImageWithValidationJobメソッドの引数は(登録するマーカー, 登録するマーカーの名前, マーカーとしての大きさ)になります。
private IEnumerator ScreenShot()
{
~~中略~~
SetTrakedImage();
}
private void SetTrakedImage()
{
//画像を登録するためのライブラリーを作成する
aRTrackedImageManager.referenceLibrary = aRTrackedImageManager.CreateRuntimeLibrary();
//トラッキングする画像として撮影したスクリーンショットを追加する
if (aRTrackedImageManager.referenceLibrary is MutableRuntimeReferenceImageLibrary mutableLibrary)
{
mutableLibrary.ScheduleAddImageWithValidationJob(screenShot, "my new image", 0.5f); // 0.5f = 50cm
}
//トラッキングをオンにする
aRTrackedImageManager.enabled = true;
}
お疲れさまでした!と言いたいところですが、最後に一つ工程が残っています。
ボタンを押した際に呼び出すメソッドを設定します!unityに戻り、ButtonのOn Clickで+ボタンを押しInActiveateUI()を選択します。
これで実装はおしまいです!
POINT!!
Buttonの設定を忘れずに!
最後にスクリプトの全体を載せておきます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
public class TakePhoto : MonoBehaviour
{
[SerializeField] private GameObject button;
[SerializeField] private GameObject rawImage;
[SerializeField] private ARTrackedImageManager aRTrackedImageManager;
private Texture2D screenShot;
public void InActiveateUI()
{
button.SetActive(false);
rawImage.SetActive(false);
StartCoroutine(ScreenShot());
}
private IEnumerator ScreenShot()
{
//UIが消えるまで待つ
yield return new WaitForEndOfFrame();
//スクリーンショット撮影
int width = 800;
int height = 800;
screenShot = new Texture2D(width, height, TextureFormat.RGB24, false);
screenShot.ReadPixels(new Rect(0, 0, width, height), 0, 0);
screenShot.Apply();
//UIを元に戻す
button.SetActive(true);
rawImage.SetActive(true);
SetTrakedImage();
}
private void SetTrakedImage()
{
//画像をRawImageに設定
RawImage imageTarget = rawImage.GetComponent<Rawimage>();
imageTarget.texture = screenShot;
//画像を登録するためのライブラリーを作成する
aRTrackedImageManager.referenceLibrary = aRTrackedImageManager.CreateRuntimeLibrary();
//トラッキングする画像として撮影したスクリーンショットを追加する
if (aRTrackedImageManager.referenceLibrary is MutableRuntimeReferenceImageLibrary mutableLibrary)
{
mutableLibrary.ScheduleAddImageWithValidationJob(
screenShot,
"my new image",
0.5f); /* 50cm */
}
//トラッキングをオンにする
aRTrackedImageManager.enabled = true;
}
}
こちらをビルドして実行するとこんな感じになります!
撮影した直後に、風景がマーカーとして登録され、cubeが登場するのがみれると思います。
背景が均一であれば、色々なものに追従させることもできそうです!
さいごに
今回はARFoundationを使って、撮影した写真をマーカーに設定する方法をご紹介しました!
少しでもARって面白い、やってみたい!と感じていたければ幸いです。
最後までご覧いただき、ありがとうございました!
NativeAR/VRのお仕事に関するご相談
Bageleeの運営会社、palanではNativeAR/VRに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。
この記事は
参考になりましたか?
0
0
関連記事
簡単に自分で作れるWebAR
「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。
palanARへpalanでは一緒に働く仲間を募集しています
正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。
運営メンバー
Eishi Saito 総務
SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。
sasakki デザイナー
アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。
やまかわたかし デザイナー
フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。
Sayaka Osanai デザイナー
Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。
はらた エンジニア
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
こぼり ともろう エンジニア
サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。
ささい エンジニア
フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。
Damien
WebAR/VRの企画・開発をやっています。森に住んでいます。
ゲスト bagelee
かっきー
まりな
suzuki
miyagi
ogawa
雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。
いわもと
デザイナーをしています。 好きな食べ物はラーメンです。
taishi kobari
フロントエンドの開発を主に担当してます。Blitz.js好きです。
kubota shogo
サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!
nishi tomoya
aihara
グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。
nagao
SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。
Kainuma
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
sugimoto
asama
ando
iwasawa ayane
yoko oshimo
異業界からやってきたデザイナー。palanARのUIをメインに担当してます。これからたくさん吸収していきます!