頭と尻尾はくれてやる!

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


CreateMLで2種類の画像を見分けられなかった話

ポケモンGOでエクセレントスローの瞬間って気持ちいいよね?



↑こういうの。カーブスローでエクセレントって気持ちいい!
なので、その部分ばかりを集めた動画を作成しようと数ヶ月かけてたくさんの動画を溜めてる。
そろそろ編集しようと思ったんだけど、結構大量にあるので大変。

そこで、こういう動画の中でExcellent!と表示された瞬間を含む数秒を探し切り取る、というのを自動化しようと思った。

CreateMLを使い、動画内の画像にExcellent!と表示されてるか否かを判断するするよう学習させたい。

そのためにはまず学習用の画像が必要、ということでサイズが300x300の画像をそれぞれ651枚ずつの計1,302枚を用意した(※1)。

Excellentがない場合のサンプル画像

↑一つはExcellent!という文字がない画像。

Excellentがない場合のサンプル画像概要
↑動画内にはいろんな場面が含まれる。

Excellentがある場合のサンプル画像

↑もう一つはExcellent!という文字を明らかに(人間の目で見て)含む画像。

Excellentがある場合のサンプル画像概要
↑先ほどのほどいろいろあるわけではないが、時間帯やタイミングなどでいろんな画像になる。

この二つを判別させたいわけだ。


Create MLで学習させmlmodelファイルを得る
↑これと同様にして学習させる。今回の場合はCrop, Expose, Noiseにチェックを入れた↓

CreateMLでの初期設定スクショ

学習開始から2時間28分で学習完了。

CreateMLでの学習結果

↑その結果がこれ。

Training 72%
Validation 68%
別途用意したテストデータ(40枚)に対して55%て、、、
全然ダメじゃないか、、、😩


データ数不足?いや、動物を見分けるのにもっと少ないサンプルでできてる例(※2)がある。
CropやExposeを有効にしてるからもっと学習したらよくなるんじゃないの?などと考えたりしていたのだが、、、

Create MLでMNISTの分類器を作ってみた - Galapagos Blog
↑こちらを読んでると、今回の課題自体がCreateMLに向いていないのか?という気がする。CreateMLは転移学習らしいので、形状を見分けるような課題に対してはいい結果がでるが、今回のような文字の有無を見分けるという課題にはそぐわないのかもしれない。



※1 機械学習用の画像作成のために、動画のある場所からある場所までで画像を作成するmacOSアプリを自作した。

機械学習用画像の作成ツールスクショ

↑こんな感じで1がExcellent!が出ているところで、0は出ていないところ(画像は撮影用なのでずれてるけど)。動画の全体の中でExcellent!が表示されている時間は短いので、0に相当する部分は間引いて両方の枚数が同じになるようにしている。


※2 参考サイト
Create MLで簡単に機械学習を体験する - Qiita
CreateMLを使ってさらっと画像認識させてみた - Qiita




スポンサーサイト






休暇村讃岐五色台のキャンプ場へ行ってきた

11月の三連休にキャンプに行って来た。

キャンプ場 | 休暇村讃岐五色台【公式】
↑行ったのは香川県の五色台というところにある休暇村のキャンプ場。


【キャンプ場についてのメモ】

11月下旬なので閑散としているのだろうと思ったら7割くらいは埋まってた気がする。
キャンプ場からは木があるためいい景色は全く見えなかった。

今回は電気・水道が付いたオートキャンプ場を選択。
お隣との間には木があったので広く感じた。

タイルを敷いてるテントサイト

↑珍しいことに地面の一部にタイルっぽいのが敷いてあるところがあった。焚き火とかはここで、ということだと思う。

ゴミを捨てるところあり。要分別。灰を捨てるところもあった。
トイレは和式。季節的に虫はいなかった。

休暇村の本館までは1kmほどと聞いたが歩いていくのは大変そう。お風呂に入りには車で行った。

休暇村讃岐五色台からの眺め

↑本館へ行くとこのようないい眺め。

休暇村のウエルカムうどん出汁の看板

↑本館にウエルカムうどん出汁、というのがあったので飲んだらすごくおいしかった。




【私的メモ】

