頭と尻尾はくれてやる!

iOSアプリなどの開発日記です


iOSアプリ赤ちゃんの成長グラフver2.3(ARKitで身長計測機能の追加)が公開

変更内容はARKitを使って子供の身長を計測できる機能の追加。もちろん今まで通り手入力もできる。



↑こんな感じで。
子供の身長は2歳未満は寝かして、2歳以上は立って計測する(※)ので自動的に2歳未満の場合は横向き(壁から頭)、2歳以上は縦向き(床から頭)を計測する。
頭部把握後にドラッグで微調整できる。
画面をダブルタップでリセットできるんだけど、これを記述するの忘れてたな、、、😨


ちなみにこれ、コード自体は1年くらい前にできてた。
昨年の今頃ARKitを引き連れiOS 11が公開になった。事前にXcodeのbeta版をインストールしてARKit使った機能を組み込もうと作っていたのだが、どういうわけか申請ができなかった。このアプリだけでなく他の場合でも。
Appleのサポートといろいろとやりとりするも何の進展もなく時だけが経過してた。
ところが最近MacをMojaveにアップデートしたらすんなり申請できたのだった。
昨日申請し、今日にはReady for Saleへ。感慨深い。


※厚生労働省が統計を取るのに定めている計測方法。なので母子手帳に載ってるグラフなんかを見ると身長は2歳で不連続になってる。
スポンサーサイト






NSTableViewに置いたNSPopUpButton等の変化時にどの行のボタンなのか得る

NSTableViewにNSPopupButtonを置く
↑これの続き。
NSTableViewに置いてるcheckboxやpopup buttonを変更した時(popup buttonだと変更しなくても)、メソッドがコールされるようにしてるけど、実はどの行に対するアクションなのかがわからない。
bindingで全ての状態がわかるので、調べればわかるといえばわかるのだけど、、、なんとも面倒だ。
やっぱりどの行のNSPopUpButtonオブジェクトやNSButtonのチェックボックスが変更されたのかを知りたい。

調べるとNSTableViewクラスに
- (NSInteger)rowForView:(NSView *)view;
というメソッドがあってこれを使えばよい。

storyboardでNSTableViewに置いたボタンからコード側にactionをつなぐとすると、そのメソッドはこれらのような感じになる↓
-(IBAction)tappedCheckbox:(id)sender
{
    NSButton *checkbox = (NSButton *)sender;
    NSInteger row = [tableView rowForView:checkbox];
    NSLog(@"row=%ld",row);
}

-(IBAction)tappedPopUpButton:(id)sender
{
    NSPopUpButton *button = (NSPopUpButton *)sender;
    NSInteger row = [tableView rowForView:button];
    NSLog(@"row=%ld",row);
}
これでどの行に対するアクションなのか知ることができる。

なお
IBOutlet NSTableView *tableView;
↑このようにtableViewはNSTableViewオブジェクトで、storyboardから参照を持ってきてる。


符号なしcharと浮動小数点数を持つバイナリファイルをObjective-Cで保存しPythonで読み込む

浮動小数点数を持つバイナリファイルをPythonで読み込む
↑この続き、というか変化球というか。

macOSアプリ(Objective-C)で機械学習のデータセットを作成する時に入力と正解ラベルをセットにして1ファイルにするとなにかと都合がいい(いろんなケースがあるだろうけど、自分の場合は)。
ということで、macOSアプリ側で画像データ(unsinged char)の後に正解ラベル(float値)を付けて一つのバイナリファイルとし、それをPython側で読めるようにしたい。
今回はそういうことが可能か確認した。

最初に5個のunsigned char値を入れ、その後に5個のfloat値があるとし、そのバイナリファイルを扱う。

まずmacOSアプリ側で作成し、保存する。
{
    // unsigned char値の作成
    NSUInteger nofCData = 5;
    unsigned char *cData = calloc(nofCData, sizeof(unsigned char));
    for (NSUInteger ite=0; ite<nofCData; ite++) {
        cData[ite] = ite*10;
    }
    for (NSUInteger ite=0; ite<nofCData; ite++) { // チェック
        NSLog(@"data[%ld] = %hhu",ite,cData[ite]);
    }
    // float値の作成
    NSUInteger nofFData = 5;
    float *fData = calloc(nofFData , sizeof(float));
    for (NSUInteger ite=0; ite<nofFData; ite++) {
        fData[ite] = (float)ite/10.0;
    }
    for (NSUInteger ite=0; ite<nofFData; ite++) { // チェック
        NSLog(@"data[%ld] = %f",ite,fData[ite]);
    }
    

    // 保存
    NSString *filePath = …
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager createFileAtPath:filePath contents:[NSData data] attributes:nil];//カラを新作
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];

    NSData *nsCData=[NSData dataWithBytes:cData length:nofCData*sizeof(unsigned char)];
    [fileHandle writeData:nsCData];
    
    NSData *nsFData=[NSData dataWithBytes:fData length:nofFData*sizeof(float)];
    [fileHandle writeData:nsFData];

    [fileHandle synchronizeFile];
    [fileHandle closeFile];
}
↑コードはこんな感じで、NSFileHandle使って順番にunsigned char値を保存し、次にfloat値を保存する。
あらかじめ
- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
でカラのファイルを作成しておく必要がある。でないと落ちないけどファイルができない。
{
    //これだとダメ
    NSData *nsCData=[NSData dataWithBytes:cData length:nofCData*sizeof(unsigned char)];
    [nsCData writeToFile:filePath atomically:YES];
    NSData *nsFData=[NSData dataWithBytes:fData length:nofFData*sizeof(float)];
    [nsFData writeToFile:filePath atomically:YES];
}
↑なお、このように以前と同じようなNSDataの
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
メソッドで保存すると後の方しか保存されないのでダメ。

