頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


SceneKitでマスクをしたい

ARKitを使ってごにょごにょしてるんだけど、どこでもドア的な表現をSceneKitでしようとしてふと固まってしまった。SceneKitでマスクってどうやるんだ?

どこでもドアの向こう側には別な世界があって、それらがドアの入り口形状の長方形でマスクされれば表現できるわけだけど、、、

いろいろ調べたつもりなんだがマスクのやり方がわからない。

Metalのステンシルバッファでマスクしてみる
↑Metalでステンシルバッファ使ってやったことはあるけど、、、超絶めんどくさい。天下の(?)SceneKitなんだからもっとサクッとできそうな気がしてならない。

結局、、、ステンシルバッファは使わずに、SceneKitでオフスクリーンレンダリング、つまり最初にマスクしたいオブジェクト(どこでもドアの向こうにあるオブジェクト)をMTLTextureに出力し、次にドアのこちら側のオブジェクトとドア入り口の長方形をディスプレイに表示する。その長方形の色はフラグメントシェーダーでMTLTextureから選んで表示してやる、という流れでやることにした。

オブジェクトの位置関係

↑位置関係はこんなの。黄色い四角形がドア入り口に相当。

↑床面がドアの向こうにも表示されてるのはご愛嬌(手抜き)。

GitHub - lachlanhurst/SceneKitOffscreenRendering: Using SCNRenderer to render a scene offscreen to a texture that's then displayed in another scene
↑すごく参考になったのがこちらのコード。不要な部分を排除してすんごい理解しやすいコード。感謝、感謝。SCNRendererクラスって初めて使ったわ。

上のサンプルコードと異なる部分だと、、、
出力するテクスチャの設定。
{
	MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm width:width height:height mipmapped:NO];
	offscreenTexture = [device newTextureWithDescriptor:textureDescriptor];
}

ドア入り口の長方形の表示にシェーダーを設定する。ここでシェーダーに渡してやるテクスチャ画像をoffscreen renderingの出力画像に設定してる。
-(void)setupShaderForNode:(SCNNode *)node
{
    SCNGeometry *geometry = node.geometry;
    
    SCNMaterial *material = geometry.firstMaterial;
    
    SCNProgram *program = [SCNProgram program];
    program.vertexFunctionName = @"myVertex";
    program.fragmentFunctionName = @"myFragment";
    material.program = program;
    
    SCNMaterialProperty *imageProperty = [SCNMaterialProperty materialPropertyWithContents:offscreenTexture];
    [material setValue:imageProperty forKey:@"offscreenTexture"];
}

こんな感じでマスクできそうだけど、、、
うーーーーん。やっぱりそのうちSceneKitでしれっと実装される気がする。


XcodeのコンソールにはPythonだと日本語出力できない?

ずっとPython 3を使うのにXcodeを使ってるんだけど、これまで日本語出力はしてなかったのよ。
いや出力しようとするとうまくいかなくて調べるのも面倒だから日本語は使わなかった、ってだけだったんだな。
今まではそれで事足りてたんだけどさ。

最近、Pythonでスクレイピングとかやってんのよ。そしたらどうしても日本語を扱うわけで、その時にエラーが出てしまい困ってるんだわ。

ネットで調べてもPython 2ならともかく3ならそれほど悩まなくても良さそうなもんだけど、、、

print("テスト")
例えば↑このPythonのコードをXcodeから動かすと、、、

print("\u30c6\u30b9\u30c8")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
↑エラーになる。encodeだのunicodeだのいろいろと試してみたがコンソールに日本語が表示されることはなかった。

Python3の実行結果

↑でもターミナルからだと動く。

きっとXcodeになんかあるんかな?ってことであきらめた。



Python 3.5.2 :: Anaconda 4.1.1 (x86_64)
Xcode 8.3 (今はXcode 9 beta 3を使ってるけど正式版からずっとこの調子)



iOS 11のARKit使ったdemo動画を作ってみた

久々にiMovie使って編集なんぞをしてYouTubeに動画をアップしてみた。



↑iOS 11のARKitを使った動画なんだけど、細かいことはまだbeta版なので差し控えておくとして、関係なさそうなところに関して言うと、、、

