littlewing

人間とコンピューターとメディアの接点をデザインするために考えたこと

UWPのTextBoxでEnterキーでVirtual keyboardを閉じる

UWPの2DビューでIPアドレスなど一行だけ入力したときにEnterで、キーボードを閉じるには自前で以下のような実装をしないといけません。

こんな感じ

hoge.xaml

  • XAML側でKeyDownイベントを取得する
  • この場合は自作のOnKeyDownHandlerを呼び出しています
<TextBox x:Name="hoge" KeyDown="OnKeyDownHandler" HorizontalAlignment="Left" Margin="166,112,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="189" InputScope="AlphanumericHalfWidth"  />

hoge.xaml.cs

  • OnKeyDownHandlerでEnterを検知してキーボードを閉じる
  • using Windows.System;が必要です。
private void OnKeyDownHandler(object sender, KeyRoutedEventArgs e)
{
        if (e.Key == VirtualKey.Enter)
        {
                Windows.UI.ViewManagement.InputPane.GetForCurrentView().TryHide();
        }
}

カメラキャリブレーションの用語の覚書

なんとなくやっていたカメラキャリブレーションについて 用語の定義など改めて調べてみた。

文末の「参考」にある opencvのドキュメントなどが詳しいのだが 用語がわからないと、理解が進まないので、自分が理解するためのメモ。

https://pbs.twimg.com/media/DL20xKTV4AEv4TP.png

画像引用元


Distortion Coefficients (レンズ歪みパラメータ )

  • 放射状歪み と 接線歪みを補正するパラメータ
  • [1 x 4] もしくは [1 x 5] の行列として表現される

  • 放射状歪み(Radial Distortion) は直線が曲線になるような歪み

    • 画像中心から離れれば離れるほど歪みは大きくなる。
    • k1 , k2, k3として表されることが一般的。
  • 接線歪み(Tangential Distortion)は,レンズと画像平面が完璧に平行になっていないことが原因で生じる歪み。

    • ある領域が期待しているよりも近くにあるように見えてしまう。
    • p1 , p2として表されることが一般的。
  • opencvの行列表現では

 Distortion\ Coefficients  =  \begin{pmatrix} k_1&k_2&p_1&p_2&k_3 \end{pmatrix}

として表現される。※k3が省略の場合もあり


Intrinsic Parameters (内部パラメータ) 

  • カメラ固有のパラメータ。カメラ行列とも呼ばれる
  • 同じカメラで同じ設定であれば常に同じ
  • [3 x 3] の行列として表現される
  • 焦点距離
    • Focal Length = (fx , fy ) (単位はピクセル)
  • 光学中心(主点)
    • Principal Point = (cx , cy ) (単位はピクセル)

 Intrinsic\ Parameters  =  \begin{pmatrix} f_x&0&c_x \\ 0&f_y&c_y \\ 0&0&1 \end{pmatrix}


Extrinsic Parameters (外部パラメータ)

  • ある座標系における3次元点の座標を別の座標系での座標に変換するための回転と並進のパラメータを指します.
  • マーカーとカメラ間の位置関係などを設定します。
  • [3 x 4] の行列として表現される

 Extrinsic\ Parameters =  \begin{pmatrix} R_{11}& R_{12}& R_{13}& t_x \\ R_{21}&R_{22}&R_{23}&t_y \\ R_{31}&R_{32}&R_{33}&t_z \end{pmatrix}  \\R:回転行列\\t:並進ベクトル


参考

imura-lab.org

HoloLens のDevice Portalにlocalhostで接続するには、Windows SDKが必要

HoloLens のDevice Portalにhttp://localhost:10080 もしくは、http://127.0.0.1:10080/で接続するには、Windows SDKが必要。

良く見たらドキュメントにも書いてあった。

PC に Visual Studio Update 1 と Windows 10 開発者ツールをインストールします。 これで USB 接続が有効になります。

Windows SDKは、全部入れると数ギガになるのだが、 試したところ、USB接続を利用するだけなら「Windows IP over USB」が入っていれば、DevicePortalは利用できた。 これだけなら、1M以下で済む。

