バナー

会社によると思うのですが、トゥーウェイズでは年度末の3月に納期が重なることが多く、1〜3月がとっても忙しくなります。
4月も新年度の更新やその後の対応などでちょっとバタバタして、5月くらいになるとふと暇になります。
このスキに何か新しいことせねば。

そうだ、アプリ、作ろう。

iOSのアプリ制作で使われているObjective-Cという言語は以前マカセルさんという会社のセミナーに通って勉強したことがあったのですが、その後アプリはいくつかリリースしたものの、iOS向けとAndroid向けをワンソースで制作できるFlashやTitaniumで制作していました。
去年新しくSwiftという言語が発表されて興味は持っていましたが、Swiftで開発をするならAndroid向けにJavaでの開発も漏れなく付いてくるわけで、なかなか具体的に取り組もうとしてませんでした。

ただ、今回つくりたかったアプリをFlashで作ったところ………お、重い。
MarilenaというOpenCVをFlashに移植したライブラリを使って顔認識をしてみたのですが、iPadで実行させたところ認識まで2〜3分。
すっかり忘れた頃に認識されるという重さ。
これじゃだめだなぁ……。
OpenCVExtension.aneというANEも見つけたのですが、これ、Mac用のみなのかな?
うごかなーい。といって、ANEを1から作るのはハードルが高すぎる……。
OpenCVでの顔認識をいろいろ調べてたら、なんだ顔認識、iOSでもAndroidでも標準機能?であるのね。
じゃぁ、ネイティブで作っちゃおう。(ネイティブって言葉の使い方ビミョー?)

5月19日にクライアントさんのところに更新レクチャーに行った帰りにSwiftとAndroid用のJavaの本を1冊ずつ購入。
iOSはアプリの審査で時間をとるので、先にこちらから手をつけます。

Swiftの書籍、やっぱりまだ多くないなぁという印象。
そんな中から選んだのがこちら


9章のスタンプアプリが、つくりたいものと似ていたからです。
(この本すごくよかったです。自分にすごく合っていたと思います。)

私の言語スキル?としては、ActionScriptが一番得意で、JavaScriptとPHPとあとかじる程度にVBAとかPerlとかくらいです。(LINGOとFortranは前世のことのように綺麗さっぱり忘れました!)


まず、OSを嫌々ながらYosemiteにアップしました。
インストールしたあと立ち上がらずに真っ黒になるという事態になりながらなんとかクリア。

Xcodeをインストールします。
Xcodeってすごーく場所をとるので、使ってないモニタをよっこらしょと運んできて、デュアルディスプレイにしました。

ここで大きな落とし穴。書籍は6.2、最新は6.3。Swiftが1.2となり、ちょいちょい仕様が変わってましたorz
去年発表された場合の新しい言語ですからね。まだカッチリしてないのよね。
書籍そのまま写経したらエラー出ます。5月に購入した、5月初版の書籍ですよ……?

書籍を1章から書かれている通りに作業していきます。
2章で簡単な動きのあるアプリ?をつくり、流れをつかみます。
3章でメモを取りながら文法を勉強します。
4〜8章は布団の中で読んで、
9章をひたすら手順通りに作業しました。

触ってみての感想は、ActionScriptと似てるなぁ〜!
関数とかは全然見たこともない長ったらしいのがわんさかあるのですが、クラスを継承してカスタムクラス作ってコンストラクタがあって〜というのが馴染み深くて。
そんなことからエイヤッ!と4〜8章をとばしちゃいました。

9章は写真にスタンプ(移動できる)をつける勉強だったのですが、アレンジして最前面のスタンプに枠をつけるのとスタンプを拡大縮小できるように。
次に顔認識。webで検索してまずは顔認識してスタンプを配置するアプリ制作。
その次に画面遷移だけのアプリ制作。
これらを組み合わせて一つのアプリにして、AutoLayoutで画面サイズの変化に対応して、iAdをつけて、SNS投稿機能をつけて、スタンプ選択の設定画面つけて、写真にすかしつけて、スタンプランダム機能つけて、設定保存つけて、多言語切り替えつけてアプリ内課金をつけました。

アプリ内課金はSwiftでの記述がwebでは本当に少なかったので、このためだけにもう一冊書籍購入



最後まで苦しんだのが画像のサイズや座標位置の計算。
写真を画面サイズに縮小して表示しても、顔検出の位置は顔認識に通してる画像のサイズなので、そのスケールの計算とか、顔認識はなぜかY座標が下になるのでその計算とか、スタンプサイズの計算とか、保存やSNSにアップするときの画像のサイズ計算とか。
スタンプの位置がずれて顔見えてるやん!ってのもしょっちゅう。

こんな感じで縮小後のサイズ取得して
scaleimage = AVMakeRectWithAspectRatioInsideRect(timage!.size, MainImageView.bounds)
こんな感じでスケール取得して
sizescale = min(scaleimage.size.width / timage!.size.width , scaleimage.size.height / timage!.size.height)
こんな感じでスタンプ位置取得。
faceRect.origin.x = scaleimage.origin.x + (faceRect.origin.x - stampW / 2 + faceRect.size.width / 2) * sizescale
faceRect.origin.y = scaleimage.origin.y + (timage!.size.height - faceRect.origin.y - stampH) * sizescale

中でも一番苦しんだのが、カメラロールから取得した画像は大丈夫なのですが、アプリ内で撮影したものを使おうとすると、内部的に写真がくるりんと90度回転してしまうという現象。
ただ、表示上はちゃんと縦になってたので、「顔が認識できないよーー!(>_<)」と苦しみました。
(UIImageからCIImageにするときに回転しちゃう。カメラで撮影して変数に入れるときに、drawInRectで一旦書いちゃうことで回避)
こんなおまじない。

UIGraphicsBeginImageContextWithOptions(image.size, true, 0)
image.drawInRect(CGRectMake(0, 0, image.size.width, image.size.height))
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

そんなこんなでなんとかアプリ完成。

アプリ名はUsacooSnap(うさくーSnap)といいます。
写真を撮ったときに、友達が映っててSNSにアップするために顔を隠したりするじゃないですか。
あれを顔認識で自動的にやってくれるものです。
自動的に写真から顔を検出して、うさくーキャラクター(https://usacoo.net/characters/)のお面をかぶせます。
もちろん外すことも可能なので、自分の顔だけ外すこともできます。
無料アプリですが、120円のアップグレードすることでお面の数を3→11にできます。

よかったら試してみてくださいね。

うさくーSnapはこちら。

ついで言うとアプリ内課金でミスをしていて、課金後落ちるということで一回リジェクトされました。ないもの参照してました……。修正したら難なくクリア。

程よい規模のアプリで完遂でき、よいお勉強になりました。

さて。

次は同じアプリのAndroid版です。
がんばりまーす。

★追伸!
リリースしたものを使っていただいたところ、青い枠が消えないよーという声が。
リジェクト時についでに触ったもののせいで、顔が2つ以下の場合に枠が消えなくなっていました。
修正版をすでに申請してますので、しばしお待ちください。
それまでは大人数写真でお試しくださいませ。

ブログランキング このエントリーをはてなブックマークに追加

カテゴリ:iPhone/iPadアプリ