今回は寒さ対策でテントに敷くための大きい段ボール、および断熱シート(厚さ3ミリ程度だが)を持参。これらを通常のマットの下に敷いた。そのおかげか地面からの冷えは感じなかった。
さらにごつい服を着てたのでシュラフの中では寝返りを打ちにくく、ぐっすりとは眠れなかった。冬用のシュラフが必要なんだろうな。

夕食の味噌鍋

↑夕食はコチュジャン入りの味噌鍋。麺には現地調達した讃岐うどんを入れたけど、さすがにコシなんてなかった。寒いところだったので食べやすさを優先したメニューにして正解だった。

コールマンのホットサンドメーカーで作ったホットサンド

↑今回の初アイテム、ホットサンドメーカーで作ったホットサンド(朝食)。
焚き火の火で大丈夫かな?と思ったがススっぽくなることもなくおいしくできた。
食料を調達した香川県のマルナカには8枚切りの食パンがなく6枚切りので作ったがなんとかなった。


テント設営し、ある程度夕飯の準備をしておいてお風呂に入りに本館へ行ったところで、結婚指輪がなくなっていることに気付いた。キャンプサイトで準備中になくしたのか?頑張って探したが見つからず。しばらく警察の拾得物検索サイトをチェックすることになりそう。


Objective-CでCGAffineTransformからSCNMatrix4へ変換する