ARKitを使って得た平面の下や周囲に見えないような床や壁のオブジェクトを作って置いてる。
Switchの箱とAMRSのパッケージはBlenderでdaeファイルを作成、Xcode側に持って来てSceneKitで物理エンジン用の設定もして世界に発生させてる。
ARKit面白いねえ〜

部屋のテーブルにコインを大量発生させたところを撮影できるようなアプリでも作ろうかな、とか思ってみたけどコインが小さいせいか物理エンジンによる挙動がおかしくてボツ。なんかいいアイデアねえかなあ。



iOS 11 beta 3
Xcode 9 beta 3



SceneKitのライトの明るさを設定するのにはまった

SceneKitにSCNLightってのがあってそのプロパティのintensityを変えればライトの明るさを変更できると思ってたんだけど、、、何だかうまくいかなくてしばし悩んだ。

やろうとしたのは最初は真っ暗で、あるタイミングでライトを点灯する、ってだけ。
最初に
spotLight.light.intensity = 0.0;

として、ライトを点けるところで
spotLight.light.intensity = 1000.0;

とかすりゃいけそうやん?ところがこれが意図通りにならない。

いろいろと調べたけど直接の原因はよくわからなかった。
ただ、最初の値を0にしちゃうとその後いくら値を設定しようがダメで、最初の値を1.0とかにしとくと変更することができた。



memo
Xcode 8.3.1


機械学習で人体頭部の姿勢を得る(4)

機械学習で人体頭部の姿勢を得る(3)
↑の続き。全然あかん、こうなったらヤケクソや!何がなんでもデータセットに含まれる顔の種類を増やすんやあ!ってことでなんとか楽に増やす方法を検討した。

今まではMakeHumanで出力したdaeファイル及びテクスチャ画像をBlenderで再設定してdaeファイルを出力、それをXcodeに持ってきて使ってた。Blenderで設定するのが面倒だったので、以前はあきらめたBlenderを介さない方法を再検討。

1) MakeHumanでのdae出力のオプションでBone orientationをLocal=Globalってのに変更、OrientationはY up, face Z(デフォ)で出力。
2) SceneKitではScene assetsのSettingsでAlways use the Y-up axisのチェックを外す

この状態だとテクスチャが設定されていないのでそこはコードでやる。
髪形や眉毛の形もdaeファイル内の文字列を調べれば設定すべきpngファイルはわかる。

そんなわけでMHでランダムに顔を作成、できたデータから差し替えていった。最終的には140種類の顔でそれぞれ1,000枚で14万のデータセットとなった。
そしてぶん回した。175kあたりで跳ね上がってるあたりからできたデータから順に差し替えてる。

TensorBoardの結果

↑データ差し替えからでもざっくり700時間くらい動かしてる。
その結果がこちら。↓



微妙だ。汎用性を求めるならやはり相当工夫してデータセットを作成する必要があるのか、、、

さらに、iPhone 7 Plusのフロントカメラで自分の顔の姿勢を把握できるか試してみたのが下の動画。むしろこれだけでもできれば、と思ってたが、やっぱり微妙。普通の光源、背景だとグタグタでそれっぽく動く状態にして撮影してこれだからなあ、、、



こういうのができたら自分専用モーションキャプチャーとか作れんじゃね?と思っていたけど、、、

今後はNNの構成を変更するとかカラー化するとかそもそものデータセットに工夫するとか色々手はあるかもしれないけど、機械学習は時間がかかるなあ。さて、どうするかな。



なお、iOSでのMetal Performance Shaderで推論するのに1画像あたり13〜21msec程度なので60FPSは微妙かもしれないけど1秒に数コマなんてことでもない感じ。今は実装してないけどカメラからの画像をMetal(GPU)使って欲しいサイズのデータを得てそのままMPSへ渡せばもっと早くできるんだろうな。



memo
iOS 10.3.2
MakeHuman 1.1.0
Python 3.5.2 :: Anaconda 4.1.1 (x86_64)
TensorFlow 1.0 ← ええかげんアップデートせにゃ!




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad