SlideShare a Scribd company logo
OpenCVとARCoreで作るスタンプAR
ARコンテンツ作成勉強会 in 熊本
自己紹介
氏名:吉永崇(Takashi Yoshinaga)
所属:九州先端科学技術研究所(ISIT)
専門:ARを用いた医療支援や運動計測
コミュニティ:ARコンテンツ作成勉強会 主催
ARコンテンツ作成勉強会の紹介
 2013年5月に勉強会をスタート
 ARコンテンツの作り方をハンズオン形式で学ぶ
 人数は5~10名程度の少人数で実施
 参加条件はAR/VRに興味がある人(知識不要)
 各地で開催 (福岡、熊本、宮崎、長崎、大分、 鹿児島、山口、広島、関東、北海道)
Twitterと勉強会ページで情報を発信しています
#AR_Fukuoka Googleで「AR勉強会」で検索
#AR_Kumamoto
今日のハッシュタグ
Special Thanks
Shinji Hayai
@_shinjism
事前準備
① 演習用データ
http://arfukuoka.lolipop.jp/stampar/Sample.zip
② ARCoreSDK(v1.14.0)
https://github.com/google-ar/arcore-unity-sdk/releases/tag/v1.14.0
③ Unity2017.4.34f1 or later
https://unity3d.com/jp/unity/qa/lts-releases?version=2017.4
④ Android SDK
https://developer.android.com/studio
今日のゴール
https://youtu.be/a8o1ieL01_w
ARCore (GooglePlay開発者サービス(AR))
Googleが提供する次世代ARプラットフォーム。普通のスマホでマーカーレスARを実現。
【主要機能】
(1) 自己位置推定 (Motion Tracking)
(2) 平面認識 (Environmental Understanding)
(3) 明るさ推定 (Light Estimation)
(4) マーカー認識 (Augmented Image)
(5) 空間共有 (Cloud Anchor)
(6) 顔認識 (Augmented Faces)
(1) 自己位置推定 (Motion Tracking)
OpenCV Plus Unity
 画像処理ライブラリの定番としてお馴染みのOpenCVのUnity版
 C#版のOpenCVSharpをベースにUnityに対応させたアセット
 Windows/Mac/Android/iOSに対応。しかも無料!
処理手順
二値化
capture
色の変更
アルファ値
の追加
2D→3DGOAL!
まずはUnityの操作の基本
プロジェクトを作成
New
プロジェクトを作成
最後にCreate Project
プロジェクト名
保存場所
Unityの操作画面(概要)
ゲーム空間の設計画面
ゲーム空間にCGを追加しよう
①右クリック
②3D Object
③Quad
実行してみよう
クリックして実行
クリックして終了
カメラから見た空間
Scene(設計画面)の視点を変えよう
[←] [→]で左右移動
[↑][↓]でズームイン/アウト
[Alt]+ドラッグで回転
+ドラッグで上下左右
オブジェクトの位置・向き・サイズを調整
クリックして選択
移動 回転 拡大・縮小
数値を用いた位置・姿勢・サイズの指定
 オブジェクトの詳細の確認・追加・変更はInspectorで行う
 例えば、TransformのPositionを変更すると位置が変わる
②Inspector
① Quad
数値を用いた位置・姿勢・サイズの指定
各値を初期状態に戻す
Position 0 0 0
Rotation 0 0 0
Scale 1 1 1
座標系
Y
ZX
Unityでは横はX、奥行方向がZ、そして地面に対して垂直がY
色情報の設定:テクスチャを指定
既存の3Dモデルにテクスチャ画像を貼り付けて見た目を変更
色情報の設定:マテリアルの作成
①Assets
②空白を右クリック
色情報の設定:マテリアルの作成
①Create
②Material
色情報の設定:マテリアルの適用
①Quadをクリック
②Materialsを開く
※▼をクリック
色情報の設定:マテリアルの適用
①NewMaterialに注目
②MaterialsのElement0
にドラッグ&ドロップ
色情報の設定:マテリアルの適用
①Quadをクリック
②NewMaterialを開く
※▼をクリック
色情報の設定:マテリアルの適用
ここをクリック
色情報の設定:マテリアルの適用
①Unlit
②Transparent
色情報の設定:マテリアルの適用
Quadの詳細情報として
テクスチャを登録する
色情報の設定:画像のインポート
①Assets
②ImportNewAsset...
色情報の設定:画像のインポート
①Sampleフォルダ
②logo.pngを選択
③Import
色情報の設定:テクスチャの貼り付け
①Quadをクリック
色情報の設定:テクスチャの貼り付け
①logoに注目 ②テクスチャ指定領域に
ドラッグ&ドロップ
色情報の設定:テクスチャの貼り付け
ポイント&アイディア
【ポイント】
3Dオブジェクトにテクスチャを貼るというマテリアルを一度設定。
その後は画像を関連付けるだけで見た目を変えることが可能。
【アイディア】
 カメラ画像を着色領域(黒)と透過領域(白)に分ける
 黒画素の領域をスクリプトで操作して色を変更
 画像の白画素の領域を透明にした画像を作成
 透過画像を貼り付けたQuadを空中に出現させる
一旦、現状を保存
①File
②Save Scene as...
(Unity2018はSave As)
現状を保存:Sceneの保存
①適当に名前を付ける
(例:StampAR)
②保存
以降はCtrl/Command + Sで現状を保存
ARCore SDKの導入
①Assets
②Import Package
③Custom Packageから下記を開く
arcore-unity-sdk-v1.XX.0.unitypackage
ARCore SDKの導入
Import
ARCore SDKの導入
GoogleARCoreが追加される
AR用カメラの設定
Main Cameraを削除
※右クリック→Delete
AR用カメラの設定
Assets→GoogleARCore→Prefabs
AR用カメラの設定
①ARCore Device
②Hierarchyにドラッグ&ドロップ
AR用カメラの設定
①ARCore Device
②DefaultSessionConfig
をダブルクリック
AR用カメラの設定
Camera Focus ModeをAutoに変更
オブジェクト表示位置の調整
Quadをクリック
表示オブジェクトの設定
Position: 0, 0, 0.5
Scale: 全て0.1
オブジェクト表示位置の調整
Quadをダブルクリック
保存
Ctrl + S
または
Command + S
ビルド設定
①File
②Build Settings...
ビルド設定
①Android
②Switch Platform
ビルド設定
①Internal
②Player Settings
ビルド設定
①Resolution and Presentation
②Default OrientationをPortraitに変更
ビルド設定
①PackageNameを設定
例)com.fukuoka.test
②Minimum API Level
をAndrid 7.0に変更
ARCoreの利用設定(Unity2018のみ)
Allow unsafe Codeをオン
ARCoreの利用設定
①XR Settings
②ARCore Supportedをオン
Ctrl/Command+Sで現状を保存
実機インストール
①File
②Build & Run
実機インストール
①インストーラ(.apk)の名前を付ける
②保存
動作確認
画像処理を始める準備
OpenCV Plus Unityの導入
①Window
②Asset Store
OpenCV Plus Unityの導入
OpenCV Plusで検索
OpenCV Plus Unityの導入
OpenCV Plus Unityをクリック
OpenCV Plus Unityの導入
ダウンロード
OpenCV Plus Unityの導入
インポート
OpenCV Plus Unityの導入
Import
OpenCV Plus Unityの導入
OpenCV + Unity
が追加されていればOK
UnityEditorの画面設定
Game
UnityEditorの画面設定
①Free Aspectをクリック
②+をクリック
UnityEditorの画面設定
①名前を付ける
②800 × 1280
UIのインポート
②Import Package
①Assets
③Custom Package...
UIのインポート
②開く
①StampUI.unitypackage
UIのインポート
Import
UIのインポート
Scene
UIのインポート
①Assets
②Canvasが追加
されていることを確認
UIのインポート
①Canvas
②Hierarchyにドラッグ&ドロップ
UIのインポート
UIが追加されているはず
UIのインポート
①Canvasをダブルクリック
②UIの全体が見える
UIのインポート
①xやzをクリック
②UIを正面に向ける
UIの役割
キャプチャ開始
色変更
空間に貼り付け
キャプチャや画像処理
結果の可視化
画像表示部分の設定
①Canvasを開く
②Assetsを開く
画像表示部分の設定
①RawImage
②Materialに注目
画像表示部分の設定
①NewMaterialに注目
②Materialに
ドラッグ&ドロップ
画像表示部分の設定
確認用の領域に透過画像を
表示できるようになった
画像処理スクリプト記述の準備
空白を右クリック
画像処理スクリプト記述の準備
Create Empty
画像処理スクリプト記述の準備
①Game Object
②Add Component
画像処理スクリプト記述の準備
①New Script
②スクリプト名を決める
(例:StampScript)
③Create and Add
画像処理スクリプト記述の準備
①Game Object
②StampScript
が追加されていればOK
画像処理スクリプト記述の準備
ダブルクリック
OpenCV等のインポート
using UnityEngine;
using UnityEngine.UI;
using OpenCvSharp;
using OpenCvSharp.Demo;
public class StampScript : MonoBehaviour {
// Start関数は初期化のために一度だけ実行される
void Start () {
cg = GameObject.Find ("Robot Kyle");
}
// Update関数は毎フレーム実行される
void Update () {
}
}
canvas
変数の用意
//UIが張り付けられたCanvas
public GameObject canvas;
//プレビュー領域
public RawImage preview;
//キャプチャ領域を保持
UnityEngine.Rect capRect;
//キャプチャ画像を保持
Texture2D capTexture;
void Start () {
}
void Update () {
}
preview
UIと変数の関連付け
①GameObjectをクリック
②CanvasとPreview
が追加されていればOK
UIと変数の関連付け
Canvasに注目
StampScriptの
Canvasにドラッグ&ドロップ
UIと変数の関連付け
RawImageに注目
StampScriptの
Previewにドラッグ&ドロップ
処理手順
二値化
capture
色の変更
アルファ値
の追加
2D→3DGOAL!
処理手順
二値化 色の変更
アルファ値
の追加
2D→3DGOAL!
capture
準備:まずは画面全体をキャプチャしてみる
//UIが張り付けられたCanvas
public GameObject canvas;
//プレビュー領域
public RawImage preview;
//キャプチャ領域を保持
UnityEngine.Rect capRect;
//キャプチャ画像を保持
Texture2D capTexture;
void Start () {
int w = Screen.width;
int h = Screen.height;
//原点(0,0)から画面の縦横の長さまでをキャプチャ領域とする
capRect = new UnityEngine.Rect(0, 0, w, h);
//画面サイズの空画像を作成
capTexture =
new Texture2D(w, h, TextureFormat.RGBA32, false);
//capTextureをプレビュー領域に貼り付け
preview.material.mainTexture = capTexture;
}
width
height
(0,0)
画像処理用の関数
void Start () {
/*省略:前ページで記述した初期化*/
}
IEnumerator ImageProcessing()
{
canvas.SetActive(false);//Canvas上のUIを一時的に消す
yield return new WaitForEndOfFrame();//フレーム終了を待つ
capTexture.ReadPixels(capRect, 0, 0);//キャプチャ開始
capTexture.Apply();//各画素の色をテクスチャに反映
canvas.SetActive(true);//Canvas上のUIを再表示
}
public void StartCV()
{
StartCoroutine(ImageProcessing());//コルーチンの実行
}
ここに記述
StartCV()を呼び出す
①CaptureBtnをクリック
②Buttonを探す
③OnClick()の
下方にある+をクリック
StartCV()を呼び出す
GameObjectに注目
OnClick()内のNoneと
書かれた箇所にドラッグ&ドロップ
StartCV()を呼び出す
①No Functionをクリック
②StampScript
StartCV()を呼び出す
StartCV()
Build & Run!
動作確認
キャプチャ画像が表示される
Capture
コードを整理(1/2)
IEnumerator ImageProcessing()
{
canvas.SetActive(false);
yield return new WaitForEndOfFrame();
capTexture.ReadPixels(capRect, 0, 0);
capTexture.Apply();
canvas.SetActive(true);
}
void CreateImages() {
/*ここに画像生成コードを移す*/
}
画像の生成
このあと、画像生成のコードが増えるため関数にまとめて整理しておく
コードを整理(2/2)
このあと、画像生成のコードが増えるため関数にまとめて整理しておく
IEnumerator ImageProcessing()
{
canvas.SetActive(false);//Canvas上のUIを一時的に消す
yield return new WaitForEndOfFrame();
CreateImages(); //画像の生成
canvas.SetActive(true);//Canvas上のUIを再表示
}
void CreateImages()
{
capTexture.ReadPixels(capRect, 0, 0);
capTexture.Apply();
}
処理手順
二値化 色の変更
アルファ値
の追加
2D→3DGOAL!
capture
ここからOpenCV!
capture
処理手順
色の変更
アルファ値
の追加
2D→3DGOAL!
二値化
グレースケール画像の二値化
0 255
0 255
0~255の輝度値を、ある値(しきい値)以上か未満かで分離することを二値化と呼ぶ。
画像処理すべき領域か否かをはっきり分けることができるため非常に重要なテクニック。
OpenCVで画像を扱う準備
//スクショ領域を保持
UnityEngine.Rect capRect;
//スクショ画像を保持
Texture2D capTexture;
//OpenCVで扱う画像を保持
Mat bgraMat, binMat;
void Start () {
int w = Screen.width;
int h = Screen.height;
//原点(0,0)から画面の縦横の長さまでをキャプチャ領域とする
capRect = new UnityEngine.Rect(0, 0, w, h);
//画面サイズの空画像を作成
capTexture =
new Texture2D(w, h, TextureFormat.RGBA32, false);
//capTextureをプレビュー領域に貼り付け
preview.material.mainTexture = capTexture;
}
二値化
void CreateImages()
{
capTexture.ReadPixels(capRect, 0, 0);
capTexture.Apply();
//Texure2DをMatに変換
bgraMat = OpenCvSharp.Unity.TextureToMat(capTexture);
//カラー画像をグレースケール(濃淡)画像に変換
binMat = bgraMat.CvtColor(ColorConversionCodes.BGRA2GRAY);
//大津の方法で二値化。結果を白黒反転
binMat = binMat.Threshold(100, 255, ThresholdTypes.Otsu);
//あとで色を変えられるようにカラー(BGR)に変換
bgraMat = binMat.CvtColor(ColorConversionCodes.GRAY2BGRA);
}
bgraMat binMat(GrayScale) binMat (Binarized) bgraMat (B=G=R)
二値化結果の表示
IEnumerator ImageProcessing()
{
canvas.SetActive(false);
yield return new WaitForEndOfFrame();
CreateImages();//画像を生成
SetColor(capTexture);//テクスチャに色をセット
canvas.SetActive(true);
}
//bgraMatが保持する色をテクスチャにセットする
void SetColor(Texture2D texture)
{
OpenCvSharp.Unity.MatToTexture(bgraMat, texture);
}
動作確認
①Capture ②二値化結果
Matに関するメモリの開放
IEnumerator ImageProcessing()
{
canvas.SetActive(false);
//Mat用に確保したメモリを解放
if (bgraMat != null) { bgraMat.Release(); }
if (binMat != null) { binMat.Release(); }
yield return new WaitForEndOfFrame();
CreateImages();
SetColor(capTexture);
canvas.SetActive(true);
}
capture
処理手順
色の変更
アルファ値
の追加
2D→3DGOAL!
二値化
capture
処理手順
アルファ値
の追加
2D→3DGOAL!
二値化 色の変更
黒画素に色を付ける (1/2)
void SetColor(Texture2D texture)
{
//Matが初期化されていない場合は何もしない
if (bgraMat == null || binMat == null) { return; }
unsafe
{
//各Matのピクセル情報の配列(ポインタ)を取得
byte* bgraPtr = bgraMat.DataPointer;
byte* binPtr = binMat.DataPointer;
//全ピクセル数を算出
int pixelCount = binMat.Width * binMat.Height;
//各ピクセルを参照して黒画素なら色を塗る
for (int i = 0; i < pixelCount; i++)
{
}
}
OpenCvSharp.Unity.MatToTexture(bgraMat, texture);
}
後ほど処理を記述
ポインタと各ピクセルの色情報
 どちらの画像も左上から横方向スキャンし、それを全段で行った
場合の各画素の色情報を1次元配列に格納している。
 binPtr(白黒画像) :
 bgraPtr(カラー画像+アルファ):
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
・・・
・・・
binPtr bgraPtr
0th pixel 1st 2nd
全要素数 n (=width*height)
全要素数 n*4
この次の作業
void SetColor(Texture2D texture)
{
//Matが初期化されていない場合は何もしない
if (bgraMat == null || binMat == null) { return; }
unsafe
{
//各Matのピクセル情報の配列(ポインタ)を取得
byte* bgraPtr = bgraMat.DataPointer;
byte* binPtr = binMat.DataPointer;
//全ピクセル数を算出
int pixelCount = binMat.Width * binMat.Height;
//各ピクセルを参照して黒画素なら色を塗る
for (int i = 0; i < pixelCount; i++)
{
}
}
OpenCvSharp.Unity.MatToTexture(bgraMat, texture);
}
これから処理を記述
黒画素に色を付ける (2/2)
byte* bgraPtr = bgraMat.DataPointer;
byte* binPtr = binMat.DataPointer;
int pixelCount = binMat.Width * binMat.Height;
for (int i = 0; i < pixelCount; i++)
{
//白黒画像のi番目に相当するBGRAのデータの位置
int bgraPos = i * 4;
//白かったら無視(あとで透過させる)
if (binPtr[i] == 255)
{
}
//黒かったら色を塗る
else
{
bgraPtr[bgraPos] = 255; //B
bgraPtr[bgraPos+1] = 0; //G
bgraPtr[bgraPos+2] = 0; //R
}
}
動作確認
色の配列を作成
//14色の色情報
byte[,] colors = { { 255, 255, 255 },{ 18, 0, 230 },
{ 0, 152, 243 }, { 0, 241, 255 }, { 31, 195, 143 },
{ 68, 153, 0 }, { 150, 158, 0 }, { 233, 160, 0 },
{ 183, 104, 0 }, { 136, 32, 29 }, { 131, 7, 146 },
{ 127, 0, 228 }, { 79, 0, 229 }, { 0, 0, 0 } };
//何番目の色かを表す変数 (colNo=0~13)
int colorNo = 0;
void Start()
{
int w = Screen.width;
int h = Screen.height;
/*資料のスペースの都合により省略*/
}
①color.txtからコピペ
②自分で書く
黒画素の色の切り替え(1/3)
void SetColor(Texture2D texture)
{
//Matが初期化されていない場合は何もしない
if (bgraMat == null || binMat == null) { return; }
unsafe
{
//各Matのピクセル情報の配列(ポインタ)を取得
byte* bgraPtr = bgraMat.DataPointer;
byte* binPtr = binMat.DataPointer;
//全ピクセル数を算出
int pixelCount = binMat.Width * binMat.Height;
//各ピクセルをチェックして黒かったら色を付ける
for (int i = 0; i < pixelCount; i++)
{
}
}
OpenCvSharp.Unity.MatToTexture(bgraMat, texture);
}
ここで色を指定 (次のページで解説)
黒画素の色の切り替え(2/3)
for (int i = 0; i < pixelCount; i++)
{
//白黒画像のi番目に相当するBGRAのデータの位置
int bgraPos = i * 4;
//白かったら無視(あとで透過にする)
if (binPtr[i] == 255)
{
}
//黒かったら色を付ける
else
{
bgraPtr[bgraPos] = colors[colorNo, 0]; //B
bgraPtr[bgraPos + 1] = colors[colorNo, 1]; //G
bgraPtr[bgraPos + 2] = colors[colorNo, 2]; //R
}
}
黒画素の色の切り替え(3/3)
public void ChangeColor()
{
colorNo++;
colorNo %= 14; //またはcolors.Length / 3;
SetColor(capTexture);
}
//色を変更する関数
void SetColor(Texture2D texture)
{
//Matが初期化されていない場合は何もしない
if (bgraMat == null || binMat == null) { return; }
unsafe
{
//各Matのピクセル情報の配列(ポインタ)を取得
byte* bgraPtr = bgraMat.DataPointer;
byte* binPtr = binMat.DataPointer;
/*資料のスペースの都合により以下省略*/
ChangeColor()を呼び出す
①ColorBtnをクリック
②Buttonを探す
③OnClick()の
下方にある+をクリック
ChangeColor()を呼び出す
GameObjectに注目
OnClick()内のNoneと
書かれた箇所にドラッグ&ドロップ
ChangeColor()を呼び出す
①No Functionをクリック
②StampScript
ChangeColor()を呼び出す
ChangeColor()
動作確認
Capture Color Color
capture
処理手順
アルファ値
の追加
2D→3DGOAL!
二値化 色の変更
capture
処理手順
2D→3DGOAL!
二値化 色の変更
アルファ値
の追加
白画素を透過させる(1/2)
void SetColor(Texture2D texture)
{
//Matが初期化されていない場合は何もしない
if (bgraMat == null || binMat == null) { return; }
unsafe
{
//各Matのピクセル情報の配列(ポインタ)を取得
byte* bgraPtr = bgraMat.DataPointer;
byte* binPtr = binMat.DataPointer;
//全ピクセル数を算出
int pixelCount = binMat.Width * binMat.Height;
//各ピクセルに対して透過/非透過の処理を行う
for (int i = 0; i < pixelCount; i++)
{
}
}
OpenCvSharp.Unity.MatToTexture(bgraMat, texture);
}
ここで色を指定 (次のページで解説)
白画素を透過させる(2/2)
for (int i = 0; i < pixelCount; i++)
{
//白黒画像のi番目に相当するBGRAのデータの位置
int bgraPos = i * 4;
//白かったら透過
if (binPtr[i] == 255)
{
bgraPtr[bgraPos + 3] = 0;
}
//黒かったら非透過
else
{
bgraPtr[bgraPos] = colors[colorNo, 0]; //B
bgraPtr[bgraPos + 1] = colors[colorNo, 1]; //G
bgraPtr[bgraPos + 2] = colors[colorNo, 2]; //R
bgraPtr[bgraPos + 3] = 255;
}
}
動作確認
①Capture
②透過画像
プレビュー表示の最大化
①RawImage クリック
プレビュー表示の最大化
全体を選択
プレビュー表示の最大化
Left,Top,Right,Bottom
をすべて0に変更
プレビュー表示の最大化
RawImageをオフ
プレビューの表示
IEnumerator ImageProcessing()
{
canvas.SetActive(false);
//Mat用に確保したメモリを解放
if (bgraMat != null) { bgraMat.Release(); }
if (binMat != null) { binMat.Release(); }
yield return new WaitForEndOfFrame();
CreateImages();
SetColor(capTexture);
canvas.SetActive(true);
//プレビューを表示する
preview.enabled = true;
}
動作確認
Capture
capture
処理手順
2D→3DGOAL!
二値化 色の変更
アルファ値
の追加
capture
処理手順
二値化 色の変更
アルファ値
の追加
2D→3DGOAL!
テクスチャ付きのQuadをPrefab化
Quadをクリック
②QuadをAssetsに
ドラッグ&ドロップ
テクスチャ付きのQuadをPrefab化
Quadを削除
空間にスタンプを固定
//スタンプのテンプレートオブジェクト(テクスチャ付きのQuad)
public GameObject original;
void Start()
{
int w = Screen.width;
int h = Screen.height;
capRect = new UnityEngine.Rect(0, 0, w, h);
capTexture =
new Texture2D(w, h, TextureFormat.RGBA32, false);
preview.material.mainTexture = capTexture;
}
//スタンプを空間に置くための関数
public void PutObject()
{
}
次のページからコードを記載
スタンプの実サイズを計算
//カメラの情報を取得
Camera cam = Camera.main;
//画面左下のxy座標を3次元に変換(0.6m手前に置くとする)
Vector3 v1 =
cam.ViewportToWorldPoint(new Vector3(0, 0, 0.6f));
//画面右上のxy座標を3次元に変換
Vector3 v2 =
cam.ViewportToWorldPoint(new Vector3(1, 1, 0.6f));
//画面左上のxy座標を3次元に変換
Vector3 v3 =
cam.ViewportToWorldPoint(new Vector3(0, 1, 0.6f));
//キャプチャ領域の実空間でのサイズを計算
float w = Vector3.Distance(v2, v3);
float h = Vector3.Distance(v1, v3);
/*次のページに続く*/
(0,0)
(1,1)
(0,1)
v1
v2
v3
空間にスタンプを固定
/*前のページに記述したコードからの続き*/
GameObject stamp = GameObject.Instantiate(original);
//オブジェクトの生成とカメラに対する位置・向き・サイズを設定
stamp.transform.parent = cam.transform;
stamp.transform.localPosition = new Vector3(0, 0, 0.6f);
stamp.transform.localRotation = Quaternion.identity;
stamp.transform.localScale = new Vector3(w, h, 1);
//上記で作ったオブジェクトに貼るテクスチャを作成
Texture2D stampTexture =
new Texture2D(capTexture.width, capTexture.height);
//色を塗り、そのあとテクスチャとして貼り付ける
SetColor(stampTexture);
stamp.GetComponent<Renderer>().material.mainTexture
= stampTexture;
//スタンプの原点をカメラではなくワールドに変更
stamp.transform.parent = null;
preview.enabled = false;
オブジェクトと変数の関連付け
GameObject
オブジェクトと変数の関連付け
Quadに注目
オブジェクトと変数の関連付け
Originalにドラッグ&ドロップ
PutObject()を呼び出す
①StampBtnをクリック
②Buttonを探す
③OnClick()の
下方にある+をクリック
PutObject()を呼び出す
GameObjectに注目
OnClick()内のNoneと
書かれた箇所にドラッグ&ドロップ
PutObject()を呼び出す
①No Functionをクリック
②StampScript
PutObject()を呼び出す
PutObject()
動作確認
描画できるスタンプ数に制限を設ける
//スタンプのテンプレートオブジェクト(テクスチャ付きのQuad)
public GameObject original;
//生成されたスタンプを覚えておくListを作成
List<GameObject> stampList = new List<GameObject>();
void Start()
{
int w = Screen.width;
int h = Screen.height;
capRect = new UnityEngine.Rect(0, 0, w, h);
capTexture =
new Texture2D(w, h, TextureFormat.RGBA32, false);
preview.material.mainTexture = capTexture;
}
描画できるスタンプ数に制限を設ける
public void PutObject()
{
/*資料のスペースの都合により省略*/
stamp.transform.parent = null;
//以下、生成したスタンプの記録と削除
stampList.Add(stamp);
if (stampList.Count == 10)
{
DestroyImmediate(stampList[0].
GetComponent<Renderer>().material.mainTexture);
DestroyImmediate(stampList[0]);
stampList.RemoveAt(0);
}
preview.enabled = false;
}
完成!

More Related Content

PDF
はじめようARCore:自己位置推定・平面検出・FaceTracking
PDF
OpenCV/ARCore/Unityで作る塗り絵AR
PDF
Immersal を活用した AR クラウドなシステム開発とハンズオン!
PDF
第4回UE4勉強会 in 大阪 UE4でのチーム製作
PPTX
AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう
PDF
待望のUE4新機能 ナイアガラでプログラマブルVFX
PPTX
UE4の攻略方法を伝授! より効率よく楽しく学ぶ ための鉄則について
PDF
UE4のシーケンサーをもっともっと使いこなそう!最新情報・Tipsをご紹介!
はじめようARCore:自己位置推定・平面検出・FaceTracking
OpenCV/ARCore/Unityで作る塗り絵AR
Immersal を活用した AR クラウドなシステム開発とハンズオン!
第4回UE4勉強会 in 大阪 UE4でのチーム製作
AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう
待望のUE4新機能 ナイアガラでプログラマブルVFX
UE4の攻略方法を伝授! より効率よく楽しく学ぶ ための鉄則について
UE4のシーケンサーをもっともっと使いこなそう!最新情報・Tipsをご紹介!

What's hot (20)

PDF
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
PPTX
Nreal Lightハンズオン
PDF
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
PDF
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
PPTX
HoloLens2とMeta QuestではじめるWebXR
PDF
WebRTCの技術解説 公開版
PDF
UE4.14.0 Forward Shadingのエンジン改造でセルシェードやってみた
PPTX
大規模タイトルにおけるエフェクトマテリアル運用 (SQEX大阪: 林武尊様) #UE4DD
PDF
Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
PDF
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
PPTX
MRTKをNreal Lightに対応させてみた
PDF
PDF
NiagaraでサクッとMorphEffectを作ろう
PDF
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 1
PPTX
猫でも分かる3人称視点VRコンテンツ
PPTX
絵心がなくてもわかる UE4絵作りのコツ
PDF
UE4とUnrealC++について
PDF
【Unity道場 2月】シェーダを書けるプログラマになろう
PPTX
A-Frameで始めるWebXRとハンドトラッキング (HoloLens2/Oculus Quest対応)
PDF
UE4を使った映像制作 (UE4 Character Art Dive Online)
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
Nreal Lightハンズオン
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
HoloLens2とMeta QuestではじめるWebXR
WebRTCの技術解説 公開版
UE4.14.0 Forward Shadingのエンジン改造でセルシェードやってみた
大規模タイトルにおけるエフェクトマテリアル運用 (SQEX大阪: 林武尊様) #UE4DD
Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
MRTKをNreal Lightに対応させてみた
NiagaraでサクッとMorphEffectを作ろう
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 1
猫でも分かる3人称視点VRコンテンツ
絵心がなくてもわかる UE4絵作りのコツ
UE4とUnrealC++について
【Unity道場 2月】シェーダを書けるプログラマになろう
A-Frameで始めるWebXRとハンドトラッキング (HoloLens2/Oculus Quest対応)
UE4を使った映像制作 (UE4 Character Art Dive Online)
Ad

Similar to OpenCVでつくろうARスタンプアプリ in 熊本 (20)

PDF
OpenCVで作るスタンプAR
PDF
OpenCVとARCoreで作るスタンプAR in 宮崎
PDF
ARコンテンツ作成勉強会 in 宮崎: はじめようARCore
PPTX
AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう
PDF
はじめようARCore in 札幌
PDF
UnityとVuforiaで始めるAR開発
PDF
KinectでAR空間に入り込もう
PDF
オープンソースで始めるAR/VR開発
PDF
ノンプログラミングで始める AR 開発入門
PPTX
エンジニアカフェ1周年イベント:WebAR/VR開発入門
PPTX
Unityのポストエフェクトで遊ぶ!
PDF
はじめようARCore: Motion Tracking & Image Tracking編
PPTX
Unity勉強会ハンズオン
PDF
20180616 scratch
PDF
第19回SOIL水曜セミナー:RGB-DカメラでAR空間に入り込もう
PDF
HTMLを書くだけで誰でも簡単!A-FrameではじめるWeb AR/VR
PDF
A-Frameで始めるOculus Quest対応WebVR
PDF
3Dプリント羽ばたき飛行機製作ワークショップ
PPTX
0から始めようWebAR/VR入門ハンズオン
PPTX
AI x WebAR! MediaPipeの顔認識を使ってみよう!
OpenCVで作るスタンプAR
OpenCVとARCoreで作るスタンプAR in 宮崎
ARコンテンツ作成勉強会 in 宮崎: はじめようARCore
AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう
はじめようARCore in 札幌
UnityとVuforiaで始めるAR開発
KinectでAR空間に入り込もう
オープンソースで始めるAR/VR開発
ノンプログラミングで始める AR 開発入門
エンジニアカフェ1周年イベント:WebAR/VR開発入門
Unityのポストエフェクトで遊ぶ!
はじめようARCore: Motion Tracking & Image Tracking編
Unity勉強会ハンズオン
20180616 scratch
第19回SOIL水曜セミナー:RGB-DカメラでAR空間に入り込もう
HTMLを書くだけで誰でも簡単!A-FrameではじめるWeb AR/VR
A-Frameで始めるOculus Quest対応WebVR
3Dプリント羽ばたき飛行機製作ワークショップ
0から始めようWebAR/VR入門ハンズオン
AI x WebAR! MediaPipeの顔認識を使ってみよう!
Ad

More from Takashi Yoshinaga (20)

PPTX
【準備編】OculusQuest/HoloLens2対応WebXR開発
PPTX
ARコンテンツ作成勉強会( #AR_Fukuoka )紹介
PPTX
iPad LiDARで エンジニアカフェを3Dスキャン
PPTX
Web技術ではじめようAR/VRアプリ開発
PPTX
【準備編!】HoloLens 2/Oculus Quest対応WebXRハンズオン
PPTX
Holo-SDKハンズオン:はじめようヘッドトラッキングを用いた3D表現
PPTX
FUKUOKA Engineers Day 2021 発表資料:AR Fukuoka & HoloBox紹介
PPTX
Voxon Photonics VX1 で遊んでみた
PPTX
AR-Frame x AR.js入門
PPTX
AI x WebXR: フェイストラッキングを用いた擬似3D表現を解説!
PPTX
コロナ禍中のコミュニティ活動
PPTX
Project HoloBox
PPTX
AR Fukuoka紹介2020
PPTX
iPad LiDARで作ってみた in AR Fukuoka 忘年会2020
PPTX
MRTKで始めるAR開発 (HoloLens 1 and 2, ARCore, ARkit)
PPTX
OSC2020 Fukuoka: インストールいらず、WebAR入門
PPTX
Oculus Quest 1&2 開発のはじめの一歩 with A-Frame WebVR
PPTX
AI x WebAR MediaPipeの顔認識を使ってみよう! in 織りなすラボ
PPTX
Spatial Copy & Paste @HoloLensゆるっとLT会
PPTX
ノンプログラミングで始めるAR (HoloLens 2 / ARCore / ARKit) 開発 with MRTK
【準備編】OculusQuest/HoloLens2対応WebXR開発
ARコンテンツ作成勉強会( #AR_Fukuoka )紹介
iPad LiDARで エンジニアカフェを3Dスキャン
Web技術ではじめようAR/VRアプリ開発
【準備編!】HoloLens 2/Oculus Quest対応WebXRハンズオン
Holo-SDKハンズオン:はじめようヘッドトラッキングを用いた3D表現
FUKUOKA Engineers Day 2021 発表資料:AR Fukuoka & HoloBox紹介
Voxon Photonics VX1 で遊んでみた
AR-Frame x AR.js入門
AI x WebXR: フェイストラッキングを用いた擬似3D表現を解説!
コロナ禍中のコミュニティ活動
Project HoloBox
AR Fukuoka紹介2020
iPad LiDARで作ってみた in AR Fukuoka 忘年会2020
MRTKで始めるAR開発 (HoloLens 1 and 2, ARCore, ARkit)
OSC2020 Fukuoka: インストールいらず、WebAR入門
Oculus Quest 1&2 開発のはじめの一歩 with A-Frame WebVR
AI x WebAR MediaPipeの顔認識を使ってみよう! in 織りなすラボ
Spatial Copy & Paste @HoloLensゆるっとLT会
ノンプログラミングで始めるAR (HoloLens 2 / ARCore / ARKit) 開発 with MRTK

OpenCVでつくろうARスタンプアプリ in 熊本