macOSアプリ側での実行結果

↑チェックした値の確認。

作成・保存したファイルの情報

↑計算通り 1バイトx5個 + 4バイトx5個 = 25バイトのファイルができた。


次にPython側でこのファイルを読み込む。
{
    fid = open(FilePath, "rb")
    for ite in range(5) :
        r = struct.unpack('B', fid.read(1))
        print("data[%d]=%d"%(ite,r[0]))
    for ite in range(5) :
        r = struct.unpack('f', fid.read(4))
        print("data[%d]=%f"%(ite,r[0]))
}
↑こちらもopenしたファイルを順番に読み込んだらいけた。

読み込んだ結果

↑実行後の結果。めでたし、めでたし。


(参考)
Objective-cでファイル書き込み - 備忘録 〜プログラミング〜


MacでPHPを動かす時のメモ

久しぶりにMacでPHPを動かす必要があったんだがすっかり忘れていたのでメモ。

MacでPHPを使う時の設定
↑ここにもあるが、、、


sudo vi /etc/apache2/httpd.conf
↑ターミナルからviでファイルの編集をする。これで起動。


LoadModule php7_module libexec/apache2/libphp7.so
↑ここがコメントになってるので有効にする。
え?今のMacで動かしていなかったのか?!動かしていたはずだと思い込んでた。


DocumentRoot "/Library/WebServer/Documents"

↑この2行を書き換えて作業フォルダを指定する。

/Users/yama…/Dropbox/website/
↑phpファイルはDropboxに置いてるのでこのようにして書き換えた


vi コマンドリファレンス
↑viの操作はこちらを参考に。
カーソル移動は矢印キーを使う(普段のショートカットだとダメ)。
iで入力モードに入り入力できる、escで元のコマンドモードに戻る。
ZZで保存して終了。


sudo apachectl start
↑これで起動できる。
ブラウザにlocalhostでOK。


地味にPHPって7まで行ってたの?と驚いた。



macOS Mojave 10.14


Kerasに自作データセット(画像)を与えてみる

MNIST(手書き文字認識)で使うpng画像、つまり手書き文字の画像がフォルダ内にあるとして、、、
それを読み込んでKerasで使うことはできるか?というのを確認した。

MNISTに取り組む場合、それが機械学習のHello World的な位置付けということもあってトレーニングデータ、テストデータがどういう風になっているのかなんて気にすることはない。ただ使うだけ、という具合になってる。

KerasでCNNを使った強化学習をやろうとしているので、自作データを学習に使えるのか?というのを確認しておきたかった。

png画像フォルダ

↑幸いMNISTで使うpng画像がすでにある。だいぶ前にpng画像からtfrecordファイルを作成できるか確認するために作成したpng画像だと思う。
これを使ってテスト用のデータセットを作成し、Kerasに与えて期待する結果を得られるかやってみる。

KerasのMNISTで数エポック学習させ、テストデータに対する評価の結果がこれ↓
Test loss: 0.03404631294881692
Test accuracy: 0.988
↑これはサンプルコードのままのデータセットの場合。


次に自分で10,000枚のpng画像を1枚ずつロードしてテスト用のデータセットを作成した。
def loadTestData() :

    x =  np.array([])
#    y = [] #リストの場合
    y =  np.array([]) 
    
    for ite in range(10) :
        fileIte = 0
        while(1) :
            filePath = BaseFolder + "%d/%04d.png"%(ite,fileIte)
            if (os.path.exists(filePath)) :
                imgarr = makeArrayFromOneImage(filePath)

                x = np.append(x , imgarr)
#                y.append(ite)#リストの場合
                y = np.append(y , ite)
                
                fileIte += 1
            else :
                break

    return x, y


def makeArrayFromOneImage(filePath) :
    pngImage = Image.open(filePath)
    size = pngImage.size
    imgarr = np.array([])
    
    for y in range(size[0]) :
        for x in range(size[1]) :
            r = pngImage.getpixel((x,y))
            imgarr = np.append(imgarr,np.array([r]))

    return imgarr
↑コードはこんな感じ。
loadTestData()で読み込んだ1枚の画像データをnumpyのarrayなりリストに入れていく。TensorFlowだとデータセットはnumpyでもリストでもよかったと思うが、ここでは画像データに関してはreshapeとかしているのでリストじゃダメ。
makeArrayFromOneImage()で1枚のpng画像から1ピクセルずつ輝度を拾ってnp.arrayに入れていく。

Test loss: 0.03404631299573957
Test accuracy: 0.988
↑その結果。当然NNの学習度合いは同じ(係数は全く同じ)なので、同じ結果になるはずなんだが、、、精度が何かしら違うのか途中から違ったりする。まあいいか。
なお、正解データにリスト、np.arrayのどちらを使っても結果は同じだった。

とりあえず、png画像をロードしてデータセットの作成ができたのは確認できた。




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