FC2ブログ

頭と尻尾はくれてやる!

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


daeファイルはアプリのビルド時に圧縮される?

Blenderで作成したdaeファイルをNSXMLParserでパースしたい

↑これにからんでなんとかdaeファイルのテキストを得ようとしてるんだが、、、
どうやらビルド時にdaeファイルは圧縮されてるようでテキストを得るのが無理っぽい、というか俺にはできそうにない。
順に書いていくと、、、

daeファイル


↑Blenderでdaeファイル(COLLADA)を出力したとする。どこでもいいんだけど、デスクトップにあるとする。

daeファイルをテキストエディタで見る

↑このdaeファイルをテキストエディタで見ると、xmlファイルだ。

Xcodeに持って来たdaeファイル

↑そのファイルをXcodeに持ってくる。参照じゃなくてコピーする。
するとプロジェクトを置いてるところにdaeファイルがコピーされる。

XcodeのShow in Finder

↑XcodeのShow in Finderで確認可能。ただ、アプリ実行時にはこのファイルを直接使うわけじゃない。
{
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"frog5" ofType:@"dae"] ;
}
↑macOSアプリ内でこのdaeファイルを使おうとこのようにしてパスを得る。
実行時にこのパスを確認すると
/Users/yama/Library/Developer/Xcode/DerivedData/180807Outline-dmdarosyorbzvzennfoggerorzuk/Build/Products/Debug/180807Outline.app/Contents/Resources/frog5.dae
なんて出てくる。さっきShow in Finderで見たのとは別なところにある。.appのさらに下側にバンドルされるみたいでFinderなんかではもう見えない。

ビルドした時点で多分daeファイルは圧縮されてる。
アプリで上記パスのファイルを copyItemAtPath:toPath:error: でコピーして(※1)そのファイルをFinderで確認すると容量が
627,908バイト→227,491 バイト
と大きく圧縮されていた。
この圧縮されてるファイルをテキストエディタで覗いてみると

圧縮されたdaeファイル

↑こんな感じで元のxmlファイルとなにやら違う。APPLE独自のものになってるんだろうか。

つまり、Xcodeに持って来たファイルはビルド時にバンドルされるわけで、そこでdaeファイルは圧縮される。そうなるとそのファイルを「どーせ、xmlファイルだろ?」と思ってパースしようとしても無理!
ということだと思う。まずいな、、、😖


※1
copyItemAtPath:toPath:error: メソッド実行時に圧縮されてるかもと思ったけど、コピーする前のファイルもxmlとしては読めないし、外部のdaeファイルをコピーしても圧縮しない(パースできる)。やっぱりビルド時に圧縮してるんだろう。


Kerasのコールバック関数内で係数にアクセスする

Kerasで係数の保存と読み込み
↑Kerasでの学習結果をファイルに保存はできた(※1)。

それらを強化学習用にmacOSアプリで読み込みたい。
調べるとcoremltoolsなるものを使ってmlmodelに変換できるらしいのだが、、、噂通り難易度が高く、、、pipでインストールするもエラー出まくりで、、、はい、諦めました、、、😭

いや待て、そもそも学習中の係数にアクセスしてそのまま保存してやればいいんじゃね?モデル構成なんかいらんし、実際強化学習となればいちいち変換なんてやってらんねえぞ。
ということで

(1)学習中に呼び出される関数の設定
(2)コールバック関数で係数にアクセス

この二つが可能か調べた。


(1)学習中に呼び出される関数の設定
これは前記事にあるようなコールバック関数でよさそう。リファレンス(※2)にサンプルコードもある。
class TestCallbackFunction(keras.callbacks.Callback) :
    def on_epoch_end(self, epoch, logs={}) :
        print("on_epoch_end [%d]"%epoch)
↑呼び出されてほしい関数を作っておいて
test_cb = TestCallbackFunction()
↑設定して前記事と同様fitで渡してやる。

すると、1epoch終了ごとにこの関数が呼び出されてる!よしよし。


(2)コールバック関数で係数にアクセス
いろいろ調べた結果、、、
class TestCallbackFunction(keras.callbacks.Callback) :
    def on_epoch_end(self, epoch, logs={}) :
        print("on_epoch_end [%d]"%epoch)
        lastLayer = self.model.layers[-1]
        print(lastLayer.get_weights())
↑モデルオブジェクトにはself.modelでアクセスできる。
modelを構成する層はlayersで取得できるので、一番最後の層を
lastLayer = self.model.layers[-1]
として取得してる。-1で最後のを指定できるって最近覚えました。
layerの係数は get_weights() でアクセス。

Kerasの出力

↑実行結果、とりあえずウエイトとバイアスの出力まではできた!
それにしてもKerasの日本語リファレンスは親切だねえ。


※1
前記事ではモデルと学習後の係数を別々に保存してるけど実は一度にできるらしい。
model.save(f_dir + “model_and_weights.h5”)
↑これでモデルも係数もいけた。

※2
コールバック - Keras Documentation


ファミリー共有してるアプリのアプデができなくなった

ファミリー共有してる有料アプリ(マイクラ)のアップデートが嫁さんのiPhone 6でできなくなった。

iPhoneのエラーメッセージ