f:id:pigshape:20180129162153p:plain

知らなくて、非開発用PCを利用した場合にはまったのでメモ。

Unityで利用する c++ のDLLを作成する。(Visual Studio 2017)

基本的に、以下のページにある手順で進めればNative Plugin を作成できるのですが 解説が、VS2013ベースになっているので、Visuai Studio 2017で実施した場合に ハマッた部分を、忘れないうちにスクショ付きでまとめました。

部分的にしか解説してないので、全体は以下のページを参照してください。

qiita.com

  • Visual Studio Community 2017
  • Unity 2017.3.0f3
  • Windows 10 Fall creator update

でやりました。


DLLビルド用のVSプロジェクトの準備

  1. 既存のソリューションに、DLL作成用のプロジェクトを追加する場合はこんな感じでスタート

f:id:pigshape:20180118122930p:plain

  1. DLLを作るのですが、この画面では、「c++ のWin32コンソールアプリケーション」を選択。 f:id:pigshape:20180118123005p:plain

  2. 次に表示されるこの画面で「アプリケーション設定」をクリックして、DLLを選択します。 シンボルのエクスポートも忘れないように。 f:id:pigshape:20180118123057p:plain

  3. Unityに出力するなら「SDLのチェック」は外さないといけないらしいです。

f:id:pigshape:20180118133326p:plain


で、コードを書く。ここは省略します。


exe形式で実行テスト

同一ソリューション内で、テストのためのexe用プロジェクトを作成したのであれば、 「参照の追加」を行うのが、手っ取り早いです。

f:id:pigshape:20180118131611p:plain

ただし、既存の外部DLLやlibを使う場合はこれではダメです。 そのような場合は、以下の3つを設定します。

  1. c++  > 全般 > 追加のインクルードディレクトリ include/フォルダを指定し、その中に.hファイルを置く f:id:pigshape:20180118131154p:plain

  2. リンカ >全般>追加のライブラリディレクトリ libフォルダを指定 f:id:pigshape:20180118131322p:plain

  3. リンカ >入力 >追加の依存ファイル libファイルを指定 f:id:pigshape:20180118131345p:plain


作成したDLLをUnity上で実行する

Unityからは

[DllImport("sample-opencv-dll")] private static extern int CountUp();
            Debug.Log(CountUp());
            Debug.Log(CountUp());
            Debug.Log(CountUp());

のような感じで呼びだすことができます。 「DllImport」にファイル名を書くときは拡張子 (.dll)を含めるとエラーになるので含めません。


libで追加ライブラリを指定した場合は、そのdllもPlugins内に配置しておかないと、

Plugins: Failed to load 'Assets/Plugins/x86_64/xxxxxxxx.dll' with error '指定されたモジュールが見つかりません。
'.

という警告や

DllNotFoundException: Failure has occurred while loading a type.

という例外エラーが発生するので、関連DLLの配置もお忘れなく。


おまけ 既存DLL ( or lib ) の中身を解析する方法

スタートメニューから[開発者コマンド プロンプト for VS2015]を起動する

  • DLLのインターフェースを確認する
cd (DLLの場所)
dumpbin  /exports xxxxx.dll
  • dllが32bitか64bitか確認する。
dumpbin   /HEADERS xxxxx.dll | findstr machine

Unity 2017.3 で TouchScreenKeyboard が使えない

Unity 2017.3を利用してHoloLensアプリを開発する際に、キーボードが使えなくて困ったのでメモ。

D3DのHoloLensアプリケーションではキー入力が使えないのですが、 Unity 2017.2までは、 Build TypeをXAMLにして、TouchScreenKeyboardを利用すれば、自動的にXAML画面が呼び出されて文字入力を行うことができました。

littlewing.hatenablog.com

具体的には以下のコードをGameObjectにアタッチすると、startが呼び出された時点で、本来はキー入力画面が表示されます。