Creating Face-Based AR Experiences | Apple Developer Documentation
↑APPLE公式のサンプルコード Creating Face-Based AR Experiences (プロジェクト名はARKitFaceExample)でTrueDepth Cameraを使うコードの勉強のためSwiftで書かれているコードをObjective-Cに書き直しつつ”写経”している。
{
        let affineTransform = frame.displayTransform(for: .portrait, viewportSize: sceneView.bounds.size)//—(1)
        let transform = SCNMatrix4(affineTransform)//—(2)
        faceGeometry.setValue(SCNMatrix4Invert(transform), forKey: "displayTransform”)//—(3)
}
↑そこにこのような、SCNMatrix4のtransformをシェーダ(shader modifierと言うべき?)に渡すような記述がVideoTexturedFace(顔が大きくなるやつ)にある。
(1)でCGAffineTransformのaffineTransformを得ている。このCGAffineTransformは2D画像を変換するもの。
(2)でそれをSCNMatrix4へ変換している。
(3)さらにその逆行列をシェーダに渡す。

困ったことにObjective-Cでは(2)のように簡単にCGAffineTransformからSCNMatrix4へ変換することができない。
ということでなんとかしたいのだが、、、

【解決策その1】
{
    CGAffineTransform affineTransform = [frame displayTransformForOrientation:UIInterfaceOrientationPortrait viewportSize:size];//—(4)
    CATransform3D caTransform = CATransform3DMakeAffineTransform(affineTransform);//—(5)

    SCNMatrix4 transform;
    transform.m11 = caTransform.m11;
    transform.m12 = caTransform.m12;
    transform.m13 = caTransform.m13;
    transform.m14 = caTransform.m14;
    transform.m21 = caTransform.m21;
    transform.m22 = caTransform.m22;
    transform.m23 = caTransform.m23;
    transform.m24 = caTransform.m24;
    transform.m31 = caTransform.m31;
    transform.m32 = caTransform.m32;
    transform.m33 = caTransform.m33;
    transform.m34 = caTransform.m34;
    transform.m41 = caTransform.m41;
    transform.m42 = caTransform.m42;
    transform.m43 = caTransform.m43;
    transform.m44 = caTransform.m44;

    transform = SCNMatrix4Invert(transform);
}
↑(4)でCGAffineTransformを得ている。
(5)で2DのCGAffineTransformを3DのCATransform3Dに変換(※)。
これをSCNMatrix4にしたいわけだが、、、後は単に入れるだけのべたな方法だ。


【解決策その2】
{
    CATransform3D caTransform = CATransform3DMakeAffineTransform(affineTransform);

    NSValue *value = [NSValue valueWithCATransform3D:caTransform];
    SCNMatrix4 transform = [value  SCNMatrix4Value];
}
↑CATransform3Dに変換するのまでは先ほどと同じ。
それをNSValue経由で変換してやる。すっきりした。


以上のようにすれば、CGAffineTransformからSCNMatrix4へ変換することはできる。


【おまけ】
{
    CATransform3D caTransform = CATransform3DMakeAffineTransform(affineTransform);//—(6)
    NSValue *value = [NSValue valueWithCATransform3D:CATransform3DInvert(caTransform)];//—(7)
    [faceGeometry setValue:value forKey:@"displayTransform”];//—(8)
}
↑でもシェーダに渡すのにNSValueオブジェクトで渡せるのでSCNMatrix4を使わなくていいことに気付いた。
(6)CATransform3Dに変換するのまでは先ほどと同じ。
(7)で(逆行列にした)CATransform3DをNSValueにして
(8)でシェーダに渡す。
これが一番すっきりする。


※参考サイト
how to convert the CGAffineTransform to CGTransform3D? - Stack Overflow





Objective-CのプロジェクトからSwiftを使おうとしたらFile Not Found

Objective-CのプロジェクトからSwiftを使う場合には、
#import "プロジェクト名-Swift.h"
を記述すべし、と多くの解説ページには書かれているのだが、なぜかこれがうまくいかない。

File Not Foundエラー

↑File Not Foundのエラーでビルドさえできない状態になる。


いろいろと調べた結果、、、
この原因はプロジェクトの名前が”181106ImageTest”となっており数字で始まっていたため。
プロジェクト名を数字で始めるのは具合が悪い場合があるのか、Product Bundle Identifierなどでは最初の数字が”-“(ハイフン)で置き換えられていたりする。

参考サイト(※)には
「#import "ProductModuleName-Swift.h"」を記述する
とあるので、XcodeのBuild SettingsでProduct Module Nameを調べると、、、

XcodeのBuild Settingのスクショ

↑”_81106ImageTest”となっている。ここはハイフンではなくアンダーバーなのか🤔

ということで
#import "_81106ImageTest-Swift.h"
とすれば File Not Foundエラーは消えた。

管理しやすいからという理由で冒頭に日付を持つプロジェクト名を付けているんだけど、この方法はお勧めしません。



※参考サイト
Objective-CコードからSwiftのクラス/プロトコルを使う方法(フレームワーク開発編) - Qiita




Xcode 10.1
macOS Mojave 10.14.1
Swift 4.2.1

Swiftのバージョン確認方法はターミナルから swift -version でOK。
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.2.0


iPhone 7 Plusのバッテリー交換を配送でAppleに依頼した

iPhone 7 PlusからXS Maxに機種変更したので、7 Plusのバッテリー交換をAppleのサポートに依頼した。年内だと安いと聞いていたし。
使用途中ということではないし、店舗は予約が取れそうにもないので配送して修理を依頼することにした。

申し込んでから宅配業者が引き取りに来るまでにSIMを抜いておく、初期化するなど準備しておくことがある。iPhone 7 Plusを自分が使う事はもうないので工場出荷状態へ戻しておいた。

iPhoneの梱包の様子

↑二重にプチプチ封筒にデバイスを入れ、XS Maxを入れてた箱に同じように梱包しておいた。

iPhoneを梱包した箱

↑これをやってきた宅配業者(クロネコ)に手渡した。

ところがその日の夕方、クロネコの営業所から電話があって、「梱包してくれているんですけど、Apple様指定の箱がありまして」みたいな内容だった。
それならそこまで厳重に梱包しなくてよかったやん!でもそんなことAppleのサイト見ても書いてないよな、、、?


修理状況のスクショ(梱包箱をお届け中)

↑修理状況をサイトで確認できるようになっているのだが、申し込んでから数日はずーっと「梱包箱発行完了」という状態だったので、ちゃんと届いているのだろうか?と心配してたのだが、、、、

クロネコが引き取りに来てから5日後にメールで修理開始のお知らせが来た。

修理状況のスクショ(修理完了)

↑その翌日には、修理が終わって発送準備中になっていた。
さらにその翌日には発送完了メールが来た。そこにはクロネコの配送状況がわかるページへのリンクがあったのだが、そのページが有効になる前に修理終了したiPhoneが届いた。

修理後のiPhone 7 Plus

↑突然帰って来たiPhone 7 Plus。
無事届いたからいいんだけど、行きも帰りもAppleとクロネコ間のデータの連携が微妙だったな。


ということでバッテリー交換は、集荷から7日後に到着したのでした。早いなあ。




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