↑App Storeアプリでアップデートしようとしても
共有コンテンツはご利用いただけません。
共有コンテンツにアクセスするには、ファミリー管理者がファミリーのお支払い方法を更新する必要があります。

というばかりでできない。ファミリー管理者って俺だよな?ってことで調べた。

家族の共有コンテンツが表示されない場合 - Apple サポート
↑公式のサポートページを見つつアカウントのサインアウト→サインインとかやるも状況変わらず、、、

ようやくわかったのが自分のApple IDに紐づけているクレジットカードの有効期限が切れてた、ということだった。
スクショないんだけど、iPhoneの設定から自分のカード情報を見ても不具合があるようには見えない。何の警告もない。番号のほとんど、有効期限なんかは伏せ字になってるし。
ただ、警告に支払い方法うんぬんとあったので念のためカード情報(セキュリティーコード)を入力したら、過去の日付はダメ、みたいなのが出たので気付いた。

そんなわけで有効期限(あとセキュリティーコードも)を修正したら問題解決した。


ん?でも先月Apple Developer Programの支払いで有効期限に問題ないカードで支払ってるはずなんだがなあ、、、🤔


Blenderで作成したdaeファイルをNSXMLParserでパースしたい

macOSアプリでdaeファイルの中身を調べたいことがあった。daeファイルって、基本xmlファイルだからテキストエディターなんかで中身を見ることができる。
NSXMLParserを使えば中身を取得できるのだが

daeをXcodeにインポート

↑このようにdaeファイルをXcodeにインポートした場合はうまくできなかった(外部に置いている場合(※1)はできてた)。

やりたいことは、
(A)SceneKit(※2)で使い、かつ
(B)daeファイルをパース
を両立させたいわけだ。

Bのパースするためのコードはこんな感じ↓
{
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@“frog5” ofType:@“dae”];
    NSURL *targetURL = [NSURL fileURLWithPath:filePath];//(※3)

    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:targetURL];

}
ファイルの有無をチェックするとちゃんと有る、となるのだがパースができない。
手打ちで拡張子をxmlもしくはscnに変更するとパースは可能になったのだがAのSceneKitで使うことはできなくなる。

Convert to dae to scn

↑ならば、とdae→scnにちゃんと(?)Xcodeの機能
Editor / Convert to SceneKit scene file format (.scn)
で変換してやると、、、当然SceneKitで使えるが、パースができなくなった。

ならば、とdae→NSStringにすればNSXMLParserの
initWithData:
でパースできんじゃね?と思ったけどdaeファイルの文字列を取得できなかった(※4)。


結局、ABを両立させることはできなかった。
回避策としては、一度どこかにdaeファイルを保存してからそれを読み込むか、Xcodeインポート時にdaeとxmlの二つ作成するか(試してないので動くか不明)。まあどちらにせよダサい、ダサすぎる、、、



※1
外部のdaeファイルを指定するコード。
↓これだと問題ない(ABともいける)。
{
    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:targetURL];//パース可能
}
※2
daeファイルをSceneKitで使うのに↓のようにしてSCNSceneオブジェクトを得る必要がある。
{
    SCNScene *daeScene = [SCNScene sceneNamed:daeFileName];
}
しかしこの形式で使えるファイル形式は定められていてリファレンスによると↓のようになってる。
SCNSceneリソース形式

※3
↓この方法でNSStirng→NSURLに変換すると動かないってのは何回もはまってきたんだけど今回の問題はこれじゃない。
{
    NSURL *targetURL = [NSURL URLWithString:filePath];
}

※4
↓これだとdaeファイルの文字列を取得できなかった。
{
    NSString *content = [NSString stringWithContentsOfFile:filePath
                                                  encoding:NSUTF8StringEncoding
                                                     error:&error];
}



macOS High Sierra 10.13.6
Xcode 9.4.1


KerasでのTensorBoard関連の設定をする

Kerasで係数の保存と読み込み
↑この続きというわけでもないけど似たようなコードになる。
KerasでもやっぱりTensorBoardに記録したいよねってこともあるだろう、ということでそのあたりのメモ。
tb_cb = keras.callbacks.TensorBoard(log_dir=log_filepath, histogram_freq=1)
↑コールバックでTensorBoard用にデータ保存せえよって指定できる。

initial_epoch = 0
epochs=5
とすれば

Kerasでの計算結果出力

↑このように1〜5の5エポック分の計算を行う。

TensorBoardの画像1

↑ただ、TensorBoardだと0から表示されるっぽい。

TensorBoardの画像2

↑係数ファイルを読み込んで継続した場合もOK。よしよし。
それにしても記述がめっちゃ少なくなるな、、、恐るべし、Keras!



ところで、ここまでやってみた内容(モデルと係数の保存・読み込み、TensorBoardの使用)だと
import keras.backend.tensorflow_backend as KTF

old_session = KTF.get_session()

with tf.Graph().as_default():
    session = tf.Session('')
    KTF.set_session(session)
といったTensorFlowに関係するらしき記述が必要なくても意図通りに動いてるみたいなんだけどいいんかな?
[TF]KerasからTensorboardを使用する方法
↑例えばこちらなど、調べるとそういう記述がされてるのをよく見るんだがなぜ必要なのだろう、、、?




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

FC2Ad