Hatena::ブログ(Diary)

Over&Out その後 このページをアンテナに追加 RSSフィード

2017-09-20

ARKitのサンプルコード集「ARKit-Sampler」を公開しました

iOS 11のリリースと同時に、ARKitのサンプル集「ARKit-Sampler」をオープンソースで公開しました。


ARKit Sampler


f:id:shu223:20170920095943p:image:w300


ソースコードは GitHub に置いてあるので、ご自由にご活用ください。


https://github.com/shu223/ARKit-Sampler


使用言語はSwift 4.0です。


ARKitのサンプルは公式のを含めいろいろ出てますが、ARKit-Samplerでは「余計な実装を混ぜずに、できるだけシンプルな実装で伝える」というところに気をつけています。もともとは書籍執筆のために用意したものなので、とくに序盤のサンプルはシンプルで意図が汲みやすいと思います。


ビルド方法

  1. ここから Inceptionv3.mlmodel をダウンロードして mlmodels フォルダ配下に置く
  2. Xcode 9 でビルドしてiOS 11端末にインストール

基本的にビルドするだけですが、Core MLのモデルファイルをダウンロードする必要があります。



サンプル一覧

今のところ8個のサンプルが入っています。少ないですが、随時追加していきます。


3-lines AR

実質3行」のシンプルなAR。ARKitが簡単に扱えるということがわかります。


f:id:shu223:20170913155719j:image:w200


Plane Detection

ARKitの基本機能、水平面の検出方法を示したシンプルなサンプル。


f:id:shu223:20170913173302j:image:w200


Virtual Object

水平面に仮想オブジェクトを設置するサンプル。


f:id:shu223:20170913170249j:image:w200


AR Interaction

仮想オブジェクトや、検出した水平面に対するインタラクションの実装方法を示したサンプル。


f:id:shu223:20170920155917g:image


AR Measure

もはやARKitの定番実装例となっている、ARKitをメジャー(巻尺)代わりに使うサンプル。


f:id:shu223:20170913224145j:image:w200


AR Drawing

空中に絵や文字を書くサンプル。


f:id:shu223:20170825154724j:image:w200


Core ML + ARKit",

Core ML + Visionで認識したオブジェクトに対してARKitで「ARタグ付け」するサンプル。


f:id:shu223:20170909170336j:image:w200



Metal + ARKit

ARKitの描画にMetalを利用するサンプル。


f:id:shu223:20170904173246j:image:w200


Coming soon...
  • Audio + ARKit
  • Core Location / MapKit + ARKit
  • Face Tracking
  • etc...

Special Thanks

アイコンデザインはいつものおかず氏です。


書籍「iOS 11 Programming」

ARKitとMetalの章の執筆を担当しています。


ARKitの章は本日アーリーアクセス公開予定です。



iOS-11-Samplerは?

毎年iOSのニューバージョンと同時に公開していたiOS Samplerシリーズですが・・・今年はまだありません・・・つくるつもりはあります・・・!


2017-03-19

【書評】iPhoneアプリ開発講座 はじめてのSwift

現在の最新開発環境である Xcode 8、Swift 3 対応のiOSアプリ開発入門書iPhoneアプリ開発講座 はじめてのSwift』を、著者の諏訪様・出版社のSBクリエイティブ様よりご恵贈いただきました。


f:id:shu223:20170320135355j:image:w400



昨年12月に発売されたばかりで、Amazonで購入できます。Kindle版もあります。


iPhoneアプリ開発講座 はじめてのSwift
諏訪 悠紀
SBクリエイティブ
売り上げランキング: 45,845


他の入門書との違い

iOSアプリ開発の入門書は数多出ているわけですが、本書の特長としては、表紙にも、[著者の諏訪様による紹介記事](http://dev.classmethod.jp/smartphone/iphone/wrote-swift-book/)にも

何がわからないか? に対して真摯に向き合い、熟考し、執筆しました。

とある通り、解説がめちゃくちゃ丁寧です。


たとえば、iPhoneアプリ開発を行うためには、プログラミング言語であるSwiftを学ぶ必要があるわけですが、その前段階として、

  • 「プログラムとは」
  • 「プログラミング言語とは」
  • 「コンピュータがプログラムを理解する仕組み」
  • 「iPhoneアプリ開発のためのプログラミング言語『Swift』」

と、Swiftを学ぶ理由に至るまでを順を追って、実に丁寧に説明してくれます。



そしてなんとも図表/イラストが豊富


f:id:shu223:20170320142011j:image:w600

(この丁寧さ、「読者を絶対に突き放さないぞ!」という著者様の意志を感じます)


オールカラーで、ほぼ全ページに図が入っています。



あと素晴らしいと思ったのがこういうところ。


f:id:shu223:20170320143135j:image:w600


ソースコードについての解説、普通の技術書では、インラインのコメントで済ませちゃうと思うんですよ。こういう感じで。

// Carクラスをインスタンス化し、プロパティに値を代入する
let car = Car()
car.mileage = 200
car.usedFuel = 10

// FuelEfficiencyプロトコルに準拠したインスタンスとして扱う
・・・(ソースコード省略)

それを上の写真にあるような感じで全編でソースコードの要点を図っぽく示しているところ、これは実に手間暇かかってるなーと。



そして、筆者の諏訪さんは超有名なクラスメソッド社の技術ブログで非常に多くの投稿(累計406投稿!)をされている方なので、文章が非常に読みやすいです。


Amazonのレビューにもこう書かれていました。

外国人の私でもす一回でわかるぐらいのやさしい日本語で書いています。とてもわかりやすいです、プログラミング経験ゼロの方にオススメです。


目次

  • CHAPTER01 プログラミングの基礎知識
  • CHAPTER02 プログラミングを始めるための準備
  • CHAPTER03 Swiftの基本的な文法
  • CHAPTER04 Swiftとオブジェクト指向プログラミング
  • CHAPTER05 Swiftの発展的な文法
  • CHAPTER06 iOSアプリ開発入門
  • CHAPTER07 iOSアプリ開発レシピ
    • Recipe01 電卓アプリ
    • Recipe02 タイマーアプリ
    • Recipe03 マップアプリ
    • Recipe04 図鑑アプリ
    • Recipe05 写真ビューアアプリ

それぞれの詳細については、著者様ご自身による解説記事に詳しいです。


まとめ

最新の Xcode 8 / Swift 3 対応のiOSアプリ開発入門書「iPhoneアプリ開発講座 はじめてのSwift」を紹介させていただきました。気になる方はぜひAmazonの「なか見!検索」で試し読みしてみたり書店でチェックしたりしてみてください!


iPhoneアプリ開発講座 はじめてのSwift
諏訪 悠紀
SBクリエイティブ
売り上げランキング: 45,845


2016-09-14

iOS 10の新機能のサンプルコード集「iOS-10-Sampler」を公開しました

iOS 10でも大量のAPIが追加されました。が、新しいAPIはどう使うのか、実際に何がどこまでできるのか、といった具体的なところが、英語のドキュメントやWWDCのセッション動画をながめているだけだと正直あまりピンときません。やはり実際にコードを書いて動かしてみるのが一番わかりやすい・・・ということで今年もつくりました!


iOS-10-Sampler


f:id:shu223:20160914063446j:image:w600


恒例の新機能のサンプルコード寄せ集めアプリです。ソースコードは GitHub に置いてあるので、ご自由にご活用いただけると幸いです。


使い方は Xcode 8 でビルドするだけ なので、デザイナーさんやディレクターさんもぜひお近くのエンジニアにビルドしてもらってください。


f:id:shu223:20160914072119j:image:w600


iOSももうかなり成熟してしまい、話題になる革新的な新機能とか、どの開発者にとっても嬉しい新機能というのはなかなかないわけですが、実装してみると思ったより簡単なので自分のアプリにも取り入れたくなったとか、他の誰も話題にしてないけど自分的には熱いみたいな機能もあったので、ぜひ一度お試しいただけると嬉しいです。


また、Samplerシリーズでは「余計な実装を混ぜずに、新機能のメリットをできるだけシンプルな実装で伝える」というところに気をつけています *1。コピペもしやすいと思うので、自分のアプリに取り入れて動かしてみるとより楽しいかもしれません。


今のところ18個のサンプルが入っています。随時追加していきます。機能追加プルリク大歓迎です!


以下各サンプルの紹介です。


Speech Recognition

新たに追加された Speech Framework を利用した音声認識のサンプルです。


f:id:shu223:20160914070235j:image:w405


Appleのサンプルをベースに、全58種類の対応言語を選択する機能を追加しています。


Looper

AVFoundationに新規追加されたクラス AVPlayerLooper を用いた動画のループ再生のサンプルです。


f:id:shu223:20160914070311g:image:left f:id:shu223:20160914070308g:image



このクラス自体はプレイヤー機能は持っておらず、AVQueuePlayer と AVPlayerItem のインスタンス、そしてループする範囲を示す CMTimeRange オブジェクトを渡して使用します。

public init(player: AVQueuePlayer, templateItem itemToLoop: AVPlayerItem, timeRange loopRange: CMTimeRange)

Live Photo Capturing

写真撮影用に追加された新クラス AVCapturePhotoOutput を使用したライブフォト撮影サンプルです。*2


f:id:shu223:20160914070434j:image:w200


Live Photo のビューワーは iOS 9.1 から使えましたが、今回から撮影もできるようになりました。


Audio Fade-in/out

すごーく地味だし、このAPIがなくてもできたといえばできたことなんですが、実際に使う人は多いかもしれません。AVAudioPlayerにフォードイン/アウトするためのメソッドが追加されました。

// Fade In
player.setVolume(1, fadeDuration: 3)

// Fade Out
player.setVolume(0, fadeDuration: 3)

これタイマーとかでやってた人は嬉しいんじゃないでしょうか。


Metal CNN Basic: Digit Detection

Metal Performance Shaders フレームワークに追加されたCNN (Convolutional Neural Network / 畳み込みニューラルネットワーク)を用いた手書き数字認識のサンプルです。*3


f:id:shu223:20160914070517g:image


この「Metal AcceleratedなCNN計算処理」は個人的には今回一番熱い新機能です。



Metal CNN Advanced: Image Recognition

上のサンプルに引き続き、Metal Performance ShadersのCNNを利用したリアルタイム一般物体認識のサンプルです。*4


f:id:shu223:20160914070509g:image


速くて見づらいかもしれませんが、ノートパソコン(notebook)→ リモコン(remote control) → iPhone(iPod)と認識しています。


Metal ShaderというぐらいなのでGPUで処理されます。6s利用ですが、処理速度も申し分なしでした。(ちなみにMetalはAppleのハードウェアに最適化されたグラフィックスAPIで、「OpenGLより最大10倍速い」と言われています)


ちなみにミスリードもあるかもしれないので念のためですが、「一般物体認識」という新機能があるわけではないです。本サンプルで使用しているモデルはImageNetデータセットを用いてInception v3ネットワークをTensorFlowで学習させたもので、新機能はあくまで「Metal(GPU)でCNN処理」という部分になります。


PropertyAnimator: Position

アニメーション用の新クラス、UIViewPropertyAnimatorを用いて UIView オブジェクトの位置と、背景色をアニメーションさせるサンプルです。


f:id:shu223:20160914070727g:image


画面上をタッチしたままグリグリと動かしてみてください。touchMovedが呼ばれるたびにアニメーションが追加するという単純な処理をやっているのですが、いい感じに追随してくれるのが今回のクラスがアニメーションの追加をいい感じにやってくれてる *5 おかげなのかなと。


PropertyAnimator: Blur

UIViewPropertyAnimator の `fractionComplete` を用いて UIVisualEffectView / UIBlurEffect のブラーをアニメーションさせるサンプルです。


f:id:shu223:20160914070720g:image


やってることは超シンプルで、`effect` プロパティから UIBlurEffect を削除する処理を UIViewPropertyAnimator に登録しておいて、

animator = UIViewPropertyAnimator(duration: 0, curve: .linear) {
    self.effectView.effect = nil
}

スライダーの値に応じて `fractionComplete` を変化させています。*6

@IBAction func sliderChanged(sender: UISlider) {
    animator.fractionComplete = CGFloat(sender.value)
}

Preview Interaction

新クラス、UIPreviewInteraction で、3D Touchでピーク&ポップするサンプルです。


f:id:shu223:20160914070939g:image


Notification with Image

新しい通知のフレームワーク、UserNotifications framework を用いて、画像付きローカル通知を発行するサンプルです。


f:id:shu223:20160914033106j:image:w200:left f:id:shu223:20160914033113j:image:w200



Sticker Pack

iMessage のステッカーパックのサンプルです。


f:id:shu223:20160914032800j:image:w200


Messagesってメッセンジャーアプリとしてどれだけのシェアがあるの?という声も効きますが、ステッカーパックは画像をアセットカタログに入れていくだけの超超簡単実装なので、いい感じの画像を持っているアプリはやっといて損はないのかなと。


Core Data Stack

NSPersistentContainer を使うと Core Data の実装がシンプルになるよ、というサンプルです。


f:id:shu223:20160914034038j:image:w200


noliliさんよりpull requestいただきました!


TabBar Customization

UITabBarのバッジをカスタマイズするためのAPIが追加されました。*7


f:id:shu223:20160914034330j:image:w200


センスがなく、全然いい感じにカスタマイズできてないのが心残りですが。。


New filters

CIFilterで追加されたフィルタのサンプル。


f:id:shu223:20160914034350j:image:w200:left f:id:shu223:20160914034353j:image:w200



前回は豊作だったのですが、今回はちょっとしかありませんでした。。


New Fonts

新規追加されたフォントのサンプル。こちらも今回は少なく、4種だけ。*8


f:id:shu223:20160914034359j:image:w200


Proactive: Location Suggestions

NSUserActivityに新たに追加された `mapItem` プロパティを用いた "Location Suggestions" のサンプル。


f:id:shu223:20160914054654j:image:w200:left f:id:shu223:20160914071309j:image:w200



いわゆる「Proactive」というやつで、Appleから出てるサンプルがあるのですが、どの実装が何に効いているのか、というかこのサンプルをどう試すのか、というのがちょっとわからず(WWDCセッションをちゃんと見ればいいのかもしれませんが)、下記記事に助けられました。


Attributed Speech

AVSpeechUtterance に、NSAttributedStringを渡せるイニシャライザが新たに追加されたので、これを試すデモです。


NSAttributedString は文字列に色んな属性を指定できるわけですが、


これを音声合成の「Utterance」に渡せるということは、例えば、NSFontAttributeNameを用いてある範囲のフォントをboldにすると、その部分だけ強調されて発声されるとか、何か別の属性を使ってアクセントを制御できるとか、そういうことを期待したわけです。


が、結果は・・・何も起こりませんでした



同ツイートのメンションで岸川さんから `kCTLanguageAttributeName` で言語を切り替える、`kCTRubyAnnotationAttributeName` でルビをふる、といった文字列だけではなくて音声にも有用そうな属性を示唆いただきましたが、これらを試してみてもやはりあり/なしで違いは発声しませんでした。


何か私の実装が間違っているのかもしれませんし、プルリクをいただけるかもしれないので、サンプルとしては残してあります。


Haptic Feedback

iPhone 7のTapticEngineを利用するフィードバックのサンプルです。UI

ImpactFeedbackGenerator、UINotificationFeedbackGenerator、UISelectionFeedbackGeneratorの全てのパターンを試せます。


f:id:shu223:20170103172859j:image:w200


所感

箇条書きで。。

  • Notificationのカスタマイズ、ロック画面でプレビューは嬉しい
  • 標準で、ローカルで音声認識ができるようになったのも嬉しい
  • MPSCNNは熱いのでここはもっと勉強したい
  • iMessage app / Sticker Pack は当初まったく期待してなかったけど自分でやってみるとその簡単さとやっておいて損はない(親アプリがiOS 9でもok)という点で意外と熱い
  • UIViewPropertyAnimator、あまりワクワクするような新しさのあるものではなかったが、従来のものよりは便利なのでiOS 10以上のアプリでは普段使いすると思う
  • 3D TouchでPeek&Popは3D Touchデバイスが普及するまでは静観
  • Proactiveは今は静観
  • SiriKitは良いサンプルが思いつかず今回は入れなかった

デュアルカメラとか、Taptic Engine APIとか新デバイス系はまた後ほど。


おわりに

最初は個人的な勉強として始めたものがすっかり恒例になって、もうかれこれ4年もこれをやっています。


f:id:shu223:20160914061757j:image:w320


これがまぁなかなか大変で、それなりに時間がかかるので、周りの人には毎年「今年はやらないかも」とか毎年言ってて、なんだかんだやっぱり今年もつくってしまったという。







まぁ自分はやっぱり「新しいAPIが追加されると開発者としてできることが増える」のが好きなのと、(冒頭に毎年書いていることですが)自分で手を動かさないと全然理解できないというのがあるので、これはやっぱり続けた方がいいなと。


そんなわけで Apple Watch Series 2 が届いたら「watchOS-3-Sampler」もつくりたいと思います!


*1:Appleによる公式サンプルではアプリとしての体裁を整えるために新機能とは直接は関係ない実装がたくさん入っていたりしてややこしくなっているケースが多々ある

*2:Appleの「AVCam」サンプルをベースに、Live Photo撮影の実装だけを抜き出し、シンプルにしたもの

*3:本サンプルは、Appleの「MPSCNNHelloWorld」サンプルをベースに、不要な実装を除去しシンプルにしたもの

*4:本サンプルのモデルデータと、ネットワークの実装は、Appleの「MetalImageRecognition」サンプルをベースにしています

*5:WWDC16のセッション216でそんな感じのことを言ってました

*6:この手法は、こちらのコードで知りました: https://github.com/manuelCarlos/IOS10-Animate

*7:これらの追加APIについては、こちらの記事で知りました: no title

*8:しかもFutura、AmericanTypewriterは従来からあるfamilyの太さ違い

2016-08-16

イスラエルとパレスチナでiOSとBLEについて講演してきた話

7月24日〜30日、「中東のシリコンバレー」と呼ばれスタートアップがめちゃめちゃ盛り上がっているイスラエルのテルアビブ、IT産業が伸びているというパレスチナのラマッラ、そしてあの聖地エルサレムにて、iOS×BLEについて話してきました。


f:id:shu223:20160816085014j:image:w300

(在イスラエル日本大使館作成のチラシ)


なにそれどういうこと?と思われた方もいらっしゃるかもしれませんが、これ、外務省の「日本ブランド発信事業」という事業の一環なのです。


こういうこともなかなかないだろうという貴重な経験をさせていただいたので、ブログに書いておこうと思います。


経緯

正式に決まったのは出発のちょうど1ヶ月前ですが、きっかけは半年以上前、昨年12月に開催された DemoDay.Tokyo #0 にまでさかのぼります。そこで「勉強しつつソースコードをオープンにしてたら海外からも仕事が来るようになった」という話をしたのですが、そこに外務省の方が来られていて、「こういうのあるんだけど興味ある?」「あります!」的なやり取りをさせていただいたのでした。


「iOSという米国産プラットフォーム上で活動してるだけの自分が日本ブランド発信なんて場違いだろう」という気持ちもありつつダメ元で応募書類を提出したところ、WHILLとかMoffとかBONXとか、日本発の魅力的なプロダクトに横断的に関わっているというところを評価されて見事採択されたのでした。


スケジュール

こんな感じのスケジュールでした。

  • 7/24 東京発
  • 7/25 テルアビブ着、エルサレムへ移動しアズリエリ工科大学にて講演
  • 7/26 テルアビブのGoogle Campusにて講演
  • 7/27 テルアビブのSigma Labsにて講演
  • 7/28 パレスチナのビルゼイト大学にて講演
  • 7/29 テルアビブ発
  • 7/30 東京着

毎日講演が入っていて、移動もあり、会食もあり、それ以外の時間は現地のスタートアップと会ったり資料の手直しをしたりしてたので、自分でどこかに観光に行くような余裕はありませんでした(後述しますが道中で名所に寄ってくれたりはしました)


位置関係

テルアビブとかエルサレムとか言っても多くの日本人にとってはなかなか位置関係をイメージしづらいんじゃないかと思うので、地図を載せておきます。


f:id:shu223:20160816084908p:image:w280


テルアビブ〜エルサレムまで車で片道1時間〜1時間半(渋滞状況による)ぐらいです。


歴史的背景とかは素人が下手に説明できない複雑さがあるのでぜひググッてみてください。。


各講演の様子

それぞれの規模はそんなに大きくはなくて、20〜40名ぐらい。しっかり細かい質問や意見を拾うことができてちょうど良い人数だったと思います。4講演とも基本的には同じテーマで話をした *1 のですが、それなりに場所も離れているので、参加者のかぶりはなかったようです。


初日:アズリエリ工科大学 / エルサレム

f:id:shu223:20160816085715j:image:w600


f:id:shu223:20160816085714j:image:w600


2日目: Google Campus / テルアビブ

f:id:shu223:20160816085753j:image:w600


f:id:shu223:20160816085750j:image:w600


3日目: Sigma Labs / テルアビブ

f:id:shu223:20160816085826j:image:w600


4日目: ビルゼイト大学 / パレスチナ

f:id:shu223:20160816090120j:image:w600


f:id:shu223:20160816090218j:image:w600



各講演やその他の活動についての報告はレポートに書いて既に外務省に提出したので、いずれサイトにて公開されるかと思います。


道中の観光

初日のエルサレムの会場への移動中に、大使館の方のはからいで旧市街に寄っていただきました。

旧市街はユダヤ教・イスラム教・キリスト教の聖地であり、嘆きの壁や聖墳墓教会、岩のドームといった各宗教縁の施設を訪れる人々が絶えない。旧市街は城壁に囲まれ、東西南北に宗派ごとで四分割されている。北東はムスリム地区、北西はキリスト教徒地区、南西はアルメニア正教徒地区、南東はユダヤ人地区となっている。現在の城壁はオスマン・トルコのスレイマン1世によって建設されたものである。城壁には北側中央にあるダマスクス門から時計回りに、ヘロデ門、獅子門、黄金門、糞門、シオン門、ヤッフォ門、新門の八つの門があり、ここからしか出入りができない。19世紀に作られた新門以外はスレイマン時代より存在する門である。(エルサレム - Wikipedia

こういうすごいところなのです。


f:id:shu223:20160725162845j:image:w600


f:id:shu223:20160725163126j:image:w600

(石造りの街並)


f:id:shu223:20160725162641j:image:w400

(嘆きの壁で講演の成功を祈る。かぶっている帽子はキッパというそうです)


観光ではありませんが、パレスチナはこういう機会でもないとなかなか入っていけない(個人の旅行でも入れるみたいですが)ので、すべてが新鮮でした。


f:id:shu223:20160728143114j:image:w600

(パレスチナのとあるレストランから見た風景)


あと、パレスチナからの帰り、かの有名な死海にも寄っていただいたのですが、ビーチに出られるゲートが既に閉まっていて、遠くの方から眺めることしかできませんでした。


大使との会食

なんと、イスラエル大使公邸にてイスラエル大使とお食事をご一緒させていただく機会にも恵まれました。


f:id:shu223:20160726210756j:image:w500


安倍総理やオバマ大統領との写真が飾られている中、恐縮しすぎてちゃんと話せるのかと心配もありましたが、非常に気さくに話していただき、ご飯も和洋イスラエル料理の折衷で非常に美味しく、至福の時間を過ごさせていただきました。


f:id:shu223:20160816093042j:image:w600


途中ポケモンGOの話題になり、帰り際にズバット(コウモリみたいなやつ)を見つけて大使とのツーショットを撮影したところ非常に喜んでいただけました。(写真は 在イスラエル日本大使館のページに掲載されています。)


治安

よく聞かれるのですが、今回の滞在中、治安について不安に感じることは一切ありませんでした。そもそも「海外危険情報」を出しているのが外務省であり、移動も行き先もその外務省や現地大使館の方々が全面的にアレンジしてくださったので、大船に乗った気持ちだったというのもあります。


が、最近ではテルアビブの平均年収が東京のそれを超えたという話もあり、普通に生活水準も高く、警備もしっかりしていることもあって、基本的にかなり平和なようです。


f:id:shu223:20160727122358j:image:w600

(とあるオフィスから見たテルアビブ市街)


旅行なり仕事なりで、またぜひ行きたいと思っています。


おわりに

行く前はワクワク感よりも「自分でいいのだろうか」という不安の方が大きかったのですが、それなりに事業の趣旨に沿った貢献もできたと思うし、僕としては大変貴重な経験を多くさせていただけたので、とにかく行ってよかったです。


本事業の実現にご尽力いただいた外務省の皆様、各講演のアレンジから滞在中の移動や食事等全てにおいてお世話になった在イスラエル日本国大使館の皆様、パレスチナ講演にご協力いただいた対パレスチナ暫定自治政府日本国政府代表事務所の皆様、どうもありがとうございました!


お知らせ

iOSDC

いよいよ今週末に差し迫った iOSDC 2016 にて、『海外のiOSカンファレンスに登壇する - 完全版』というタイトルで発表させていただきます。


ベルリンの「UIKonf」、ロンドンの「iOSCon」、サンフランシスコの「AltConf」と、今年は3つの海外のiOSカンファレンスに登壇する機会に恵まれました。


とはいえ招待されたわけではなく、CFPに自ら応募して投票・審査の上で採択された結果です。


本発表では、海外カンファレンスに参加するメリット、CFPの探し方、発表の準備、実際の登壇でうまくいったことや失敗したこと等について話します。


出番は朝イチの10:20、しかもゲストスピーカーである岸川さんの裏ということで誰も来てくれないんじゃ・・・と恐々としております。来ていただけると嬉しいです。


iOSDC Reject Conference

iOSDC Reject Conferenceにもday1、day2両方とも出させていただきます。


day1はこちらのテーマ。


day2の方は5分のLT枠で応募していて、落ちたのですが、15分枠が定員割れで空いていたので、そちらで出させていただくことになりました。


どちらもまだまだ勉強が必要な分野ですががんばって準備します。よろしくお願いします。


*1:イベントの告知内容や現地主催者の要望に応じてソースコードレベルの話までするかどうかというようなちょっとした調整はした

2016-07-20

TensorFlowをiOSで動かしてみる

TensorFlow に iOS サポートが追加された というニュースを見かけたので、ビルドして、iOSで動作させてみました。


f:id:shu223:20160720074930j:image:w240

たまたま目の前にあった扇風機もバッチリ認識してくれました)


本記事では最終的にうまくいった手順を書いています。この手順をなぞってみるにあたってTensorFlowや機械学習・ディープラーニングについての専門知識は不要ですのでぜひお試しください!


ビルド手順

(2017.4.15追記)v1.1.0 RC2 のビルド

現時点での最新Release(候補)である v1.1.0 RC2 も、tensorflow/contrib/makefile/build_all_ios.sh を実行するだけでビルドできました。


(2016.8.22追記)v0.10.0 RC0 のビルド

現時点での最新Releaseである v0.10.0 RC0 は、上記手順でビルドしようとすると compile_ios_tensorflow.sh を実行するところでコケてしまったのですが、今は各ビルドの手順がまるっと入ったスクリプトが用意されているようです。

tensorflow/contrib/makefile/build_all_ios.sh

依存ライブラリのダウンロードからiOSアーキテクチャ向けビルドまで、これ一発でokでした。


(※旧バージョンでの手順)v0.9.0 のビルド

iOSサポートバージョンであるv0.9.0をチェックアウトして、以下の手順でビルドしていきます。手順はこの通りになぞるだけですし、ほぼスクリプトを実行するだけで非常に簡単です(が、実行時間がかなりかかります)。


  • スクリプトを実行して Eigen や Protobuf 等の依存ライブラリをダウンロード
cd tensorflow
tensorflow/contrib/makefile/download_dependencies.sh

  • protobuf をビルド&インストール
cd tensorflow/contrib/makefile/downloads/protobuf/
./autogen.sh
./configure
make
sudo make install

ここで、僕の環境では `./autogen.sh` 実行時に

Can't exec "aclocal": No such file or directory at /usr/local/Cellar/autoconf/2.69/share/autoconf/Autom4te/FileUtils.pm line 326.
autoreconf: failed to run aclocal: No such file or directory
shuichi-MacBook-Pro-Retina-15inch:protobuf shuichi$ ./configure
-bash: ./configure: No such file or directory

というエラーが出ました。”aclocal”というのは、”automake”パッケージに含まれているらしいので、automakeをインストール。

brew instal automake

で、改めて

./autogen.sh
./configure
make
sudo make install

  • iOS native版のprotobufをビルド
cd ../../../../..
tensorflow/contrib/makefile/compile_ios_protobuf.sh

  • iOSアーキテクチャ向けにTensorFlowをビルド
tensorflow/contrib/makefile/compile_ios_tensorflow.sh

サンプルをビルドする

`tensorflow/tensorflow/contrib/ios_example` に2種類のサンプルがあります。


simple と名付けられたサンプルアプリは、今回ビルドした static library をアプリ内に組み込む際の最小実装としての参考にはなりそうですが、デモとして見て楽しい機能があるわけではないので、本記事ではもう一方の camera の方を紹介します。


まず、このファイルをダウンロードして、解凍すると入っている、

  • imagenet_comp_graph_label_strings.txt
  • tensorflow_inception_graph.pb

の2つのファイルを、`tensorflow/contrib/ios_examples/camera/data` に置きます。*1


この Inception というのはGoogleが提供する画像認識用の学習済みモデルのようです。


cameraサンプル実行例

cameraサンプルを実行すると、すぐにカメラが起動します。身近のものを色々と映してみました。(リアルタイムカメラ入力に対する認識結果を表示してくれます)


MacBook

f:id:shu223:20160720080028j:image:w240


"Notebook" "Laptop" どっちでも正解!


扇風機

f:id:shu223:20160720074930j:image:w240


"Electric Fan" 正解!


椅子

f:id:shu223:20160720080106j:image:w240


"Folding Chair"(折りたたみ椅子) 惜しい。。ですが、そもそも `imagenet_comp_graph_label_strings.txt` には chair が3種類しかなくて、その中では一番近いと言ってもいいかもしれません。


iPhone

f:id:shu223:20160720080129j:image:w240


"iPod"・・・惜しい!iPhoneなのでほぼ正解と言ってもいいかもしれません。


パフォーマンス

今回cameraサンプルを試したデバイスはiPhone 6だったのですが、認識はまだまだリアルタイムとは言い難く、数秒単位の遅延がある感じでした。まだiOS向けにビルドできるようになったというだけでiOSにおける GPU Accelerated はされてないですし、パフォーマンスの最適化はまだまだこれからのようです。


(2017.4.15追記)v1.1.0 rc2 / iPhone 7 で試したところ、それなりにリアルタイムで動きます。`contrib/ios_examples` 配下のコミットログを見たところ、Metal等による最適化はまだされてないようですが、いくつかパフォーマンスに関連しそうな改善はあったようです。

(追記ここまで)


ちなみにiOS 10 で Accelerate.framework に追加された BNNS (Basic neural network subroutines) や MetalPerformanceShaders.framework に追加されたCNNのAPIを使用する最適化もissueに挙がっています。


MPSCNNについてはいくつか記事を書いたのでよろしければ:


ビルド手順の情報ソース

iOSサポートバージョンである0.9.0トップ階層にあるREADMEを見ても、iOSについては書かれていません


上述したビルド手順は`contrib/makefile` 配下のREADMEに書かれています。

関連情報を以下にまとめておきます。


サンプルのソースコードを読んでみる

サンプルは全編Objective-C++で書かれています。読んでもわからないだろうと思いつつ、せっかくなので読んでみます。


tensorflow_utils

モデルとラベルデータを読み込むメソッドと、認識結果を返すメソッドを持つユーティリティクラスのようです。

tensorflow::Status LoadModel(NSString* file_name, NSString* file_type,
                             std::unique_ptr<tensorflow::Session>* session);
tensorflow::Status LoadLabels(NSString* file_name, NSString* file_type,
                              std::vector<std::string>* label_strings);
void GetTopN(const Eigen::TensorMap<Eigen::Tensor<float, 1, Eigen::RowMajor>,
             Eigen::Aligned>& prediction, const int num_results,
             const float threshold,
             std::vector<std::pair<float, int> >* top_results);

汎用的に使えそう。


ios_image_load

画像ファイルを読み込むクラス。

std::vector<tensorflow::uint8> LoadImageFromFile(const char* file_name,
             int* out_width,
             int* out_height,
             int* out_channels);

プロジェクトには追加されているけど使われてないっぽい。


CameraExampleViewController

サンプル本体。肝っぽいところだけを拾っていくと、


`std::unique_ptr<tensorflow::Session>` なメンバ変数を定義して、

std::unique_ptr<tensorflow::Session> tf_session;

viewDidLoadのタイミングでモデルを〜.pbファイルからロード

tensorflow::Status load_status =
  LoadModel(@"tensorflow_inception_graph", @"pb", &tf_session);

で、カメラからのリアルタイム入力が得られるたびに呼ばれるデリゲートメソッドを見てみると、

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection {
  CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
  [self runCNNOnFrame:pixelBuffer];
}

CMSampleBufferRef から CVPixelBufferRef を取得して `runCNNOnFrame:` を呼んでいるだけのようです。


`runCNNOnFrame:` はコードが若干長いですが、このへんと、

tensorflow::Tensor image_tensor(
    tensorflow::DT_FLOAT,
    tensorflow::TensorShape(
        {1, wanted_height, wanted_width, wanted_channels}));
auto image_tensor_mapped = image_tensor.tensor<float, 4>();
tensorflow::uint8 *in = sourceStartAddr;
float *out = image_tensor_mapped.data();

このへんが肝っぽいです。

if (tf_session.get()) {
  std::string input_layer = "input";
  std::string output_layer = "output";
  std::vector<tensorflow::Tensor> outputs;
  tensorflow::Status run_status = tf_session->Run(
      {{input_layer, image_tensor}}, {output_layer}, {}, &outputs);
  if (!run_status.ok()) {
    LOG(ERROR) << "Running model failed:" << run_status;
  } else {
    tensorflow::Tensor *output = &outputs[0];
    auto predictions = output->flat<float>();

    // ラベル取得
  }
}

が、すみません、それぞれ何をやっているのかを解説するにはTensorFlowの処理をちゃんと理解する必要がありそうです。。(勉強します)


自分のアプリに組み込む

試せていませんが、こちら に手順が示されていました。

  • ユニバーサルなstatic library(libtensorflow-core.a)をビルドしてプロジェクトに追加する
    • [Library Search Paths] にも追加。

The `compile_ios_tensorflow.sh' script builds a universal static library in tensorflow/contrib/makefile/gen/lib/libtensorflow-core.a. You'll need to add this to your linking build stage, and in Search Paths add tensorflow/contrib/makefile/gen/lib to the Library Search Paths setting.

  • libprotobuf.a と libprotobuf-lite.a をプロジェクトに追加する。
    • [Library Search Paths]にも追加

You'll also need to add libprotobuf.a and libprotobuf-lite.a from tensorflow/contrib/makefile/gen/protobuf_ios/lib to your Build Stages and Library Search Paths.

  • [Header Search paths] を追加

The Header Search paths needs to contain the root folder of tensorflow, tensorflow/contrib/makefile/downloads/protobuf/src, tensorflow/contrib/makefile/downloads, tensorflow/contrib/makefile/downloads/eigen-eigen-, and tensorflow/contrib/makefile/gen/proto.

  • [Other Linker Flags] に `-force_load` を追加

In the Linking section, you need to add -force_load followed by the path to the TensorFlow static library in the Other Linker Flags section. This ensures that the global C++ objects that are used to register important classes inside the library are not stripped out. To the linker, they can appear unused because no other code references the variables, but in fact their constructors have the important side effect of registering the class.

  • bitcodeを無効にする

The library doesn't currently support bitcode, so you'll need to disable that in your project settings.


まとめ

TensorFlowをiOS向けにビルドし、付属のサンプルを動かしてみました。パフォーマンスの最適化等、まだまだこれから感はありますが、扇風機や椅子、ノートパソコンやiPhone等、大きさも形も全然違うものを認識してくれて未来を感じます。


試してみるだけなら機械学習やTensorFlowについての専門知識を必要としませんし、ぜひお手元で動かしてみてください!


次のステップとしては、下記記事で紹介されているテンソルの計算部分に特化してSwiftで書かれたライブラリと比較したりしつつ、ちゃんとTensorFlowでやっていることを理解したいと思います。


また、本記事同様に「とりあえず動かしてみる」シリーズとして、こちらもよろしければどうぞ:


*1:ちなみにこのとき、 https://github.com/miyosuda/TensorFlowAndroidDemo/find/master にある同名ファイルを使っても、ちゃんと動きません。参考

2009 | 08 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 11 | 12 |
2017 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2018 | 02 |