public class InputTest : MonoBehaviour
{
    TouchScreenKeyboard keyboard;
    public static string keyboardText = "Input any";
    // Use this for initialization
    void Start()
    {  
        Debug.Log("start keyboard");
        if (keyboard == null)
            keyboard = new TouchScreenKeyboard(keyboardText, TouchScreenKeyboardType.Default, false, false, false, false, "sample prompting text that goes above the textbox");
        else
            keyboard.active = true;       
    }
}

しかし、これが、Unity 2017.3では動かない。アプリが落ちてしまいます。特に例外も発生しない。

Unity version Result
Unity 2017.3.0b10 not working
Unity 2017.3.0f3 not working
Unity 2017.2.0b11 working
Unity 5.6.3f1 working

Unity 2017.2とUnity 2017.3でBuild出力されたC#プロジェクト内の、MainPage.xaml.csを比較してみたところ、

 appCallbacks.SetKeyboardTriggerControl(this);

の記述が、Unity 2017.3では削られていました。

//Unity 2017.2.0b11で出力した、MainPage.xaml.cs抜粋

appCallbacks.RenderingStarted += () => { RemoveSplashScreen(); };

#if UNITY_UWP
                if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Phone.PhoneContract", 1))
                    isPhone = true;
#endif

//ここから、4行がUnity2017.3では無い。
#if !UNITY_WP_8_1
                appCallbacks.SetKeyboardTriggerControl(this);
#else
                isPhone = true;
#endif
//ここまで

appCallbacks.SetSwapChainPanel(GetSwapChainPanel());
appCallbacks.SetCoreWindowEvents(Window.Current.CoreWindow);
appCallbacks.InitializeD3DXAML();

そこで、2017.3側で SetKeyboardTriggerControlを追加しようとしたところ、そんなメソッドは無いと怒られます。

f:id:pigshape:20180105194643p:plain

Documentには載ってるのに・・

あきらめて、自前でXAML Page作ります。

xaml切り替えは @d_yamaさんの解説記事がわかりやすいです。

blog.d-yama7.com

HoloLens+Arucoを触ってみた

こちらのリポジトリの「HoloLensArucoTracking」を触ってみた https://github.com/KeyMaster-/HoloLensArucoTracking/

  • Editor用とHoloLens用のSceneがある。
  • 使い方はReadme見れば大体わかる
  • Unity 5.6.3とUnity 2017.3.b10でHoloLens実機ビルドできた。

youtu.be

注意点

特定のIDに反応させたい

  • MainCameraについている、MarkerObjectPlacer.csがONの状態だと、どのマーカーにも 反応してCubeが表示される。
  • 特定のIDを利用したい場合は、TrackedObjectExampleを利用する。

マーカーIDを指定しても反応してくれない

  • READMEにも書いてあるが、ArucoのマーカーIDがOpenCVのものと、本家(このコードはこっち)で異なる。 そのためAruco Marker Generatorなどで、マーカーを作成した場合はIDが異なるので注意。 どのIDが反応しているかを調べるには、先ほど書いたメインカメラについている、MarkerObjectPlacer.csのonDetectionRun()部分で
        for (int i = 0; i < ArucoTracking.marker_count; i++) {
            PoseData pose = trackingRunner.poseDict[ArucoTracking.ids[i]];
            Debug.Log("ID is " + ArucoTracking.ids[i]);  //★この行を追加

            quadInstances[i].transform.localPosition = pose.pos;
            quadInstances[i].transform.localRotation = pose.rot;
        }

などとしてやれば調べることができる。 OpenCVのMarkerID:1はこのコードではID:256として反応した。

マーカーの位置がずれる

MainCameraについているArucoRunner.csに、マーカーの実寸サイズをちゃんと指定してやる必要がある。

一辺、36mmのマーカーなら、Inspector上でMarker Size 0.036と指定してやる。


その他のAruco関連ライブラリ

MarkerBased AR Example

ちなみに、Arucoを動かすことができるAssetがAssetStoreにもある。

こちらも試していましたが、カメラキャリブレーションがそのままでは、ガバガバなので、 ちゃんと使うには自前で調整が必要そうです。

aruco-unity

Unity上でのカメラキャリブレーションに関しては、こちらのプロジェクトにはキャリブレーション用のシーンがありました。

github.com


参考ドキュメント