Tech

はじめてのVケット

VR

VRChatで開催されているバーチャル世界の祭典、Vケット4に行ってきた。

出展ブースだけでなく、マップそのものが凝ってて楽しい。VRすごい!

続きを読む

[OpenCV + Visual Studio 2019]Haar Cascadesでトラッキング

Tech ,

OpenCVに標準で用意されているHaar CascadeClassFilterを用いてWebカメラの映像から顔のトラッキングを試してみた。

環境

OS: Windows 10
Webカメラ: Logicool HD Webcam C525
開発環境: Visual Studio 2019(ver 16.2.3)
ライブラリ: OpenCV(4.1.1)
言語: C++

OpenCVをVisual Stdio 2019で使う準備

VS2019上でOpenCVを使うための事前準備。
導入済みの方は飛ばしてください。

まずは環境変数に以下のディレクトリをPathに追加する(OpenCVをCドライブ直下に展開した場合。以下、OpenCVのパスは各自環境に合わせてください)。
「C:\opencv\build\bin」

Visual Studio 2019を起動し、空のプロジェクトを作る。
メニューより「プロジェクト(P) > プロパティ」から、プロパティページを開く。
次の項目を変更する。

「構成プロパティ > VC++ディレクトリ > インクルードディレクトリ」に以下を追加
C:\opencv\build\include

「構成プロパティ > VC++ディレクトリ > ライブラリディレクトリ」に以下を追加
C:\opencv\build\x64\vc15\lib

「構成プロパティ > リンカー > 入力 > 追加の依存ファイル」に以下を追加
opencv_world411d.lib

環境構築は以上。


参考:
OpenCV(4.1.0) + Visual Studio 2019の設定忘備録 – Qiita @kenjiSpecial@github

OpenCV 4.1.1をVisual Studio 2019から使用する時の手順 – Qiita @h-adachi

カスケードフィルタ実装

OpenCVが提供している顔認識用のカスケードフィルタを使用して、リアルタイムのフェイストラッキングを実装する。

カスケードファイルの場所は以下の通り。
C:\opencv\sources\data\haarcascades\haarcascade_frontalface_alt.xml

Windowsのパスは記述が面倒なので、使用するカスケードファイルをプロジェクトファイルのあるディレクトリにコピーする。
今回はfilterというフォルダを作り、その中にカスケードファイルを配置した。

顔検出のソースコードは以下の通り。
(参考: OpenCV: Cascade Classifier

#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include <iostream>

using namespace std;
using namespace cv;


int main()
{
	CascadeClassifier face_cascade;

	// カスケードフィルタの場所を指定
	if(!face_cascade.load("./filter/haarcascade_frontalface_alt.xml"))
    {
        cout << "--(!)Error loading face cascade\n";
        return -1;
    };

	vector<Rect> faces;

	// ビデオデバイスを選択
	VideoCapture capture(0);
	if (!capture.isOpened())
	{
		cout << "--(!)Error opening video capture\n";
		return -1;
	}

	Mat frame;
	while (capture.read(frame))
	{
		capture >> frame;
		face_cascade.detectMultiScale(frame, faces, 1.1, 3, 0, Size(20, 20));

		// 検知対象を矩形表示
		for (int i = 0; i < faces.size(); i++)
		{
			rectangle(frame, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 0, 255), 3, 16);
		}

		imshow("Capture - Face detection", frame);
		
		// escape押下でループ終了
		if (waitKey(10) == 27)
		{
			break;
		}
	}
	destroyAllWindows();
	return 0;
}


Github – suminoame/opencv_haar_tutorial

そこそこ良い精度で追従するが、顔が少しでも傾くと検知しなくなる(正面の顔を検出するフィルタであるため)。
今回使用したフィルタ以外にも、様々なカスケードファイルが公開されているので色々試してみよう。
(参考:「顔以外」のものを画像認識する on iOS ‐ Qiita@shu223


深層学習を用いたトラッキングも試したい。

【Unity + Oculus Rift S】OVRGrabberとOVRPlayerController併用時の設定

Tech, Unity, VR , ,

Oculus Utilities のGrabberサンプル「LocalAvatarWithGrab」にOVR Player Controllerスクリプトを張り付けたところ妙な挙動を見せたのでメモ。


OVRGrabberで物を持ちながら移動したいと思い、OVR Player Controllerを使えば簡単にできそうじゃん!と試したところ、つまずく点が多々あったのでその記録です。

1. 移動時のアバターの視点位置が変わる

コントローラでアバターを動かした瞬間、OVR Player Controllerスクリプトを貼ったアバターの視点が上向きにずれてしまう問題が発生しました。
Inspectorを見ると、CameraRigのY座標に妙な値が入っていました。

OVRPlayerController.csの中身を調べると、CameraRig.transform.localPositionの値に固定のオフセットが掛かっている箇所がありました(UpdateController()の処理)。
useProfileData がtrueのときに、Controllerの座標に合わせてCameraRigのY座標にオフセットをかける処理のようです。
useProfileDataをfalseにすることでこの処理を無効にできます。
OVR Player ControllerのInspectorから、Use Profile Dataチェックボックスを外すことで、アバターの視点位置のズレは解消しました。

2. 視点が上空に飛ばされる

Use Profile Data を無効にしたところ、今度は視点がアバターの上空に飛ばされてしまいました。
LocalAvatarWithGrab 本体のTransformのPositionを見ると、本来アバターが存在するはずの座標からY軸方向とZ軸方向に定数値のオフセットが掛かっていることが分かりました。
このPositionのずれた座標の値をメモして、Character ControllerのCenterの座標に入れてあげることで視点の位置を調整することができました。

なぜそうなったのか原因はわかりませんでしたが、 時間のある時に Character Controllerの仕様を調べてみようと思います 。


3. GrabberのColliderがズレる

カメラは正常に設定できましたが、次はLocalAvatarWithGrabの子オブジェクトであるAvatarGrabberLeft(Right)のColliderがずれてしまいました。
どうやらカメラの向く方向に追従して子オブジェクトが動いてしまうようで、 OVRPlayerController.cs を確認したところUpdateTransform()の処理(HmdRotatesYがtrueの時に実行される個所)が原因であることが分かりました。

HmdRotatesY は OVR Player Controller のInspectorからHmd Rotates Yのチェックボックスを外すことで無効化できます。

Hmd Rotates Y を無効にするとGrabberのColliderの位置がしっかり手の動きに追従するようになりました。


備考
AvatarGrabberの子であるGrabVolumeが把持範囲のColliderを持っているんですね。Transformの値を変えることでColliderの位置や角度を自由に決めることができました。

【Unity】Oculus Rift SでVRアプリ開発 #2 ― キャラクターを動かす

Unity, VR ,

投稿日:2019/07/20
最終更新:2019/07/20

・今回の内容

3Dモデルキャラクター(ユニティちゃん)を表示する
ユニティちゃんを動かす
Oculus Rift Sのtouchコントローラーで操作する

キャラクターが動くところを見てみたい、というモチベーションで、Unity公式モデルのユニティちゃんを動かします。

参考にしたサイト:【Unity】キャラクターをアニメーションさせてみよう | 株式会社イーディーエー


こちらのサイトを参考にしてユニティちゃんモデルのアニメーションを試してみます。

Unityちゃん公式ページの右上にあるDATA DOWNLOADから、Unityちゃんの3Dモデルデータをダウンロードします。

ダウンロードしたモデルファイル(2019年7月現在では UnityChan_1_2_1.unitypackage)をUnityのProjectビュー内にあるAssetにドラッグアンドドロップしてインポートします。

インポートが完了したら、Projectビューより、UnityChan/PrefabsにあるunitychanのprefabをHierarchyビューにドラッグアンドドロップします。

これでSceneにUnityちゃんが出現します。

このままでは静止するUnityちゃんを眺めることになるので、アニメーションを追加します。
Projectビューより、右クリックで「Animator Controller」を作成し、適当な名前を付けてからダブルクリックで「Animator」画面を開きます。

・Stateの定義
方眼状のAnimatorビューが現れるので、Base Layerの画面を右クリックしてCreate StateからEmptyを選びます。
するとBase Layerに新たなボックス「New State」が追加されます。名称はInspectorビューより変更可能です。
このボックスひとつひとつがモデルのState になり、状態遷移の方向や遷移のトリガをプログラムできます。
シーン開始時の初期状態はEntry(緑のボックス)です。

今回は待機、走る、ジャンプの3つのモーションを使用したいので、New Stateを全部で3つ用意し、名前を「Wait」「Run」「Jump」に設定します。


・Transitionの定義
状態の遷移先を定義します。Stateを右クリックしてTransitionを選択すると、カーソルに追従して矢印が伸びるようになります。
遷移先のStateに矢印をつないでいく形で状態遷移を作っていきます。
今回は次のように遷移先を定義しました。

・トリガの定義
状態遷移するトリガを設定します。
Animator画面の左側にあるParametersタブから、+ボタンを押して状態遷移のイベントを作成します。

今回はWaitを初期状態としているため、Runに遷移するためのフラグisRunと、Jumpに遷移するフラグisJumpを作成します。
isRunフラグとisJumpフラグはBool型で用意しましょう。

Base Layer画面で定義したTransition(白い矢印) をクリックして、矢印方向に状態遷移するためのイベントを設定します。
選択したTransitionのInspectorビューにConditionsリストがあります。
初期状態ではList is Emptyとなっているので、+ボタンを押してフラグを追加します。
例えばWaitからRunに遷移するTransitionでは、Conditionsを「isRun:True」と定義することで、Bool型のisRunフラグがTrueになった場合に、WaitからRunに状態を遷移させます。
ここで、Inspectorビューの項目の中に「Has Exit Time」というチェックボックスがありますが、オンにするとアニメーションの再生が完了するまで次の状態に遷移しません。
遷移フラグがTrueになった瞬間に状態を遷移させたい場合は、チェックを外しましょう。

・アニメーションの定義
StateのInspectorビューから、Motionの項目クリックします。
ここでState中に再生するアニメーションを選択します。
今回はWaitのStateに「WAIT02」、Runに「RUN00_F」、Jumpに「JUMP00」を適用します。

以上でAnimatorの設定は完了です。
ProjectビューのAnimatorファイルをHierarchyビューに設置したunitychanにドラッグアンドドロップすることで、モデルのアニメーションが適用されます。


これでキャラクターにアニメーションを追加することができました。

  • ※アニメーションを実行するスクリプトファイルでエラーが発生した場合の対処法(error CS0234)

    アニメーション用のスクリプトファイルを実行しようとしたとき、以下のエラーが発生しました。

    error CS0234: 型または名前空間の名前 ‘Policy’ が名前空間 ‘System.Security’ に存在しません (アセンブリ参照があることを確認してください)。

    これは、Unityで使用する.NETのAPIバージョンを「standard 2.0」から「4.x」に変更することで解決しました。

    ・対処方法
    メニューバーのEdit > Project SettingsからPlayerタブを開きます。
    Other Settings > Configuration > Api Compatibility Level の項目を.NET standard 2.0から.NET 4.xに変更します。


    参考にしたサイト:【Unity】Unity-Chan!(ユニティちゃん)でCS0234エラーが発生したときの調査結果と解決方法 | Qiita@riekure

    error CS0234 の対処方法は以上です。

ここからはOculus Rift SのtouchコントローラーでRunやJumpの操作をできるように改良していきます。

・Oculus Rift S 導入準備

Oculus Rift Sで自作アプリを動かすには、Oculusのソフトウェアにある「設定」、「一般」タブから「提供元不明」アプリの実行許可を与える必要があります。

「提供元不明」項目のチェックをオンにしましょう。


続いてUnityでOculus Rift Sを開発するための機能を追加します。

Asset StoreからOculus Integrationをダウンロード、インポートします。

Oculus Integration – Asset Store



「Unityで開く」をクリックするとプロジェクト上で使用できるようになります。

インポートが完了すると、「Project」画面の「Assets」に「Oculus」が追加されます。

「Project」画面のAssets/Oculus/VR/PrefabsからOVRCameraRigをドラッグして「Hieraechy」画面に追加します。

このOVRCameraRigがOculusのカメラとなります。

通常のカメラは使用しないので、「Hieraechy」にあるMainCameraは消しておきましょう。

続いてtouchコントローラーを表示するPrefabを追加します。

先ほど「Hieraechy」画面に追加したOVRCameraRigを展開して、中にあるLeftHandAnchorとRightHandAnchorの中に次のPrefabをドラッグして入れます。

Assets/Oculus/VR/Prefabs/OVRControllerPrefab

これでtouchコントローラーが画面上に表示されますが、デフォルトではすべて右手用コントローラーのグラフィックとなっています。

左手のコントローラーを正しく表示するには、「Hieraechy」画面からLeftHandAnchorのOVRControllerPrefabをクリックし、「Inspector」画面のOVR Controller Helper (Script)にあるControllerタブをL Tracked Remoteに設定しましょう。


touchコントローラーが追加されました。


それでは、touchコントローラーのAボタンとBボタンでRunとJumpを操作できるようにスクリプトを書き換えましょう。

先ほど作成したユニティちゃんを動かすスクリプトファイルを次のように変更します。
(今回スクリプトファイルの名前をSampleAnimator.csとしていますが、ファイル名に合わせてclass名を変更してください)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleAnimator : MonoBehaviour
{

    // Animator component
    private Animator animator;

    // Transition flag define
    private const string key_isRun = "isRun";
    private const string key_isJump = "isJump";

    // Start is called before the first frame update
    void Start()
    {
        this.animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {

        // Push Keyboard(DownArrow) or touch Controller(Right A)
        if (OVRInput.Get(OVRInput.RawButton.A) || Input.GetKey(KeyCode.DownArrow))
        {
            // Wait >> Run
            this.animator.SetBool(key_isRun, true);
        }
        else
        {
            this.animator.SetBool(key_isRun, false);
        }


        // Push Keyboard(Space) or touch Controller(Right B)
        if (OVRInput.GetDown(OVRInput.RawButton.B) || Input.GetKey(KeyCode.Space))
        {
            // Wait or Run >> Jump
            this.animator.SetBool(key_isJump, true);
        }
        else
        {
            this.animator.SetBool(key_isJump, false);
        }
    }
}

touchコントローラーのボタン割り当てはOVRのリファレンスに記載されています。

https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovrinput/


実際に動かすとこんな感じ。

https://twitter.com/sumi_ame/status/1152571542858977280

楽しい!

次は物を掴みたいですね。

【Unity】Oculus Rift SでVRアプリ開発 #1 ― 何から手を付けよう編

Unity, VR ,

投稿日:2019/07/20
最終更新:2019/07/20

・今回の内容

Unityインストール
はじめてのプロジェクト作成

 

Oculus Rift Sを購入しました!


香港からわずか3日のスピード配達でした。

 

はじめてUnityを使った3Dゲーム開発環境を整えるにあたり、辿ってきた手順を記します。

触ってみたいけど何から始めればいいか分からない、といった方の道標になると幸いです。

 

・Unityインストール

公式サイトからUnity Hubをダウンロードします。

Download – Unity

 

参考にしたサイト:Unity Hub を利用してUnity 2018 をインストールする (Unityプログラミング) | iPentec

 

Unity Hubより最新バージョン(2019/07現在:2019.1.11f)をインストールしました。

「学習」タブにある「はじめに」のコンテンツは、Unityの操作画面でどのようなことをするのかを短時間で学習できるのでオススメです。

 

・はじめてのプロジェクト

次のサイトを参考にして、とりあえず何かプロジェクトを作ってみることにしました。

 

参考にしたサイト:Unity初期設定・チュートリアル.HMD(Oculus rift cv1)向けにビルド. | Qiita@mask0

 

真っ白な平面の上に立方体のオブジェクトを生成できました。

このフィールドをベースにして色々な機能を試していきます。


・Unityをはじめて触ってみて

予備知識が全くない状態でスタートしたこともあり、新規プロジェクトを作るだけでも四苦八苦でした。

ただ、やり方さえ掴めば充実したサポートも手伝って快適に開発できる環境が整っているという印象です。

Unity公式サイトから提供されているゲーム作成のチュートリアルも充実していて、迷ったときの参考になりました。

https://unity3d.com/jp/learn/tutorials/projects/hajiuni-jp

 

 

NEXT: キャラクターを動かす

デスクトップPC組み上げ

Tech

長らく使用していたDELLのノートパソコンXPS13のメモリ不足とストレージ不足が限界を迎えたので、新たにデスクトップPCを組んだ。


構成
OS: Windows 10 Home
CPU: Intel Core i7-9700K
メモリ: 16GB DDR4-2666
SSD(OS): 240GB
SSD(作業用): 500GB
マザーボード: ATX Z390 (MPG Z390 GAMING PRO CARBON AC)
電源: 750W (NeoECO Gold NE750G)
ケース: COUGAR TURRET
CPUファン: 虎徹 Mark II



一週間ほど使ってみた感想としては、平常負荷でCPUコア温度は40℃程度、ファンの音はCPUクーラー、電源、ケース備え付けクーラー共にまったく気にならなかった。一部レビューで電源ファンに高周波ノイズがあると聞いていたが、今のところ確認できず無音に近い。
映像出力はHDMIとDisplay Portのデュアルディスプレイで使用している。
ケースの強化ガラスは黒いスモークがかかっており、マザボやファンのLEDが透けて見えていい感じ。

FF14のパッチ5.0発売に合わせてRTX2070を追加予定。グラボ合わせてトータル180k切るくらいで納まった。 i7-9700K+RTX2070のBTOが170kほど(2019年4月現在)だったので大満足です。

 


備忘録:
新規インストールしたWindows10にてfirefoxでブラウジングした際に、.jpg形式の画像を保存すると拡張子が.jfifとなる問題が発生した。
原因はwindowsのレジストリキーが書き換わったためであった。
今まで使っていたノートPCではこの問題は確認できず、なぜ.jfifに置き換わったかは不明。

・環境
Windows 10 Home 64bit (Version 1809)

・修復手順
(1) Windowsメニューから「regedit」と検索してレジストリエディターを起動する。
(2) アドレスバーから以下のディレクトリを指定して「image/jpeg」の項目を開く。

  • コンピューター\HKEY_CURRENT_USER\Software\Classes\MIME\Database\Content Type\image/jpeg


(3) Extensionのデータの規定値を「.jfif」から「.jpg」に変更する。

・参考
FirefoxでjpegファイルをD&Dで保存すると拡張子がjfifになる問題 | PCトラブルあれこれ




GCPでWordPress運用 ― メモリ不足の解消

Tech ,

(更新日:2019年2月28日)
GCP(Google Cloud Platform)の無料枠で使用できるマシンのメモリは0.6GBと少なく、その上でWordPressを動かすとメディア編集などですぐにメモリ不足になります。
具体的な影響としてはメモリ不足でMySQLが動かず、データベース接続確立エラーでWordPressにアクセスできない問題が頻発しました。

そこで今回はストレージ上にswap領域を追加することでメモリ不足の解消を試みました。
試しに1GBのswap領域を確保したところ、WordPressの動作が安定してデータベース接続確立エラーが出なくなりました。

swapの設定手順は実マシン上でのLinuxOSの操作と変わりません。
VMに自動インストールされたdebianのswap領域は0Bとなっているので、手動で追加します。
パーティションは弄りたくないので、swapファイルを追加する方法を取ります。

続きを読む

GCP(Google Cloud Platform)でWordPressをはじめた際のメモ – 2019年2月

Tech ,

(最終更新日:2019年2月28日)
GCPの無料枠でWordPress環境(本サイト)をスタートした際の備忘録を残します。
[次の記事:GCPでWordPress運用 ― メモリ不足の解消]



ざっくりググって実践した際に詰まったポイントを主に書いていきます。
基本的な設定はこちらのサイトを参考にしました。
Qiita – GCP(Google Cloud Platform)でWordPressスタート(2018年10月)
大阪SEのメモブログ – 【WordPress移行】GCPでWordPress環境を構築する(2018年10月)

このうち、「大阪SEのメモブログ」様の手順でおおよそサイトの立ち上げを完了できました。

少し手間取ったポイントを記します。
(1) WordPressVMデプロイ時のwarning
上記ブログの通りにVMのディスク容量を無料枠の30GBに設定してWordPressのVMをデプロイしたところ、「ストレージが10GBを超えている」という旨のwarningが出ました。
VMのディスク容量は後からでも変更できるようなので、デプロイ時に10GBとして、後でVMマネージャからディスク容量を30GBに変更することでデプロイを完了させました。
なぜwarningが出たか判明する前にデプロイが正常完了してしまったので根本の解決はできませんでしたが、現時点で特に問題は見られません。

(2) 静的IPアドレス設定時のトラブル
WordPressをデプロイしたVMの外部IPアドレスを設定した際に、静的IPアドレスを使用するとWordPressへのアクセスが途端に重くなりました。
VMの外部IPアドレスはデフォルトで「エフェメラル」に設定されていますが、エフェメラルIPアドレスではVMの対外IPアドレスが変更されることがあります。
そのため、webサーバとして外部に公開するためにはVMのアドレスを「静的外部IPアドレス」に設定して固定する必要があります。
しかし、「静的外部IPアドレス」に設定したアドレスにブラウザからアクセスするとWordPressへの接続が遅すぎてタイムアウトで接続失敗、または画像データがロードできないといった事象が発生しました。

解決方法として、WordPressのURLをVMで設定した「静的外部IPアドレス」に変更することで、正常に接続できるようになりました。
GCPでWordPressを立ち上げた際に、WordPress側のデフォルトURLにはVMのエフェメラルIPアドレスが初期設定されています。
VMの外部IPアドレスを静的IPアドレスに変更してアクセスを試みた際に、WordPressのURLがエフェメラルIPアドレスのままであったためアクセスに失敗したようです。

WordPressのURLは「ダッシュボード > 設定 > 一般」から変更できます。
具体的な手順は以下の通りです。
GCPで「静的外部IPアドレス」を予約、静的IPアドレスを控えた上でVMの外部IPをエフェメラルに設定します(未使用の予約済み静的IPアドレスを所持していると料金が発生するそうですが、ステータスを見る限り今回課金は発生しませんでした。気になる方は要調査)。
ブラウザからVMのIPアドレス(エフェメラル)にアクセスし、WordPressにログインして「設定」のWordPress URLの中身を先ほど控えた「静的外部IPアドレス」に変更します。
その後、VMの外部IPアドレスを予約した静的IPアドレスに戻すことでWordPressに正常にアクセスできるようになりました。
サイトURLの変更後はブラウザ上でのサイトの接続、表示完了に1秒とかからなくなりました。

なお、USのeastデータセンタにVMを置きましたが、pingは160ms程度でした。
lolipopサーバでは9ms程度でしたが、webサイトとしてブラウジングする分にはUSサーバの現環境でも不自由はない体感です。