Quantcast
Channel: その後のその後
Viewing all 314 articles
Browse latest View live

ニッチな技術書を書いて #技術書典 に出展してみたら想像以上に需要があった話

$
0
0

昨日「技術書典4」にて、iOS/macOSGPUインターフェースであるMetalの入門書を販売してきました。初出展、初参加なので雰囲気を想像するのがなかなか難しく、ニッチな技術書なのできっと大量に余るだろうなと想像してたのですが、ありがたいことに用意した100部が完売。こういう本でもこれだけ需要があるということに驚き、感動した1日でした。

以下振り返りになります。

本の出来が最高だった

印刷は「日光企画」さんにお願いしました。

僕は学生時代に製本工場で日雇いのバイトをしたことが何回かあって、そこはちょっとしたことですぐに怒鳴るおじさんとかいて非常に緊張感のある職場でした1

というわけで印刷所=怖いというイメージしかなかったのと、サイトをみると情報量が多すぎてどうすればいいのかわからなくてビビっていたのですが2、開催一週間前になってやっと勇気を出して日光企画さんに電話してみたところこれがまぁめちゃくちゃ親切で、質問に丁寧に答えてくれるし、入稿したときも午前中にすぐに確認の電話をくれて、ああ印刷所って怖くないんだ、とイメージを改めた所存です。

そして開催当日の朝、会場のブースに届いていた箱を開けてみると、

f:id:shu223:20180422101931j:plain

最高。

A5というコンパクトさと130ページのちょっとした厚み、表紙のマットPP加工、透明度15%の薄いロゴ。僕は技術書が好きで電子版隆盛の今でも装丁によっては紙の本を買ったりしますが、これは普通に自分でも欲しいと思える出来に仕上がっていました。

売上

書籍(製本版)は1200円、電子版(PDF)とのセットで1500円。4分の3ぐらいの方が電子版セットの方を選択されました。プラス「普及版」という廉価バージョンと、BOOTHで前日に出していた電子版がイベント当日にもポツポツ売れたのもあり、この日の売上は約18万円でした。

今後も電子版や再販、コンテンツの横展開で収益がありえること、そしてそもそも商業誌だと絶対に企画が通らなそうな(≒初版2000部は売れなさそうな)ニッチな分野で本を書いて、それなりに稼げたということに非常に可能性を感じております。

とはいえそれもこれも、マニアックな技術書を買いに6000人もの人達が集まる技術書典というイベントあってのこと。本当にありがたい限りです。

もっと部数を増やすべきだったか?

  • 100部完売したのが14時過ぎ。ペース的に150部だと完売はしなかったと思われる
  • それにしてもわざわざ買いに来てくれた人のぶんがなかったのは申し訳無さの極みなので、次は余らせるぐらいに刷ります
  • とはいえ今回の100部も「絶対余る」と思った数なので難しい。。

その他反省

  • 技術書典のシステムへ情報を登録していなかったため、後払いシステム(QRでの購入)が電子版セットで利用できなかった
  • 同じく、一緒に出ていた多賀谷さんがそのへんのシステムを利用できなくて申し訳なかった(システムに価格を入力したのが前日)
  • 値段体系が複雑になってしまった
    • 「普及版」の存在が話をややこしくしてしまった
    • よくわからないとお客さんは帰る
    • 後半は説明の仕方がこなれてきた。言い方大事。
  • 売り子として未熟すぎた
    • ダウンロードコードの紙をチョキチョキ切る作業をやってたり
    • 「どうぞ見てってください」のひとことは大事
    • って家に帰ってから思った

その他の学び

  • 印刷所の入稿期限は想像以上にギリギリまで行ける(=ギリギリまで執筆できる)
    • 開催前週の火曜深夜に入稿したが、実際のところまだ1日ぐらい猶予があった

  • おつりは6万円ぶん用意していったが、使わなかった

  • テーブルを覆う布はあってもなくてもよかったかも
  • ブースを構える側の気持ちがわかったのは良い副産物だった

    • いままでこういうブース形式のところに近寄るのが苦手だった
    • 手にとって、買わなくても全然気にならない。手に取ってくれるだけでも嬉しい
    • というわけで完売後に他のブースまわるの楽しかった
  • 本としての佇まいをカッコよくすることは大事

    • 自分で会場を周ったときも、かっこいい本は遠目からでも気になった

今後の展望

  • これでMetal人口増えたら嬉しい
  • Kindle版も出したい
  • 2冊目3冊目も出したい
    • 技術書典5も通ったらvol.2出したい

おわりに

技術書典4、最高でした。運営のみなさま、参加者のみなさま、お買い上げいただいたみなさま、本当にありがとうございました!技術書典5ももちろん応募します!

Metal入門、電子版は4/24まで1500円のところ1200円で販売しております。

booth.pm


  1. 深夜〜朝まで働いて1.5万円ぐらいもらえる当時(20年前)としては破格の仕事だった

  2. こういう理由で、当初「製本直送.com」というシンプルな1部から印刷可能なサービスで刷ろうかなと思っていました。が、製本直送.comだと印刷原価が一冊1500円以上になることがわかって最終的に断念


[書評]iOS/Androidアプリ開発の総合解説書 - モバイルアプリ開発エキスパート養成読本

$
0
0

著者のひとり、森本さん(@dealforest)および版元の技術評論社様よりモバイルアプリ開発AndroidiOS)を解説する技術書「モバイルアプリ開発エキスパート養成読本」をご恵贈いただきました。

f:id:shu223:20170530170038j:plain

この表紙に見覚えがある方もいらっしゃるかもしれません。そう、本書の刊行は1年前、2017年4月24日です。Swift 3、iOS 10Xcode 8とメジャーバージョンにして最新からひとつ前になってしまった数字を見るにつけ記事を書くのが遅れたことを申し訳なく思う気持ちを抱きつつも、いや、バージョンが変わってしまって注目度が下がっているかもしれない今こそこの良書を改めて紹介するタイミングなのではと。

たとえば「Swift 3入門」という記事がありますが、この章では3からの大きい変更である「命名規則」について詳しく解説されています。これはSwift.orgのAPI Design Guidelinesに書かれている1内容で、これはSwift 4になった今でも重要ですし、これを日本語で解説してくれているまとまった情報源というのは貴重ではないでしょうか。

またiOS 10の新機能/新API群も、iOS 12がそろそろ発表されるであろう今こそ、これからiOS 9を切り、いよいよiOS 10APIを積極的に使っていくぞ、という時期なのではないでしょうか。User Notificationsフレームワークによって新たに可能になったリッチなpush通知や、Haptic Feedback等は多くのアプリにとって導入を検討する価値があります。

(User Notifiationsを利用したリッチなプッシュ通知 2

ちなみにiOS 10からの機能ではありませんが、日本では同時期から利用可能になったということで、本書ではApple Payの実装についても詳しく解説されているのも貴重なポイントです。

Xcode 8の章も、(当時の新機能である)Memory Graph DebuggerとInstrumentsを両方活用してメモリリークデバッグする方法や、PlaygroundでCocoaPods/Carthageを使う方法など、さらっと実践的なTipsが書かれていたりします。他にも「なぜXcode Extensionが導入されたのか?」「Automatic Signingで困るケース」等々、とにかく開発者視点だなと。

他の解説書にはない、実際の開発現場に即した内容

iOSアプリ開発やSwiftの入門書は数多出ています。いずれの書籍にも重要なことが書かれていますし、アプリをつくれるようにはなるでしょう。しかし、実際に会社に入り、ひとつのサービス/プロダクトを継続的に開発・運用していく場合、それら既存の本に書かれていることとはまた別の知識が多く必要になります。

本書ではリアクティブプログラミング(RxSwift)、設計手法、テスト、運用ツール(Fastlane等)、mBaaS(Firebase)といった、他の書籍ではなかなか扱わないであろう、しかし昨今の開発現場では必須ともいえるテーマについても書かれています。

目次

目次と、それぞれの著者を載せておきます。現場でバリバリやってるあの人やこの人が書いてます。また本記事はiOSエンジニア視点で書いてますが、Androidについても同じテーマで書かれています。

第1章: モバイルアプリ開発の基礎知識

  • 1-1 モバイルアプリ開発を取り巻く最近の動向…… 黒川 洋 坂田 晃一

第2章: Android開発最前線

  • 2-1 快適な開発を実現! Kotlin徹底入門…… 藤田 琢磨
  • 2-2 最新Android Studio入門…… 山戸 茂樹
  • 2-3 アプリの使い方を大きく変えるAndroid 7.0/7.1の新機能…… 山田 航

第3章: iOS開発最前線

  • 3-1 Swift 3.0入門…… 田坂 和暢
  • 3-2 iOS 10入門…… 熊谷 知子
  • 3-3 Xcode 8入門…… 森本 利博

第4章: リアクティブプログラミング入門

  • 4-1 リアクティブプログラミングとRx…… 黒川 洋
  • 4-2 RxJava実践入門…… 黒川 洋
  • 4-3 RxSwift実践入門…… 坂本 和大

第5章: 現場で役立つモバイルアプリ設計・開発

  • 5-1 メンテナビリティに優れたAndroidアプリを作るための実践ガイド…… 小形 昌樹
  • 5-2 タイプセーフでモダンなiOSアプリの設計…… 鈴木 大貴

第6章: 現場で役立つテスト

  • 6-1 モバイルアプリのテスト事始め…… 山戸 茂樹
  • 6-2 Androidアプリのテスト…… 藤田 琢磨
  • 6-3 iOSアプリのテスト…… 森本 利博

第7章: 運用に役立つツールの使い方

  • 7-1 モバイルアプリの運用に役立つツール…… 志甫 侑紀
  • 7-2 Androidアプリの運用に役立つツール…… 志甫 侑紀
  • 7-3 iOSアプリの運用に役立つツール…… 坂田 晃一

第8章: 今注目の「統合アプリプラットフォーム」Firebase活用入門

  • 8-1 今注目の「統合アプリプラットフォーム」Firebaseとは…… 山田 航
  • 8-2 Firebaseをアプリに導入しよう…… 山田 航
  • 8-3 導入したFirebaseを運用してみよう…… 山田 航

まとめ

そんなわけで、「モバイルアプリ開発エキスパート養成読本」、他の書籍には書かれていない「実際の開発現場に即した実践的な知見」にあふれていて、非常に良い本なので気になった方はぜひ。Kindle版もあります。

モバイルアプリ開発エキスパート養成読本 (Software Design plus)
山戸 茂樹 坂田 晃一 黒川 洋 藤田 琢磨 山田 航 田坂 和暢 熊谷 知子 森本 利博 坂本 和大 小形 昌樹 鈴木 大貴 志甫 侑紀
技術評論社
売り上げランキング: 231,722

  1. 本書はSwift Evolutionのproposalをベースに書かれています。

  2. 画像はiOS 10 Samplerより

フリーランスを再開して2ヶ月のお仕事まとめ

$
0
0

アメリカでのパートタイム会社員と日本でのフリーランスの2足のわらじを履き始めてから約2ヶ月が経ちました。今月からまた1ヶ月ほど会社員に戻るので、この2ヶ月にやったこと・つくったものをまとめておきます。1

f:id:shu223:20180506214619j:plain
Alexaを持ち出して外で遊ぶ

Core NFCを使ったゲームアプリ

これはまだ未公開なのですが、Core NFCを使ったゲームアプリをつくりました。ブルーパドル社でのお仕事。既に何種類かのゲームが遊べるのですが、手前味噌ながらかなり楽しいです。早く公開したいですがもうちょっと先になりそうです。

Core MLを使った写真の自動分類機能

とあるIoTスタートアップにて。モデル自体は社内の機械学習エンジニアの方がつくったものが既にあり、それをCore MLで使えるように変換するところからスタート。精度やパフォーマンスの検証、どういうUXに落とし込むのがいいかの検討を経て、当該企業のiOSアプリのいち機能として実装しました。社内βテストののち、近いうちにリリースされる見込みです。

ARKit、Metalを使った機能

GraffityというAR落書きSNSアプリ(最近出た2.0ではARビデオ通話アプリに)の開発をお手伝いしました。ARKitをプロダクトとしてがっつりやっている会社というのは(ゲームを除いて)たぶんまだ多くはなく、しかもMetalシェーダを書くという今の興味にがっちりはまるお仕事でした。2

技術顧問

最近立ち上がったとある会社に技術顧問として関わらせていただいてます。優秀な方々が開発していて、正直なところ技術を顧問できてるかは疑問ですが、年齢的にボードメンバーと開発メンバーのちょうど中間だったりするので、開発陣と経営陣のコミュニケーションの橋渡し役をしたり、色んな現場を見てきたならではの視点からプロダクト全体の方向性について意見を言ったりといったところではお役に立ててるのかなと。立ち上がったばかりのスタートアップで状況は常に動き続けているので、自分がどこで役立てるのか、慎重に見定めて行動していきたい所存です。

その他

Alexaスキル

すごく簡単なものですが、Alexaスキルをつくり、ブルーパドルメンバーで遊んでみたりしました。これ自体はストアで公開するほどのものではないのですが、「音声インターフェースアプリケーションはこんな感じでつくる」というのが掴めてよかったです。

ウェブのマークアップ

ブルーパドル社ではマークアップも経験しました。htmlとcssの概念ぐらいはもちろん理解してましたが、gulp、pug、scssというような最近の書き方はまったく知らなかったし、レスポンシブ/スマホ対応というのはそういうことなのねというのを知れたのも良かったです。残念ながらJSまでは時間的に手が回らず。

AV Foundationを使うiPadアプリ

GitHubの僕のとあるリポジトリを見て、海外の会社より依頼をいただきました。AV Foundationの最近さわってないAPIが関わるところだったので、自分のローカルコードベースを再整備しておく意味でもこれはやっておきたかったのですが、タイミング的に一番忙しい時期で、「次の休日に1日だけやってみて、間に合いそうならやる」と先方に伝え、1日やってみた感触では保ち時間では到底終わりそうにないためゴメンナサイしました。

Fyusion社のお仕事

アメリカでの雇い主であるFyusionより、ちょくちょくタスクが来てました。フリーの仕事で手一杯で機能開発までは手が回りませんでしたが、僕が実装した部分について質問に答えたり、日本のクライアント関連の対応をしたり。

個人活動

はじめて技術書を個人で出版

iOS/macOSGPUインターフェースであるMetalの入門書を書き、「技術書典4」にて販売しました。

shu223.hatenablog.com

総括

実績がぼやけている?

この2ヶ月、夜も休日も仕事をしていてものすごく忙しかった気がするのですが、こうやって列挙してみると、不思議なもので「もうちょっとできたのでは」という気がしてきます。

大小のプロジェクトが順不同で入り混じっているので、工数順に並べ替えてみます。

Metal入門執筆(9人日) > ARKit+Metalを使った機能開発 > Core MLを使った機能開発 >技術顧問 > Webマークアップ> Core NFCを使ったアプリ開発>その他(それぞれ1日かそれ未満)

左端と右端以外はあまり大差なく、のべ5〜8人日ぐらい。こうして個々の工数を意識してみると、要は分散してしまってるのだなと。

これはなかなか悩ましい問題です。いまのところは、AlexaやWebをやってみるといった「寄り道」は、これまでiOSにフォーカスしすぎた自分には必要なもので、逆に「プロフィールに書いたときにわかりやすく目立つ実績」(例: 有名なプロダクトをほぼまるっと実装、みたいなの)は、いま仕事の依頼が増えても手が増えるわけでもないので、こだわりすぎるところではないかなと考えています。

iOSエンジニアとしてのリハビリ

1年半にわたってひとつの会社にフルコミットしてきたのち、ひさびさにフリーランスとして色々な現場に行ってみるとまず気付いたのは、iOSエンジニアとしての総合力が落ちているということでした。Fyusion社では機械学習・3Dプログラミング・GPU制御といった新しいフィールドを開拓できた一方で、そういった技術を利用する機能の開発に関わることにフォーカスしていたためか、UIKitの細かい挙動とか、DBまわりとか、Swiftの最近のデファクト系ライブラリとか、そういう今までは普通にキャッチアップできていたところが疎くなっていて、浦島太郎になったような心持ちでした。

専業iOSエンジニアが書いたさまざまな現場のコードに触れ、ひさびさに日々の仕事でSwiftを書き、フルスクラッチでアプリもつくり・・・という中で、だいぶ勘を取り戻せた(キャッチアップできた)実感のある2ヶ月でした。

興味のある技術分野のお仕事

MetalやARKitといった最近興味を持っている分野のお仕事や、Core MLやCore NFCといった新しいフレームワークを実プロダクトで使う機会にも恵まれ、ただただ楽しかったです。

心残りは得られた技術ノウハウ3をアウトプットできてない点。たとえばCore NFCとか、ARKitとか、実プロダクトで使ってみてこそ得られる細かい知見がいろいろとありますが、今の所ローカルメモの中で埋もれています。

技術書の個人出版という新しい可能性

前身ブログ、QiitaGitHubと、たくさん「技術情報発信」を行ってきましたが、基本的にそれら自体は無収益でした。書籍を書くこともありましたが、フルコミットで2ヶ月とかかかって、印税は「3日受託開発した方が稼げる」ぐらい。

自分に学びがあるし、発信した内容からお仕事に繋がることもあるのでここでご飯を食べられる必要はないのですが、問題は、フリーとしての仕事(しかもおもしろい)がたくさんあるとき、それらを断ってまで(=自分の時間を1日n万円で買ってまで)新しい技術を勉強する選択がなかなかできない、というところにありました。

そんな折、今回「Metal入門」というニッチな技術書を執筆し、出版社を通すことなく個人で販売してみたところ、なんと簡単に収益が商業本の印税を超えてしまいました。

執筆に使った時間をカウントしてみると、のべ9人日ぐらい。この内訳としても、半分ぐらいは本としての体裁を整えるためにRe:Viewと格闘する時間だったり、印刷所を選んだり入稿方法について調べたりする時間だったりしたので、2回目、3回目とやっていくうちにもっと短縮できるはずです。そうすると、いずれ(下地となるブログ記事等が既にある前提で)技術情報発信の時間単価が受託開発の時間単価に並ぶというのも可能性としては考えられ、これは個人的には非常にエポックメイキングな出来事でした。

ブルーパドル社での非常勤メンバーとしての関わり

ブルーパドル社では毎週「ハッカソン」と称し、なにか簡単なものをつくってそれをベースにいろいろ遊んでみつつブレストする、ということをやってます。これがめっちゃ良くて、自分でアイデアを出す脳みそをまた久々に使うようになったし、家で眠ってるガジェットを掘り起こして触ってみる機会にもなってます。(上述したAlexaスキルはそのうちのひとつ)

また僕が普段フリーランスとしてお手伝いしているスタートアップの世界と、ブルーパドル社の主な事業領域である広告の世界、すぐ隣にあるようでまったく別の世界である点もおもしろいです。同じようなプログラミング言語フレームワークを使っていても、優先するポイントや考え方が違う。それに付随してスピード感とかも違ってくるし、それぞれの業界にいる人達の興味やトレンドも違う。

いろんな面でとにかく新鮮で、毎日多くの学びがあります。

今後の展望

冒頭に書きましたが、フリーランス活動は一区切りし、5月はひさびさにサンフランシスコに戻ってFyusion社にフルコミットします。6月頭はWWDCで、中旬ぐらいからまたフリーランスを再開する予定です。


  1. 許可をいただいた会社だけ社名を書いています。自分が関わったプロダクトや機能がまだ出ていない会社については、出たら聞こう、と思ってたのでまだ伏せています。

  2. ちなみにアメリカで所属しているFyusion社と事業領域がかぶるところがあるといえなくもない(AR)ので、そこらへんはあらかじめあちらのボードメンバーに了承をとりました。

  3. もちろんその会社固有の技術情報ではなくAPIの使い方とかハマりどころとか、あくまで一般的な話

API Diffsから見るiOS 12の新機能 - ARKit 2 #WWDC18

$
0
0

今年のWWDCの基調講演は、エンドユーザ向けの新機能の話に終止した感が強く、デベロッパ的にはあまりピンと来ない2時間だったように思います。が、State of the Unionやドキュメントを見ると、試してみたい新APIが目白押しです。例年通り、気になったものを列挙していきます 1

全部書いてると時間かかりそうなので、まずは本記事では ARKit 2について。

Multiuser and Persistent AR

自分が見ているARの世界を共有・永続化できるようになったというのは本当に大きいです。Appleのデモは「ゲームで対決できます」みたいな派手なものでしたが、たとえば奥さんの机に花を置いておくとかみたいなささやかなものでもいいですし、ソーシャルコミュニケーションな何かでもいいですし、教育的な何かでも使えそうですし、とにかく「自分しか見れない」という従来の制約がなくなるだけでARを利用したアプリのアイデアはめちゃくちゃ広がると思います。

f:id:shu223:20180605114618p:plain

API的には、ARWorldMapというクラスが追加されていて、これが「世界」の情報で、これを保存したりシェアしたりするようです。

ARMultiuserというサンプルが公開されていて、送受信のあたりのコードはこんな感じです。

(送る側)

sceneView.session.getCurrentWorldMap { worldMap, error inguardletmap= worldMap
        else { print("Error: \(error!.localizedDescription)"); return }
    guardletdata= try? NSKeyedArchiver.archivedData(withRootObject:map, requiringSecureCoding:true)
        else { fatalError("can't encode map") }
    self.multipeerSession.sendToAllPeers(data)
}

(受け取り側)

ifletunarchived= try? NSKeyedUnarchiver.unarchivedObject(of:ARWorldMap.classForKeyedUnarchiver(), from:data),
    letworldMap= unarchived as? ARWorldMap {
    
    // Run the session with the received world map.letconfiguration= ARWorldTrackingConfiguration()
    configuration.planeDetection = .horizontal
    configuration.initialWorldMap = worldMap
    sceneView.session.run(configuration, options:[.resetTracking, .removeExistingAnchors])
    
    // Remember who provided the map for showing UI feedback.
    mapProvider = peer
}

ここで面白いのは、このサンプルでは送受信に Multipeer Connectivity を使っていて、データとしては普通にNSKeyedArchiverアーカイブ/アンアーカイブしたデータを送り合っている点です。

つまり、送受信や保存の方法はARKitに依存しておらず、なんでもOKということです。データをサーバに送ってもいいわけですが、バックエンドを用意せずとも、サクッとUserDefaultsに保存してもいいし、Realmに保存してもいいし、Core Bluetooth(BLE)を利用しても良いわけです。([PR]その際、こういう本が役に立つかもしれません)

iOS×BLE Core Bluetoothプログラミング
堤 修一 松村 礼央
ソシム
売り上げランキング: 92,732

3D Object Detection

「3D物体検出」は従来の(2D)物体検出と何が違うかというと、「正面から見た状態」だけでなく、横からでも、後ろからでも、上からでも、その物体を認識できるということです。この機能により、現実空間の物体(銅像とか)をマーカーとして仮想コンテンツを置く、といったことが可能になります。

ARKit 2には、3D物体を「スキャン」して「リファレンスオブジェクト」を生成する機能と、そのリファレンスオブジェクトと同じ特徴を持つ物体を現実空間から検出する機能とが追加されています。

f:id:shu223:20180605140338p:plain

(サンプルに同梱されている画像。スキャン〜検出の流れが示されている)

このわりと複雑なスキャンフロー、出来合いのやつがあるのかなと思いきや、ソースを見てみるとがっつりアプリ側で実装されています。3Dバウンディングボックスを順番に埋めていくのとかも全部。まぁ、ここはUIUXとして工夫のしがいがあるところなので、この方が良いですよね。

スキャンする際は、コンフィギュレーションとしてARObjectScanningConfigurationを使用します。

let configuration = ARObjectScanningConfiguration()

で、スキャン中にどういうことをするかですが・・・非常に泥臭い実装がされています。ここでは省略しますが、ARSessionDelegateの各デリゲートメソッドから実装を追ってみてください。

リファレンスオブジェクトを表すARReferenceObjectを作成するには、ARSessioncreateReferenceObject(transform:center:extent:completionHandler:)メソッドを呼びます。この引数に、スキャン対象のバウンディングボックスのtransform, center, extentを渡します。

sceneView.session.createReferenceObject(
    transform:boundingBox.simdWorldTransform,
    center:float3(), extent:boundingBox.extent,
    completionHandler: { object, error inifletreferenceObject= object {
            // Adjust the object's origin with the user-provided transform....
        } else {
            print("Error: Failed to create reference object. \(error!.localizedDescription)")
            ...
        }
})

ARKitの新規追加API

APIを眺めるだけでもいろいろと察することはできるので、ざーっと載せておきます。

  • ARWorldMap

The space-mapping state and set of anchors from a world-tracking AR session.

  • AREnvironmentProbeAnchor

An object that provides environmental lighting information for a specific area of space in a world-tracking AR session.

  • ARReferenceObject

A 3D object to be recognized in the real-world environment during a world-tracking AR session.

  • ARObjectAnchor

Information about the position and orientation of a real-world 3D object detected in a world-tracking AR session.

  • ARObjectScanningConfiguration

A configuration that uses the back-facing camera to collect high-fidelity spatial data for use in scanning 3D objects for later detection.

  • ARFaceAnchor - 目の動きのトラッキング

    • var leftEyeTransform: simd_float4x4

      A transform matrix indicating the position and orientation of the face's left eye.

    • var rightEyeTransform: simd_float4x4

      A transform matrix indicating the position and orientation of the face's right eye.

    • var lookAtPoint: simd_float3

      A position in face coordinate space estimating the direction of the face's gaze.

  • ARImageTrackingConfiguration

A configuration that uses the back-facing camera to detect and track known images.

こちらもどうぞ

shu223.hatenablog.com


  1. なお、本記事はNDAに配慮し、Xcode 10やiOS 12のスクショは使わず、公開情報のみで構成しています。

ドラッグ&ドロップで機械学習のモデルがつくれる「Create ML」の使い方

$
0
0

iOS 12の気になる新機能のAPIを見ていくシリーズ。昨日はARKit 2の永続化・共有機能や3D物体検出機能について書きました。

本記事ではCreate MLについて。1

Create ML

Create MLは、Core MLのモデルを作成するためのmacOSの新フレームワークです。

f:id:shu223:20180606070639p:plain

昨日のState of the Unionにてデモがありましたが、なんと、学習用データが入ったフォルダをドラッグ&ドロップするだけで作成できます。

ちなみにmacOS 10.14 Mojaveです。

MLImageClassifierBuilder

まだMojaveにアップデートしていないので試せていない2のですが、丁寧なチュートリアル記事が出ていて、作業手順を図付きで確認できます。

PlaygroundsでMLImageClassifierBuildeを初期化してshowInLiveViewを呼ぶコードを書き、

import CreateMLUI

let builder = MLImageClassifierBuilder()
builder.showInLiveView()

実行するとGUIが表れ、そこにデータフォルダをドラッグ&ドロップすると学習が開始されます。

f:id:shu223:20180606071137p:plain

f:id:shu223:20180606071232p:plain

テスト(モデルの評価)もドラッグ&ドロップ。

f:id:shu223:20180606071320p:plain

いかがでしょうか。コードは正味3行書いただけ機械学習ができてしまいました。

Create MLでつくった.mlmodelフォーマットのモデルファイルを使ったアプリの実装方法はこちらの記事をどうぞ。

Core ML+Visionを用いた物体認識の最小実装 - Qiita

学習用データについて

ドラッグ&ドロップでできます」とはいえ、そのためのデータセットを用意する必要はあります。

どういうデータを用意するかですが、同チュートリアル記事によると、

  • ラベルごとに最低でも10枚の画像
  • ラベルごとに枚数のバランスをとること(チーターは10枚、ゾウは1000枚、みたいなことをしない)

Use at least 10 images per label for the training set, but more is always better. Also, balance the number of images for each label. For example, don’t use 10 images for Cheetah and 1000 images for Elephant.

  • JPEGPNG等、画像フォーマットはなんでもいい(UTIがpublic.imageに適合していれば)
  • サイズは揃ってなくてもOK
  • サイズもなんでもいいが、最低でも299x299ピクセルはあった方が良い

The images can be in any format whose uniform type identifer conforms to public.image. This includes common formats like JPEG and PNG. The images don’t have to be the same size as each other, nor do they have to be any particular size, although it’s best to use images that are at least 299x299 pixels.

あとは実際に推論を行うのと同じ状況で学習データも収集した方がいいとか、いろんな角度、ライティングの状況のデータがあった方がいい、ということが書かれています。

If possible, train with images collected in a way that’s similar to how images will be collected for prediction.

Provide images with variety. For example, use images that show animals from many different angles and in different lighting conditions. A classifier trained on nearly identical images for a given label tends to have poorer performance than one trained on a more diverse image set.

ラベルをフォルダ名にし、その配下にトレーニングデータ、テストデータを配置します。

Next, create a folder called Training Data, and another called Testing Data. In each folder, create subfolders using your labels as names. Then sort the images into the appropriate subfolders for each data set.

f:id:shu223:20180606071547p:plain

オープンなデータセット

ちなみに独自のデータセットを作成するのは非常に大変ですが、公開されているものもたくさんあります。

Mojaveを入れたら、このあたりのデータからいろいろなモデルをつくって試してみたいなと思っています。

こちらもどうぞ

shu223.hatenablog.com


  1. なお、本記事はNDAに配慮し、Xcode 10やiOS 12のスクショは使わず、公開情報のみで構成しています。

  2. High SierraXcode 10を入れて試してみましたが、import CreateMLUIでエラーになりました。

[iOS 12]Siri Shortcutsの最小実装 - NSUserActivity編

$
0
0

先日のWWDC18で発表された、iOS 12の新機能 "Siri Shortcuts"。「よくやる手順を声で呼び出せる」というのはもちろん嬉しいことですが、それよりも、

「ロックスクリーンから呼び出せる」

というところに、プラットフォームの制約の中で取捨選択するしかないいちアプリ開発者としては圧倒的魅力を感じざるを得ません。

f:id:shu223:20180613205618p:plain

「何がどこまでできるのか、どう実装するのか」を掴むべく、まずはその最小実装を確認してみました。

ちなみに参考資料はWWDC 2018のセッション番号211「Introduction to Siri Shortcuts」とサンプルコード「SoupChef」です。1

実装方法は2通り

Siri Shortcutsの実装方法としては、以下の2種類があります。

  • NSUserActivityを利用する方法
  • Intentsを利用する方法

本記事では、タイトル通り、NSUserActivityを用いたSiri Shortcutsの最小実装だけを紹介します。

Appleのサンプル「SoupChef」は両方の実装が入っており、それはそれでありがたいのですが、初めて挑む人にはどのコードがどっち用なのか、たとえばIntentsを使わない場合はどれを省けるのかといったことがわかりづらいと思うので、そのあたりを本記事で紐解ければと。

3ステップ

NSUserActivityを用いたSiri Shortcutsの実装は、次の3つの手順で行います。

  1. ショートカットを定義する
  2. ショートカットを提供する(donate) 2
  3. ショートカットをハンドルする

「アプリの画面Bを開く」というショートカットをSiri Shortcutsを実現してみます。

1. ショートカットを定義する

Info.plistに次のようにNSUserActivityTypesを定義します。

<key>NSUserActivityTypes</key><array><string>com.myapp.name.my-activity-type</string></array>

2. ショートカットを提供する

Intentsをインポートして、

import Intents

次のようにNSUserActivityを用意します。

extensionNSUserActivity {
    
    publicstaticletmyActivityType="com.myapp.name.my-activity-type"publicstaticvarmyActivity:NSUserActivity {
        letuserActivity= NSUserActivity(activityType:myActivityType)
        
        userActivity.isEligibleForSearch =true
        userActivity.isEligibleForPrediction =true
        userActivity.title ="My First Activity"
        userActivity.suggestedInvocationPhrase ="Let's do it"return userActivity
    }
}

一見複雑に見えますが、Siri Shortcutsに関係するポイントとしては、

  • isEligibleForPredictionプロパティにtrueをセットする
  • suggestedInvocationPhraseプロパティをセットする
    • ここにセットしたフレーズがショートカットの音声コマンドをユーザーに録音してもらう画面でサジェストされる

これぐらいです。

Appleのサンプルには、次のようにCSSearchableItemAttributeSetを作成してcontentAttributeSetにセットする実装も入っていますが、

// 省略可letattributes= CSSearchableItemAttributeSet(itemContentType:"hoge")
attributes.thumbnailData = UIImage(named:"filename")!.pngData()
attributes.keywords = ["foo", "bar"]
attributes.displayName ="My First Activity"
attributes.contentDescription ="Subtitle"
userActivity.contentAttributeSet = attributes

私が試したところではSiri Shortcutsを行うだけであれば省略可能でした3。検索窓(Spotlight)からのテキストによる検索にも対応させたい場合に必要なのではないでしょうか。

作成したNSUserActivityオブジェクトを、ショートカットを提供するUIViewControllleruserActivityプロパティ(正確にはUIResponderのプロパティ)にセットします。

userActivity = NSUserActivity.myActivity

ここでもAppleのサンプルでは次のようにupdateUserActivityState(_)をオーバーライドしてNSUserActivityaddUserInfoEntries(from:)メソッドでuserInfoのデータを供給する実装が入っていましたが、これもなくても動作しました。

// 省略可overridefuncupdateUserActivityState(_ activity:NSUserActivity) {
    letuserInfo:[String: Any]=  [NSUserActivity.ActivityKeys.menuItems:menuItems.map { $0.itemNameKey },
                                         NSUserActivity.ActivityKeys.segueId:"Soup Menu"]

    activity.addUserInfoEntries(from:userInfo)
}

ショートカットでアプリが起動する際に、アプリの状態を復元するために必要なデータ(userInfo)がある場合に実装すべきものと思われます。

なお、ここに出てくるNSUserActivityCSSearchableItemAttributeSetが初見の方は、「iOS 9 の新機能のサンプルコード集」の「Search APIs」サンプルを実行してみつつコードを読んでみると非常にわかりやすいです。NSUserActivity を使うものと、Core Spotlight を使うものの2種類が実装してあり、コードがシンプルなのでどのプロパティが何に対応してるのかがわかりやすいです。

3. ショートカットをハンドルする

ショートカットが呼び出されてアプリが起動する際、UIApplicationDelegateapplication(_:continue:restorationHandler:)が呼び出されるので、そこで渡されてくるアクティビティ(NSUserActivity)をハンドルします。

funcapplication(_ application:UIApplication, continue userActivity:NSUserActivity, restorationHandler:@escaping ([UIUserActivityRestoring]?) ->Void) ->Bool {
    
    if userActivity.activityType == NSUserActivity.myActivityType {
        // Restore state for userActivity and userInfoguardletwindow= window,
            letrootViewController= window.rootViewController as? UINavigationController,
            letvc= rootViewController.viewControllers.first as? ViewController else {
                os_log("Failed to access ViewController.")
                returnfalse
        }
        vc.performSegue(withIdentifier:"B", sender:nil)
        returntrue
    }
    
    returnfalse
}

ここではactivityTypeでどのアクティビティかを判定し、あとは愚直にperformSegueで画面Bに遷移させているだけです。

完成品の挙動

NDA期間中のため完成品の挙動をキャプチャしてアップすることができないのですが、

  • 設定から当該Siri Shortcutを登録
  • ロックスクリーンから登録したフレーズで呼び出す

これでアプリが起動し、画面Bまで自動的に遷移しました。

アプリはバックグラウンドで生きている必要があるのか?

気になったのが、UIViewControlleruserActivityプロパティに当該NSUserActivityオブジェクトをセットした点です。これってこのView Controllerがショートカットのdonatorであり、アプリが生きてないと呼び出せないのか?と。

というわけでアプリをkillしてもNSUserActivityベースのSiri Shortcutは動作するか試してみました。

結果 → 動作しました。

良かったです。

次回

  • Intentsを用いる場合の最小実装
  • 両者をどう使い分けるか
  • Siri Shortcutsで呼び出せない機能はたとえばどんなものがある?

といったあたりについて書きます。(書けたらいいなと思っています)


  1. 本記事はNDAに配慮し、Xcode 10やiOS 12のスクショは使わず、公開情報のみで構成しています。

  2. 「機能を提供する」ということをiOSで表現する場合にはよく"provide"という動詞が使われることが多い気がします。ここでAppleがあえて「寄付する」「寄贈する」といった意味の"donate"を利用しているのはどういう気持ちがこもっているのでしょう?

  3. このへん、キャッシュが残るような挙動があり、動作検証結果に100%確信がありません。

アメリカ生活のふりかえり 2018年5月〜6月

$
0
0

サンフランシスコの会社で正社員として働きつつ1、日本でフリーランスとして働く二拠点生活を送っています。

今年からまた日本の住民票を戻したので、アメリカにいる期間の方が短くなります2。もうちょっとしたら家庭の事情によりさらに行く回数が減ることになりそうなので、自分にとって希少になりつつあるアメリカ滞在をなんとなく消化してしまわないよう、何をやったか/何を得たかを中心にふりかえりメモを書いておこうと思います。

やったこと

Fyusion勤務

  • とある画像処理ロジックを組んだ
    • 処理自体はCIFilterにあったので、自前でMetalシェーダを書くことはせず、MetalのパイプラインにCore Imageの処理を組み込むかたちで実装
    • このへんのMetalと他のフレームワークとの連携は本を書いたときにちゃんとドキュメントやWWDCセッションスライドを読んでおいた知見が活用できた
  • その他諸々、この数ヶ月の間に得たMetalの知見を活かした貢献ができた
  • 同僚の家に遊びに行って衝撃を受けた

f:id:shu223:20180626114308j:plain

(これまでタワーマンション的なものに興味がなかったが考えを改めた)

  • 朝から開いてる店が多く、ほぼ毎日早朝にカフェへ行き、1〜2時間仕事以外のコードを書き、それから出社していた
  • 退社後(18時ぐらいにオフィスを出る)はコードを書くウィルパワーは枯渇してるので、ブログを書いたり、メッセージやメールの返信等のタスクをこなしたり
  • サンフランシスコならではの生活とはいえないが、有意義に時間を使えたと思う。

Boston旅行 / MIT見学

  • ボストン/ケンブリッジ
    • アメリカは広いので知り合いがいるときに行っておきたい
    • 期限が切れそうなマイルを消化したかった
  • 連休+有給で5日間ほど
  • MIT見学させてもらった。最高。
    • 公開情報ではないおそれがあるので、いろいろと見せていただいた研究内容については書けない。。

f:id:shu223:20180626115114j:plain

  • シェアサイクルとUber水上タクシーで街を散策しつつ、手頃なカフェを見つけては勉強したりブログ書いたり。完全に有意義だった。

WWDC(の周辺に)参戦

  • 周辺のカフェで自主学習。いろいろブログ記事書いた(後述)
  • AltConfのセッション、おもしろいのがたくさんあった

滞在中に書いた記事

意識してたくさんアウトプットするようにした。

自分のブログ

shu223.hatenablog.com

shu223.hatenablog.com

note

note.mu

note.mu

note.mu

note.mu

note.mu

Qiita

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

滞在中に公開した/メンテしたOSS

github.com

  • サンプルいろいろ追加

github.com

github.com

github.com

github.com

  • マイナーアップデート

その他

  • 現地で働いている有志の人たちと、「2時間でIoTガジェットをつくる」プロジェクトをやった

    • 2時間でフルスクラッチでつくるわけじゃなく、顔を合わせて作業できる時間がそれだけしかなかったので、それまでにファーム/ハード(筐体&メカ)/アプリケーションのそれぞれのパートを準備してきて、会うときにがっちゃんこしたという話
    • 会ってすぐ(初対面)にアプリとハードの連結動作はうまくいき、細かい動きのチューニング含めて1時間もかからずに理想のかたちになった
    • ひさびさにBLEをさわる機会になってよかった。GATTの定義とか、ハードの方々と連携する勘所を思い出せた
  • このサンフランシスコ滞在中に連絡くれて会いに行った人の会社の仕事を最近リモートでやった

    • 上に書いたAltConfで再会した人の会社とはまた別
    • きっかけはGitHubのコード

  • Samplerシリーズの新作(iOS-12-Samplerではない)をつくり始めた
  • 次回技術書典に向けた執筆もほんのちょっとだけ手を付けた

まとめ

こうして振り返ってみると、1ヶ月の滞在としては濃密に過ごせたなと。二拠点生活移動のオーバーヘッドがあったり住居費が2倍かかったり34ともったいない点もありますが、気持ちが切り替わって時間を有意義に過ごせるというメリットを感じます。次は日本でのフリーランス生活をがんばります(がんばってます)。


  1. ビザはH-1Bです。

  2. この場合、確定申告は両方でやることになります。

  3. いま気付きましたが、ボストンにいる間は「東京の家賃+サンフランシスコの宿代+ボストンの宿代」、サンノゼにいる間は「東京の家賃+サンフランシスコの宿代+サンノゼの宿代」と、2倍どころか3倍かかってました

  4. 飛行機代は会社持ち。

[iOS 12]Network FrameworkでUDPソケット通信

$
0
0

iOS 12で新規追加されたNetwork Frameworkを使って、UDPによるソケット通信を実装してみました。

以前だとCFSocketというCore FoundationのクラスでC言語ベースで実装する必要があったところが、Networkフレームワークの登場によりSwiftでSwiftyに書けるようになります。

受信側の実装

NWListenerというクラスを使って、UDPのListenerを実装します。

// 定数letnetworkType="_networkplayground._udp."letnetworkDomain="local"
privatefuncstartListener(name:String) {
    letudpParams= NWParameters.udp
    guardletlistener= try! NWListener(parameters:udpParams) else { fatalError() }
    
    listener.service = NWListener.Service(name:name, type:networkType)

    letlistnerQueue= DispatchQueue(label:"com.shu223.NetworkPlayground.listener")
    
    // 新しいコネクション受診時の処理
    listener.newConnectionHandler = { [unowned self] (connection:NWConnection) in
        connection.start(queue:listnerQueue)
        self.receive(on:connection)
    }
    
    // Listener開始
    listener.start(queue:listnerQueue)
    print("Start Listening as \(listener.service!.name)")
}

privatefuncreceive(on connection:NWConnection) {
    print("receive on connection: \(connection)")
    connection.receive { (data:Data?, contentContext:NWConnection.ContentContext?, aBool:Bool, error:NWError?) inifletdata= data, letmessage= String(data:data, encoding: .utf8) {
            print("Received Message: \(message)")
        }

        ifleterror= error {
            print(error)
        } else {
            // エラーがなければこのメソッドを再帰的に呼ぶself.receive(on:connection)
        }
    }   
}

送信側の実装

NWConnectionというクラスを利用して、UDPでデータ送信のための準備を行います。(Connectionとは言ってるものの、UDPなのでTCPとは違ってハンドシェイクを行っての接続の確立、みたいなことはしない)

privatevarconnection:NWConnection!privatefuncstartConnection(to name:String) {
    letudpParams= NWParameters.udp
    // 送信先エンドポイントletendpoint= NWEndpoint.service(name:name, type:networkType, domain:networkDomain, interface:nil)
    connection = NWConnection(to:endpoint, using:udpParams)
    
    connection.stateUpdateHandler = { (state:NWConnection.State) inguard state != .ready else { return }
        print("connection is ready")

        // do something...
    }
    
    // コネクション開始letconnectionQueue= DispatchQueue(label:"com.shu223.NetworkPlayground.sender")
    connection.start(queue:connectionQueue)
}

funcsend(message:String) {
    letdata= message.data(using: .utf8)
    
    // 送信完了時の処理letcompletion= NWConnection.SendCompletion.contentProcessed { (error:NWError?) in
        print("送信完了")
    }

    // 送信
    connection.send(content:data, completion:completion)
}

サービスを探索する

接続相手を見つけるため、Listenerがアドバタイズしているであろうサービス(NWListener.Service)を探索します。

初期化
letnetServiceBrowser= NetServiceBrowser()
NetServiceBrowserDelegateを実装
  • すべてoptional
  • とりいそぎ動作確認したいだけであれば、netServiceBrowserWillSearch(_:)(探索スタートする前に呼ばれるのでちゃんと動いてることを確認できる)と、netServiceBrowser(_:didFind:moreComing:)(サービス発見したときに呼ばれる)を最低限実装しておけばOK
extensionViewController:NetServiceBrowserDelegate {
    // 探索スタートする前に呼ばれるfuncnetServiceBrowserWillSearch(_ browser:NetServiceBrowser) {
    }

    // サービスを発見したら呼ばれるfuncnetServiceBrowser(_ browser:NetServiceBrowser, didFind service:NetService, moreComing:Bool) {
        // 自分以外であれば送信開始guard service.name != myName else { return }
        startConnection(to:service.name)
    }
    
    funcnetServiceBrowser(_ browser:NetServiceBrowser, didNotSearch errorDict:[String : NSNumber]) {
    }
    
    funcnetServiceBrowser(_ browser:NetServiceBrowser, didFindDomain domainString:String, moreComing:Bool) {
    }
    
    funcnetServiceBrowserDidStopSearch(_ browser:NetServiceBrowser) {
    }
    
    funcnetServiceBrowser(_ browser:NetServiceBrowser, didRemove service:NetService, moreComing:Bool) {
    }
    
    funcnetServiceBrowser(_ browser:NetServiceBrowser, didRemoveDomain domainString:String, moreComing:Bool) {
    }
}
探索開始
netServiceBrowser.delegate =self
netServiceBrowser.searchForServices(ofType:networkType, inDomain:networkDomain)

その他

  • 受信・送信両方の機能を1つのアプリに持たせる

    • つまりどちらもがListenerになり、どちらもが送信側になりうる
  • アプリ起動時に受信を開始

startListener(name:myName)
  • 送信ボタン
@IBActionfuncsendBtnTapped(_ sender:UIButton) {
    send(message:"hoge")
}

実行

  • 2台のiOSバイスを用意する
  • 同じネットワークに接続する
  • 同アプリを実行

以上で両デバイスで受信準備が完了し、相手を見つけて送信準備も完了(NWConnection.State.ready)したら、送信ボタンを押すたびに相手にメッセージが飛ぶようになります。

Special Thanks

本実装はSwift Islandというカンファレンスでの Roy Marmelstein氏のワークショップで学んだ実装を自分なりに咀嚼して(復習・覚書として)書き直したものです。

WWDC18の当該セッションもまだ見てなくて、たぶんワークショップに参加しなかったら自分では当面さわらなかったんじゃないかと思うフレームワークなのですが、こうして自分でやってみると(CF時代の不慣れなC言語による難しさ成分が取り除かれているため)意外と扱いやすいことがわかってよかったです。もうちょっとネットワークプロトコルの気持ちがわかりたいなと思ってた頃なので、引き続きさわっていきたい所存です。


オランダの小さな島で開催されたカンファレンス「Swift Island」に参加した話 #swiftisland2018

$
0
0

今月の初旬、「Swift Island 2018」というSwiftおよびiOSをテーマとするカンファレンスに参加してきました。テッセル島というオランダにある小さな島が会場で、

f:id:shu223:20180723144557j:plain:w500

  • カンファレンス会場にバンガローがあり、基本的に全員がそこに泊まる
    • 部屋は別々
    • チケット代に宿代・食事代も含まれている
  • よくある「スピーカーの話を聴く」聴講型ではなく、「全員が手を動かす」ワークショップ型

というフォーマットで、今までに参加したどのカンファレンスとも違った良さがありました。

ワークショップ主体の少人数制・合宿型カンファレンス

冒頭にもちらっと書きましたが、カンファレンス名に"Island"とあり、一見「島での開催」が本カンファレンス最大の特徴っぽい感じがしますが、実際に参加してみての感想としては、

  • チケット販売枚数は最大50(ソールドアウトだったので、つまり参加者は50人)
  • すべてのセッションが参加者10人ちょっとの少人数ワークショップ形式で、全員が手を動かす

という点が本カンファレンス最大の個性かつ特長であると感じました。日本のSwift/iOSカンファレンスであるtry! SwiftやiOSDCは800人とかの規模であることを考えると、50人というのは非常にコンパクトです。トータル3日も一緒にいれば、全員の顔ぐらいはなんとなく覚えられそうなレベル。

そして、午前1コマ、午後2コマの1日3コマ × 2日間のワークショップがあり、同じ1コマの時間帯に4つのワークショップが平行開催されていて、1つあたりのワークショップの参加者は12〜13人ほど。全員が手を動かします。

そして斬新だったのは同じワークショップは繰り返し開催される点で、このおかげで人数的にあぶれたり、参加したいワークショップがかぶったりしてても別のコマで参加できるので、基本的には出たいワークショップにはすべて参加することができました。

こういうワークショップベースのカンファレンスは今まで経験したことなかったのですが、やはり聴いてなんとなくわかって気になるのと、自分で実際に一度書いてみるのとでは全然「自分のものにした感」が違う、と感じました。

「(都市から多少隔離された)島での合宿型」という形式も、50人というグループの結束が高まる/非日常感によりいつもと違う分野で手を動かすぞという気持ちを盛り上げてくれる、といった相乗効果があったと思います。

どのレイヤで手を動かすのか

参加者全員が手を動かすといっても、その方法、レベル感は講師によって様々で、例を挙げると、

  • Swiftの新機能

    • iOSのプロジェクトと、テストが用意されている
    • そのままだとテストがコケる
    • そのテストが通るように、iOS側のコードを書いていく
    • その際、Swiftの新機能Mirrorとかを使う
  • 機械学習

    • Turi Createを使ったモデルをトレーニングするコードがJupyter Notebook形式で用意されている
    • それを順次実行して学習を回してみる(ここで各ステップについてちょっと解説が入る)
    • できたCoreMLモデルをiOSに組み込む
  • Siri Shortcut

    • 前で講師が解説 → さぁみんなもやってみよう
    • を手頃なチャンクごとに繰り返す
    • 書籍みたいなテキストが用意されていて、ついていけなければ復習もできる
  • Network, Natural Language

    • フレームワーク群を使うiOSアプリケーションのスケルトンプロジェクトみたいなものが用意されている
    • 作業順とヒントが示されていて、各自で実装していく(例: Network FrameworkでUDPによるソケット通信をやるためのクラスとメソッドの定義だけ用意されていて、その中身を実装していく)

・・・と千差万別でした。どの講師の方のサンプル/教材も「どうやったらこのテーマをうまく学んでもらえるか」を考えて推敲してあるなぁと感心しました。

f:id:shu223:20180704161814j:plain:w500

(Siri Shortcutのワークショップ)

f:id:shu223:20180707041636j:plain:w500

機械学習のワークショップ)

参加者同士のコミュニケーション

全員が基本的にはワークショップ開始前日に到着するのですが、その「前夜」にもう既に参加者同士の輪が出来始めていて、自分はそこに飛び込めず、「やばい、このままずっとぼっちで過ごすのか・・・」と一時不安にもなりましたが、朝・昼・晩と食事がついていて、大きなティピーテント内にいくつか置かれたテーブルで基本的には相席になるので、そこで絶対に話す機会はあるし、

f:id:shu223:20180704124146j:plain:w600

ワークショップでも隣同士で話したり、Pub Quizといったチームで挑むイベントがあったりで、コミュニケーションのきっかけに困ることはありませんでした。

f:id:shu223:20180704220302j:plain:w600

ちなみに他のヨーロッパの国々から来てる人はいたものの、飛行機で10時間以上かかるところからわざわざ来たという人はいなくて、ヨーロッパ外からの参加は僕だけだったかもしれません。そのあたりで珍しがってもらえたというのもコミュニケーションの一助になった気がします。

テッセル島

会場のテッセル島は首都アムステルダムからものすごく遠いというわけではないのですが、電車と船と予約制バスを乗り継いで行くので、なんだかんだで半日かかります。

人より羊が多いらしく、とにかく何もありません。

f:id:shu223:20180703154846j:plain:w600

島での滞在中は自転車をレンタルして、朝とか夜とかにいろいろ周りました。灯台を目指してみたり、対岸の海の方に行ったり。

f:id:shu223:20180706094346j:plain:w600

f:id:shu223:20180723122525j:plain:w600

好みがあるとは思いますが、僕はこういうところをのんびりサイクリングするのは大好きだし、車もほとんど走ってないので会話もじっくりできて、最高でした。

アムステルダム

今回テッセルには4泊したのですが、オランダははじめてだったので、その前後でアムステルダムに合計6泊しました。

マリファナが合法、ビザが取りやすい、ぐらいの前知識しかなくて、僕はそれらに興味がなかったので、実はとくにワクワクすることもなく現地に赴いたのですが、行ってみれば移住したいと思ってしまうほどに気に入りました。

  • アムステルダムは「運河が張り巡らされている港町」
    • もともと海が近くて川が流れてる街が好きな自分にはどストライク。
    • 運河をつなぐ橋の袂には大抵カフェがあってみんな屋外でビール飲んでる。

f:id:shu223:20180630125307j:plain:w600

  • オランダ全体が自転車社会

    • 自転車専用のレーンが整備されててあらゆる場所に自転車を止められる
    • アムステルダムも街が大きくなくて自転車で事足りる
    • (ペーパードライバーな自分は車社会のアメリカでは生きづらかった…)
  • 気候も良い

    • 暑すぎない、それでいてちゃんと暑い夏 1
    • 毎日快晴(※これはたまたまそうだったのかもしれない)

まぁ、しばらく滞在しているといくつか好きではない面も見えてきましたが。。いずれ1ヶ月とかアパート借りて執筆やリモートワーク、みたいな感じでもうちょっと長めに過ごせたらいいなと思います。

お金の話

  • チケット代+自転車レンタル+テッセル延泊+テッセル移動・・・合計€1000ぐらい 2
  • 東京 <->アムステルダム往復航空券・・・$1340 3
  • アムステルダム6泊(3泊 + 1泊 + 2泊。全部Airbnb・・・合計$950ぐらい
    • 後で気付いたが、1泊とか2泊ならアムステルダムの場合はホテルの方がお得。チェックインも楽だし。
  • モバイルWi-Fiルータ、SIM・・・合計20,000円ぐらい
    • 空港でSIM買えたのでWiFiルータいらなかった。というかアムステルダムでもテッセルでもほとんど繋がらなくて、使えなかった。。
    • SIMは快適でした
  • 食費・・・数えてないが、それなりにかかってるはず

ユーロとドルと円が混じってますがざっくり35万〜40万円といった感じでしょうか。目を背けたくなる金額ですが、しかし、海外の知らない土地に行って、新しい人達と出会って・・・というのは自分にとって重要な人生の醍醐味で、ここをケチって何のために稼いでるのか、というところだし、新しい技術を学ぶきっかけというのは(腰が重い自分にとっては特に)いつでも価値あることなので、100%行ってよかったと思えます。4

まとめ

Swift Island 2018について書きました。要点をまとめると、

  • 少人数・ワークショップ主体のカンファレンス形式がとてもよかった
  • アムステルダムいいところだった
  • お金はかかるけど、たまにはこうして海外カンファレンスに参加するのはいいものだ

といったところです。またチャンスがあれば参加したいと思います。

f:id:shu223:20180707040820j:plain

こちらもどうぞ:これまでの海外カンファレンス参加記事

note.mu

d.hatena.ne.jp

d.hatena.ne.jp


  1. サンフランシスコみたいな「涼しい夏」は夏を過ごした感じがしない。。

  2. 海外のカンファレンスは高いのです。というか日本のが安い

  3. 夏の繁忙期なのでちょっと高い

  4. ちなみにオランダ滞在中にリモートワークも少ししたのですが、旅費の半分ぐらいは相殺できていると思います。

iOS 12のPortrait Matteがすごい/ #iOSDC 2018で登壇します

$
0
0

iOS 12の新機能"Portrait Matte"(ポートレート・マット)の概要と、実装方法を紹介します。1

f:id:shu223:20180822200133p:plain:w393

深度マップとセグメンテーション

昨今のiPhoneではデュアルカメラ(iPhone 7Plus, 8 Plus, Xの背面に搭載)、あるいはTrueDepthカメラ(iPhone Xの前面に搭載)から深度マップを作成し、奥行きを知ることができるようになっています。

深度マップは、

  • AR表現における回り込み(オクルージョン)
  • モノや人物の背景を差し替える 2

といった用途に用いられます。

どちらの例も要は人物やモノの「領域」を検出して分割する(セグメンテーション)ところがキーで、深度マップはそのセグメンテーションにおけるマスクとして有用なわけです。

f:id:shu223:20180822190535p:plain:w600

(撮影した画像(左)と深度マップ(右))

iOS 12の新機能 "Portrait Matte"

深度マップ関連APIiOS 11から追加されたわけですが、iOS 12では新たに"Portrait Matte"なる新機能が追加されました。"Portrait Effect Matte"とも呼ばれます。

f:id:shu223:20180822200059p:plain:w600

(従来の深度マップ(左)とPortrait Matte(右))

聞き慣れない用語ですが、たぶんApple独自用語です。WWDC18の"Creating Photo and Video Effects Using Depth"から、「Portrait Matteとはなにか」という説明をしている部分を引用してみます。

so what is a portrait matte? A portrait matte is a segmentation from foreground to background and what this means precisely is that you have a mask which is 1.

0 in the background and you get soft and continuous values in between.

つまり、背景と前景の分離に用いるセグメンテーションに特化したフォーマットで、

とスッパリ分かれており、輪郭部分の髪の毛のような詳細もその間の連続値で表現される、というもののようです。

f:id:shu223:20180822200133p:plain:w393

True Depthな前面カメラからだけではなく、背面カメラからも取得できるようです。

It is available for both the front and the rear facing camera.

ただし、静止画のみ(動画では取得不可)かつ人間が写っている場合だけ取得可能です。

It is available to you with portrait still images and at the moment only when there are people in the scene.

Portrait Matteの取得方法

Portrait Matteの取得方法は従来の深度データ(AVDepthData)の取得方法と非常に似ています。

CGImageSourceを作成したら、CGImageSourceCopyAuxiliaryDataInfoAtIndexkCGImageAuxiliaryDataTypePortraitEffectsMatteを指定してAuxiliaryデータを取得すれば、

guardletinfo= CGImageSourceCopyAuxiliaryDataInfoAtIndex(source, 0, kCGImageAuxiliaryDataTypePortraitEffectsMatte) as? [String :AnyObject] else { return }

それをそのままAVPortraitEffectsMatteのイニシャライザに渡せます。

letmatte= AVPortraitEffectsMatte(fromDictionaryRepresentation:info)

AVPortraitEffectsMatteCVPixelBuffer型のmattingImageプロパティを持っており、そこからセグメンテーション用のマスクとしてCore ImageなりMetalなりで用いることができます。

varmattingImage:CVPixelBuffer { get }

iOSDCでiOSにおける深度データの諸々について話します

"Depth in Depth"というタイトルで、iOSDC 2018で登壇します。

Depth in Depth by 堤 修一 | プロポーザル | iOSDC Japan 2018 - fortee.jp

概要:

原始のiPhoneからカメラは搭載されていましたが、深度センサが搭載されたのは比較的最近のことです。カメラやGPSが、デジタルの世界と我々が生きる現実世界を繋ぐ重要な役割を担い、アプリ開発者に多くの創造性を与えてくれたのと同様に、「奥行き」がわかるようになったというのはアプリ開発の次元がひとつ増えたようなものです。本トークではiOSでの深度の扱いについて、取得方法だけではなく、細かいパラメータの意味やMetalでの処理まで詳解します。

まだ発表内容を遂行しているところですが、発表のゴールとしては次のようなものを考えています。

  • iOSで取得できる深度データにも種類があること、またそれぞれどういうものなのかがわかる
  • 深度データ取得の(ハードウェア的な)しくみがわかる
  • iOSにおける深度データを取得する実装方法がわかる
  • 取得した深度データを使い、背景入れ替えや3Dマッピングといった応用実装ができる

ニッチな内容ですが、iOSの深度の取り扱いについてのまとまった話を日本語で聞けるレアな内容だとも思いますので、興味のある方はぜひ聞きに来てください!(上のリンクから⭐ボタンを押しておくとタイムテーブルに反映されます。たぶん)


  1. 本記事はNDAに配慮し、Xcode 10やiOS 12のスクショは使わず、公開情報のみで構成しています。

  2. グリーンバックのように彩度をキーとして背景合成を行う技術はクロマキー合成と呼ばれる

ARKit 2.0の画像トラッキングとARKit 1.5の画像検出の違い

$
0
0

ARKit 2.0では、「画像トラッキング」という新機能が加わりました。既知の2次元画像を検出・トラッキングできるので、ポスター等の現実世界に存在する2D画像を基盤にしてAR体験を開始することができるようになる、というものです。これを聞いて「あれ、その機能、既になかったっけ」と思った方もいたのではないでしょうか。

その既視感はある意味では正しく、ARKit 1.5で既に「画像検出」という機能が追加されています。

では、これらはどう違うのでしょうか?ARKit 1.5の画像検出機能を強化したものが2.0の画像トラッキングで、リプレースされたのでしょうか。それとも別々の機能として共存しているのでしょうか。

結論としては後者で、それぞれ強みを持つ別々の機能として共存しています。

コンフィギュレーションの違い

まず実装面でみると、ARKit 1.5で搭載された画像検出は、検出対象とするリファレンス画像をARKit 1.0から存在するコンフィギュレーションであるARWorldTrackingConfiguration(平面検出を行うのもこれ)の検出対象の一種として指定することで実装します。

letconfiguration= ARWorldTrackingConfiguration()
configuration.detectionImages = [referenceImage]

一方ARKit 2.0で追加された画像トラッキングは、新たなコンフィギュレーションARImageTrackingConfigurationを使用します。

letconfiguration= ARImageTrackingConfiguration()
configuration.trackingImages = [referenceImage]

どちらの実装もリファレンス画像のセットをコンフィギュレーションのプロパティに渡すところは共通で、コンフィギュレーションだけが違っています。

f:id:shu223:20180825223341p:plain

実は、ここに両者の違いが大きく表れています。

ARWorldTrackingConfigurationは、現実世界を検出するコンフィギュレーションです。現実世界の面(Surface)を検出し、そこにある画像やオブジェクトも検出します。

一方でARImageTrackingConfigurationは、既知の2D画像だけをトラッキングします。その周囲の面は検出しません。

パフォーマンスの違い

上のコンフィギュレーションの違いにより、パフォーマンスに大きな差が出てきます。ARWorldTrackingConfigurationはカメラに映る世界の面を全て見ているのでパフォーマンスコストが高く、対象画像は静止している必要があります。

一方でARImageTrackingConfigurationは対象画像しか見ないので60fpsでその画像の位置と向きを推定します。そして対象画像が移動しても追従します。

また、同じ理由から、一度に復数の対象画像を検出する場合も、ARImageTrackingConfigurationの方がよりより多くの画像をより確実に処理できます。

実際に同じデバイスで両コンフィギュレーションによる画像検出/トラッキングを試してみると(NDA期間中につきスクリーンキャプチャ動画は載せられませんが)、次のような結果になりました。

  • ARWorldTrackingConfiguration
    • trackingStatenormalになるまでが遅い
    • 検出した画像の位置・向きの更新が遅い
  • ARImageTrackingConfiguration
    • 一瞬でtrackingStatenormalになる
    • 検出した画像の位置・向きを毎フレーム正確に追従する

それぞれのユースケース

画像への追従性、パフォーマンス面だけで見ると画像トラッキングの方が圧倒的に利点がありそうですが、こちらはワールド自体は見ていないので、たとえばその対象画像がカメラの視野から外れた場合に、その画像に仮想コンテンツを固定し続けることができません。一方で(ARWorldTrackingConfiguration)の画像検出では、対象画像が見えなくなった後でもワールド空間におけるそのコンテンツの位置を追跡し続けることができます。

画像検出は、美術館の絵画や映画のポスターのような静的画像にARコンテンツを連携させるようなケースに適しているとされ、また画像トラッキングは、卓上でのカードゲームやボードゲームのように移動する物体上の画像に対してARコンテンツを連携させるようなケースに適しているとされています。1

iOSDCで「深度(デプス)」について話しました #iosdc

$
0
0

8/30〜9/2の4日間、900人規模で開催されたカンファレンスiOSDC 2018にて、「Depth in Depth」というタイトルで、iOSにおける深度データにまつわる諸々について30分の枠でお話させていただきました。

speakerdeck.com

タイトルの"in Depth"というのはWWDCのセッションや海外技術書等ではアドバンスト的な技術解説でよく用いられるタイトルですが、本セッションの難度としてはどちらかというと「デプス入門」の方が適切です。深度とは何か、どう嬉しいのか、どういうしくみで計測されてるのか、といった基礎から解説しておりますので深度についてまったく知らない方にも参考になるかと思います。1

またトーク内ではiOSAPI面に関してはサラッと流し、深度の取り扱いについて本質的・汎用的な部分の解説や、デモに時間を割くようにつとめました。iOSAPIの細かい話についてはトークよりもブログ記事の方が向いてると思うので、また別記事にでも書いていきます。

(2018.9.27追記)動画

iOSDC公式チャンネルに動画が公開されていました。

www.youtube.com

デモとかアニメーションを多用しているのでスライドよりも動画の方がおすすめです。

デモ

トーク内では全4回のデモを入れました。最初の人物切り抜きのデモに関しては@niwatako氏が動画をツイートしてくれていたので、貼らせていただきます。

客席に座っていた人に壇上に出てもらい、その場で撮影を行い、深度による切り抜きを行う、というデモです。壇上に上がってもらったのは仲のいいPEAKS永野さんですが、仕込みではなく、本当に彼を撮影し、切り抜きを試したのはこのときが初です。2

その他セッション中のツイートはこちらにまとめられています:

togetter.com

サンプルコード

ひとつのアプリケーションとして整理して公開する予定です。が、後述する理由もありなかなか時間がとれていません。なんとかiOS 12が出るまでには。。

自分にプレッシャーをかける意味でティザーリポジトリだけつくっておきました。

github.com

ここにpushする予定なので気になるみなさまはwatchしておいてください。公開後も、iOSにおける深度データ取り扱いに関するサンプルはここに追加していく予定です。

(2018.9.18追記)サンプル公開しました!

shu223.hatenablog.com

iOSDCの思い出

子供が生まれました!

なんと登壇日の朝、娘が生まれました

f:id:shu223:20180901090822j:plain

登壇の前夜、臨月の妻から破水の連絡がきて、病院に直行しました。助産師さんによると時間がかかりそうとのことだったのでもしかすると発表は辞退するかも3、というタイミングだったのですが、徹夜のお産ののち(僕は手を握っていただけ)朝9時に生まれ、もろもろ見届けたのち無事午後イチの登壇にも間に合ったという。さっそく親孝行な子です👶

今週は仕事を基本的には休ませてもらって(緊急のものはリモートで対応)、妻とてんやわんやしながら初の子育てに励んでいます。

ベストトーク賞3位!

なんと、「Depth in Depth」で、ベストトーク賞3位をいただきました。

f:id:shu223:20180906090232j:plain

1位tarunonさんの「MicroViewControllerで無限にスケールするiOS開発」、2位Kuniwakさんの 「iOSアプリの開発速度を70%高速化したデバッグノウハウ」という、超評判になっていたトークに続いての順位なので、まったくもって信じられない気持ちでした。

僕は勉強会やカンファレンスには多く登壇していますが、トーク力に関してはまったく自信がなく4、こういうプレゼンでの賞をもらうのは初めてなのでめちゃくちゃ嬉しかったです。

全体の感想

日本のiOSエンジニアが集まるお祭りとして最高なiOSDCですが、今年は前述のような状況もあってセッションもあまり聞きに行けず、懇親会にも出られず、さらにその後の打ち上げでもゆっくりできず、という感じでした。が、それでも少しでも参加して「お祭り」の空気を吸えたし、発表ドリブンで深度まわりにも勉強できたし、出産と重なったけど無事登壇できたし、賞までいただけて、今年もiOSDCは楽しかったなと。来年もたぶん生活は落ち着いてはないですが、どうにか参加したい所存です。

素晴らしいカンファレンスを開催してくださった運営チームのみなさま、スポンサーのみなさま、参加者のみなさま、スピーカーのみなさま、発表練習やスライド作成のもくもく会につきあってくれたみなさま、どうもありがとうございました!


  1. CfPの段階では実際に"In Depth"な内容まで踏み込むつもりでいて、Metalを用いて2次元の写真を3次元にマッピングするところまで掘り下げる予定でスライド作成を進めていました。が、30分という時間の中でそこまで掘り下げると全体的に中途半端になりそうなので泣く泣くカットしました。

  2. iOSDCでは動画を撮っているので、壇上に出てこれそうで、動画に残っても大丈夫そうな人に出てもらいました。

  3. 大会委員長の長谷川さんにはその旨を連絡していました。

  4. なので、「トーク下手がしゃべってもおもしろくなる」ように内容を何度も推敲して登壇に臨むようにしてます。

デプス(深度)をiOSで扱う方法を網羅したサンプルコード集「iOS-Depth-Sampler」を公開しました

$
0
0

iOSにおけるデプス(深度)関連APIの実装方法を示すサンプル集「iOS-Depth-Sampler」をオープンソースで公開しました。

github.com

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

今のところ6つのサンプル(後述)が入っています。本記事のタイトル「網羅した」は少し大げさですが、撮影済みの写真からデプスを取得する方法から、リアルタイムに取得する方法、ARKitで取得する方法、フロント/リアカメラ、Disparity / Depth / Portrait Matteといったタイプと相互変換、デプスを利用した背景合成や3D空間へのマッピングといったサンプルも備えています。

f:id:shu223:20180918074109j:plain

(2次元の写真をデプスを利用して3D空間へマッピング

今後iOSにデプス関連の機能が追加されるたびに、サンプルも追加していく予定です。

利用可能なデバイス

デュアルカメラもしくはTrueDepthカメラを持つデバイスを使用してください。 7 Plus, 8 Plus, X, XS, XRをお持ちの方はぜひビルドして遊んでみてください。リア(Dual Camera)とフロント(TrueDepth Camera)でそれぞれサポートしている機能が全然違うので、X or XSが理想です。

利用方法

git cloneしてXcode 10でビルドしてiOS 12端末 1にインストール

以上です。Metalを使用しているのでシミュレータでは動作しない点、ご注意ください。

サンプル一覧

Real-time Depth

リアルタイムにカメラから深度情報を取得し、可視化するサンプルです。

f:id:shu223:20180913012136g:plain

Real-time Dpeth Mask

リアルタイムにカメラから取得した深度情報をマスクとして使用し、背景合成を行うサンプルです。

f:id:shu223:20180913012157g:plain

Depth from Camera Roll

カメラロールにある撮影済みの写真から深度情報を取り出し、可視化するサンプルです。標準のカメラアプリのポートレートモードで撮影した写真を利用できます。

f:id:shu223:20180913012537j:plain

Portrait Matte

Portrait Matte (Portrait Effect Matte)を使用し、背景を除去するサンプルです。ポートレートモードで「人間を撮影」した写真を利用できます。要iOS 12。

f:id:shu223:20180913012548g:plain

カメラはフロント・リアどちらもOKです。

shu223.hatenablog.com

ARKit Depth

ARKitで深度情報を取得し、可視化するサンプルです。

f:id:shu223:20180913012600g:plain

現状、ARKitではARFaceTrackingConfiguration使用時のみ(つまりフェイストラッキングARのときだけ)この方法で(※後で貼るスライド内で説明しています)深度情報を取得できます。

2D image in 3D space

写真(2D)を深度をz値として3D空間にマッピングするサンプルです。

f:id:shu223:20180915110312g:plain

AR occlusion

[WIP] An occlusion sample on ARKit using depth.

そもそもデプスって?

「デプスって何?」「何が嬉しいの?」「どういう仕組みで計測してるの?」といったところは拙スライドもご参照ください。

speakerdeck.com

デモやアニメーションを交えているので、動画の方がおすすめです。

www.youtube.com

付録: iOSで深度データにアクセスする方法のまとめ(書きかけ)

Qiitaにでも書こうとまとめてたのですが、途中になってるので、ここに一旦おいておきます。

PHAssetから深度マップ画像を生成

requestContentEditingInput(with:nil) { (contentEditingInput, info) inguardleturl= contentEditingInput?.fullSizeImageURL else { fatalError() }
    letdepthImage= CIImage(contentsOf:url, options:[CIImageOption.auxiliaryDisparity : true])!...
}

深度データを持つPHAssetだけを取得する

letresultCollections= PHAssetCollection.fetchAssetCollections(
    with: .smartAlbum,
    subtype: .smartAlbumDepthEffect,
    options:nil)
varassets:[PHAsset]= []
resultCollections.enumerateObjects({ collection, index, stop inletresult= PHAsset.fetchAssets(in:collection, options:nil)
    result.enumerateObjects({ asset, index, stop in
        assets.append(asset)
    })
})

PHAssetが持つ深度データからAVDepthData生成

アセットのURLを指定して、CGImageSourceを作成する。

guardletsource= CGImageSourceCreateWithURL(url as CFURL, nil) else { fatalError() }

CGImageSourceCopyAuxiliaryDataInfoAtIndexを使用する

letinfo= CGImageSourceCopyAuxiliaryDataInfoAtIndex(source, 0, kCGImageAuxiliaryDataTypeDisparity) as? [String :AnyObject]
letinfo= CGImageSourceCopyAuxiliaryDataInfoAtIndex(source, 0, kCGImageAuxiliaryDataTypeDepth) as? [String :AnyObject]

ここで得られる辞書型データは次のような情報を持っている。

  • the depth data (CFDataRef) - (kCGImageAuxiliaryDataInfoData),
  • the depth data description (CFDictionary) - (kCGImageAuxiliaryDataInfoDataDescription)
  • metadata (CGImageMetadataRef) - (kCGImageAuxiliaryDataInfoMetadata)

この辞書型データをそのままAVDepthDataのイニシャライザに渡せる。

letdepthData= try! AVDepthData(fromDictionaryRepresentation:info)

CGImageSourceCopyPropertiesから深度に関する情報を取得する

以下のように辿って深度に関する情報を得ることもできる。

guardletsourceProperties= CGImageSourceCopyProperties(source, nil) as? [String:AnyObject] else { fatalError() }
guardletfileContentsProperties= sourceProperties[String(kCGImagePropertyFileContentsDictionary)] as? [String :AnyObject] else { fatalError() }
guardletimages= fileContentsProperties[String(kCGImagePropertyImages)] as? [AnyObject] else { returnnil }
for imageProperties in images {
    guardletauxiliaryDataProperties= imageProperties[String(kCGImagePropertyAuxiliaryData)] as? [[String :AnyObject]] else { continue }
    ...
}

こういう情報が取れる。

["Width": 576, "AuxiliaryDataType": kCGImageAuxiliaryDataTypeDisparity, "Height": 768]

とはいえ深度マップのデータそのものは入っていない。

AVCaptureSynchronizedDataCollectionからデータを取り出す

AVCaptureDataOutputSynchronizerDelegateのdidOutputメソッドの第2引数からAVCaptureSynchronizedDataCollectionオブジェクトが得られる。

funcdataOutputSynchronizer(_ synchronizer:AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection:AVCaptureSynchronizedDataCollection) {

    ifletsyncedDepthData= synchronizedDataCollection.synchronizedData(for:depthDataOutput) as? AVCaptureSynchronizedDepthData, !syncedDepthData.depthDataWasDropped {
        letdepthData= syncedDepthData.depthData
        ...
    }
    
    ifletsyncedVideoData= synchronizedDataCollection.synchronizedData(for:videoDataOutput) as? AVCaptureSynchronizedSampleBufferData, !syncedVideoData.sampleBufferWasDropped {
        letvideoSampleBuffer= syncedVideoData.sampleBuffer
        ...
    }
}

iOS 12のPortrait Matte

letinfo= CGImageSourceCopyAuxiliaryDataInfoAtIndex(self, 0, kCGImageAuxiliaryDataTypePortraitEffectsMatte) as? [String :AnyObject]
letmatte= try! AVPortraitEffectsMatte(fromDictionaryRepresentation:info)

  1. ほとんどのデプスAPIiOS 11から使えるのですが、インパクトのある「Portrait Matte」がiOS 12〜なので、本サンプルはiOS 12以上にしてしまいました。

ARKitの解説書を個人出版しました #技術書典 #技術書典5

$
0
0

ARKitの解説書「実践ARKit」を本日よりBOOTHにて販売開始しました!ARKit 2.0 (iOS 12)・Xcode 10・Swift 4.2対応、全119ページ(製本版は92ページ)。サンプルコードはGitHubよりダウンロード可能です。

shu223.booth.pm

なお、明日開催される技術書典5では製本版+電子版セットで2000円で販売する予定です。だいぶお得です。サークル名は「堤and北」、配置は「う65」です。

techbookfest.org

書籍の紹介

本書は、作りながら学ぶネイティブARKitアプリケーション開発の実践入門書です。

はじめの一歩として3行で書ける最小実装のARから始めて、平面を検出する方法、その平面に仮想オブジェクトを設置する方法、そしてその仮想オブジェクトとインタラクションできるようにする方法・・・と、読み進めるにつれて「作りながら」引き出しが増えていき、最終的にはARKitを用いたメジャーや、空間に絵や文字を描くといった、ARKitならではのアプリケーションの実装ができるよう構成しています。

全92ページ。ARKit 2.0 (iOS 12), Xcode 10, Swift 4.2対応。サンプルコードはGitHubよりダウンロード可能です。

f:id:shu223:20181007153454p:plain

目次

第1章 入門編その1 - 最小実装で体験してみる

  • 1.1 手順1:プロジェクトの準備
  • 1.2 手順2:ViewControllerの実装
  • 1.3 基本クラスの解説

第2章 入門編その2 - 水平面を検出する

  • 2.1 水平面を検出するためのコンフィギュレーション
  • 2.2 平面検出に関するイベントをフックする - ARSessionDelegate
  • 2.3 平面検出に関するイベントをフックする - ARSCNViewDelegate
  • 2.4 検出した平面を可視化する

第3章 入門編その3 - 検出した水平面に仮想オブジェクトを置く

  • 3.1 3Dモデルを読み込む
  • 3.2 仮想オブジェクトとして検出した平面に置く

第4章 ARKit 開発に必須の機能

  • 4.1 トラッキング状態を監視する
  • 4.2 デバッグオプションを利用する
  • 4.3 トラッキング状態をリセットする / 検出済みアンカーを削除する

第5章 平面検出の基礎

  • 5.1 垂直平面の検出
  • 5.2 検出した平面のアラインメントを判別する
  • 5.3 平面ジオメトリの取得
  • ARPlaneGeometry と ARSCNPlaneGeometry

第6章 AR 空間におけるインタラクションを実現する

  • 6.1 ヒットテスト(当たり判定)を行う
  • 6.2 デバイスの移動に対するインタラクション

第7章 AR 体験の永続化と共有

  • 7.1 ARWorldMap
  • 7.2 ワールドマップを取得する
  • 7.3 ワールドマップを永続化・共有する
  • 7.4 ワールドマップからセッションを復元する
  • 7.5 ワールドマップ取得タイミング

第8章 フェイストラッキング

  • 8.1 フェイストラッキングを開始する - ARFaceTrackingConfiguration
  • 8.2 検出した顔のアンカーを取得する - ARFaceAnchor
  • 8.3 顔の動きを可視化する
  • ブレンドシェイプでアニ文字風3Dアバター

第9章 特徴点を利用する

  • 9.1 特徴点を可視化する
  • 9.2 フレームに含まれる特徴点群データ
  • 9.3 ワールドマップに含まれる特徴点群データ

第10章 デプスを利用する

  • 10.1 ARFrameからデプスデータを取得する
  • 10.2 デプスを取得可能なコンフィギュレーション

第11章 ビデオフォーマット

  • 11.1 ARConfiguration.VideoFormat
  • 11.2 ビデオフォーマットを指定する
  • 11.3 使用可能なビデオフォーマット
  • 現行デバイスで使用可能なビデオフォーマット一覧
  • ビデオフォーマットはどう使い分けるのか?

第12章 アプリケーション実装例1: 現実空間の長さを測る

  • 12.1 ARKitにおける座標と現実のスケール
  • 12.2 現実空間における二点間の距離

第13章 アプリケーション実装例2: 空中に絵や文字を描く

  • 13.1 スクリーンの中心座標をワールド座標に変換する
  • 13.2 頂点座標の配列から、線としてのカスタムジオメトリを構成する
  • 13.3 その他の実装のポイント

第14章 アプリケーション実装例3: Core ML + Vision + ARKit

  • 14.1 CoreML・Vision・ARKit連携のポイント

第 15 章 Metal + ARKit

  • 15.1 その1-マテリアルをMetalで描画する
  • 15.2 その2-Metalによるカスタムレンダリング

対象読者

「実践入門書」を謳っている通り、実践を主眼に据えつつあくまでARKit入門者向けです。すでに現場でゴリゴリに触ってる人には物足りないかもしれません。また本書はネイティブiOSアプリ開発の話で、Unityを使ったARKitアプリの開発については書いてないです。

あと、全面的にリライトしたりARKit 2.0対応したりしてますが、「iOS 11 Progamming」で執筆を担当したARKitの章を土台としてますので、そちらを既にご購入の方には重複する部分が多くなってしまうかと思います。目次をよくご確認いただき、ご検討ください。

表紙の話

もともとあった表紙の構想は、ARKitにとって象徴的なシンボルである(と僕は思っている)「あの」飛行機の3Dモデル"ship.scn"を「ちょっと浮いた感じで真ん中あたりにプリントする」(+タイトル)というシンプルなものでした。

f:id:shu223:20181007153656p:plain

(ship.scn。XcodeのARKitテンプレートに同梱されている)

が、そういう特殊加工をするには部数が足りない(しかもかなり高い)ことがわかり断念。

で、次になんとなく思いついたのが、ship.scnを手書きスケッチ風にしてオライ◯ー的表紙として仕上げることでした。

何度かバージョンアップして、今に至ります。

f:id:shu223:20181007162610p:plain

(左から、Beta 1、Beta 2、RC1)

f:id:shu223:20181007154222j:plain

(入稿版)

「Metal入門」製本版も復活します

技術書典4では完売御礼だった「Metal入門」も第2刷として製本版を販売します。マイナーアップデートでSwift 4.2, iOS 12, Xcode 10対応しております。こちらも技術書典のみ製本版+電子版セットで2000円です。興味あればぜひともこの機会に。

f:id:shu223:20180422101932j:plain

(製本版はマットな表紙とほどほどな厚みが手に馴染む、最高な仕上がりとなっております)

電子版はBOOTHでも販売しております。

shu223.booth.pm

こちらの記事に評判をまとめています。

関連記事

shu223.hatenablog.com

shu223.hatenablog.com

技術書でご飯は食べられるのか? #技術書典

$
0
0

昨日開催された技術書典5にて、新刊「実践ARKit」と既刊「Metal入門」という2冊の技術書を販売してきました。これまで商業出版も含め何度か技術書を書いてきて、「技術書に儲けを期待してはいけない」1と思い込んできましたが、昨日一日の売り上げは約46万円(詳細は後述)。もしかしたら技術書を書くこと自体でそれなりに稼げる時代が来つつあるのかもしれない・・・と考えを改めました。

f:id:shu223:20181010015119j:plain

(技術書典5。自分のブースからの光景)

自分の書籍の中身やイベントがめちゃくちゃ楽しかったという話は本記事ではいったん置いておいて、そんな「お金」の面について具体的な数字、気付きなどを書いておきたいと思います。

1日の売り上げ詳細

実践ARKitMetal入門、どちらも製本版+電子版のセットで2000円で販売しました。どっちが何冊売れたかはちゃんと数えてないのですが、だいたい3:1ぐらいでARKitのほうが多かった感じです。

で、現地で約36万円売れて、Web(BOOTH)でも同日に10万円程度を売り上げました2

印刷代は合計で11.5万円ぐらいで、BOOTHは手数料が3.6%、ダウンロードコード発行代が約1万円(コンカ)。粗利だけで33万円という感じです。

この金額の意味するところ

とはいえ技術書典での1日と同じ水準で売れ続けるわけはなく、これからは電子版を中心にポツポツ売れるだけなので、実際のところ「ご飯を食べるタネ」としてはまだまだ心もとないかもしれません。

しかし、この金額は僕にとっては非常に大きな意味を持ちます。

というのも、いままでにちゃんと「本屋に並ぶ技術書」も書かせていただきましたが(いわゆる商業出版)、印税率は8%で、共著だとそこから折半なので、たとえば4000円の本を買ってもらって1冊あたり160円。初版2000部のぶんはもらえるので32万円。これが何ヶ月かフルタイムで執筆してのトータルの収益3だったのです。

また別の話ですが、僕はGitHubでいろいろとOSSを公開していて、合計で約23,000スターを獲得しています。もちろんスター数が絶対的な価値を持つわけではありませんが、しかしソースコードを公開してエンジニアコミュニティに多少なりとも貢献をしているとはいえると思います。

そんなGitHubpaypal.meのお布施リンクを置いてみてはいますが、いまのところトータル収益はゼロ円です。

それとはまた別に、Qiitaでは21,000コントリビューション以上ありますが、もちろんここからの収益はありません。

それとカンファレンスでの登壇は、(略)

つまり何がいいたいかというと、いままで技術情報の発信というのは基本的に無報酬、お金とは違うところに意味を見出しつつ、稼ぎはそれ自体ではなく別のところで得るしかなかった、ということです。

それが、今回の技術書典5では、技術情報発信(ここでは書籍)自体でそれなりの稼ぎがあったので、これはエポックメイキングだなと。

というわけで個人的にすごく楽しくなってきたので、今後の動き方を考えるためにも、今回の技術書典5を振り返って(売り上げの観点から)「やってよかった」と思うことを書いておきたいと思います。

やってよかったこと

前日からBOOTHで販売開始

今回の実践ARKitは、技術書典の前日にはBOOTHで電子書籍版の販売を開始し、告知しました。

あと、当日会場での「開封の儀」をツイートしたりと、タイムラインからでも会場の温度感が伝わるようにしました。

東京の池袋で1日だけ開催された技術書典。非常に盛り上がったとはいえ、東京以外にお住まいの方々にとってはこのためだけに来るというのはハードルが高いと思います。

  • 遠方の多くの人は技術書典に来れない
  • しかし注目はしている=熱気は届いている

というわけで、タイムライン見てて、なんかツイートとか流れてきて「いいな〜買いたいな〜」と思ったそのときにネットで買えるなら買ってしまうのではないでしょうか。「電子版は後日用意します」は思っている以上に大きな機会損失かもしれません。

印刷代の割増を恐れずギリギリまで書く

どんな時間管理術や仕事術を弄したところで、結局一番捗るのは締切間際、というのが現実かと思います。締切間際のあの集中力と決断力はプライスレスです。

ギリギリまで粘ると印刷代の割増料金がかかるといっても1日で5%程度、元の印刷代を仮に40,000円とすると、たかだか2,000円です。たったの2,000円で締切間際の集中力ブーストがもう1日分買えるなら買うしかない、と判断しまして、入稿を10%割り増し(2日延長)の10/4(技術書典は10/8開催)に行いました。この2日の作業で本のクオリティは50%はアップしたと思います。

安売りしない

前回の「Metal入門」は、技術書典初参加で、まったく空気感もわからず、「自分のとこだけ売れなかったら寂しいなー」と日和って1,200円という価格設定にしました。しかしこのMetal入門いまでも日本語では唯一のMetalのまとまった情報源で、非常にニッチな本なので、いくら安かろうがいらない人はいらないし、欲しい人は高くても買うという類のものです。なんせ代わりがないので。数は出ないけど高くても売れる、ニッチというのは弱みでもあり強みでもあるのです。

今回の新刊のテーマであるARKitはもうちょいメジャーで、同フレームワークを扱った書籍は商業・同人共にいくつか出てますが、しかしネイティブでのARKit開発(Unityではなく)を扱っていて、著者にしっかりとしたiOSのバックグラウンドがあり、体系立てて構成も練られている、となるとやはり商業出版含め代わりはないかなと思っています。

そんなわけで、「製本版+電子版とのセットで2000円」と、技術書典としては少し高めの水準の価格設定にしました4。結果的にはちゃんと売れて、合計としても前回の2倍という売り上げになったので、これでよかったのかなと思います。

売れ残りを恐れず刷る

「完売の誘惑」というのはあって、やっぱり早々に売り切って「完売しました!」とツイートして、他のブースまわったりしたい、というのはあります。

また普通の小売業にとって在庫を抱えるというのはリスクを伴うことだと思います。単純にうちの場合、余った本の箱を家に送ろうものなら奥さんに間違いなく迷惑がられます。

しかし今回、技術書典会場に【BOOTH倉庫に無料発送できる窓口】という窓口が設置され、

もはや売れ残りを恐れる理由はなくなりました。在庫が多すぎると保管料が1000円かかるとのことですが、送る物品のサイズ・重量・管理コストを考えれば、気にするべくもないめちゃくちゃリーズナブルな価格だと思います。

というわけで僕は当初の予定より1.5倍ほど多めに刷りました。もはや売れ残りすら楽しみになって、早くBOOTHの在庫に反映されないかなーと心待ちにしています。

おわりに

「やってよかったこと」を書いてみましたが、当たり前すぎますかね。。

とにかく、「技術の発信」でも収入が得られる時代が到来しつつあることが嬉しいです。お客さんの課題に対して技術力をふるう「案件」も好きですが、その仕込みフェーズ自体でも稼げるとなると、より自由に生きるための選択肢が増えたような、そんなワクワク感があります。

技術書典6で書きたいネタも山程あります。引き続き勉強と発信を続けていきたい所存です。


  1. 本屋に自分の本が並ぶというのは親にも親戚にも誇らしかったし、エンジニアとしての箔はついたと思うし、仕事に繋がった面もあるし、海外でも物理的な本は自慢になったし、もろもろメリット・デメリット比較して書きたいと思ったから書いたわけで、実際書いてよかったと今も思います。

  2. 新刊は前日からBOOTHという販売サイトにて電子版の販売を開始しました。

  3. 書いた本はどちらも2, 3回増刷されましたが、なんやかんやの規約があってなかなか増刷分は入ってこなかったりします

  4. BOOTHでの通常販売はもうちょい高めになっています。


フリーランスのお仕事まとめ2018年5月〜8月

$
0
0

前回の実績まとめ記事以降(5月〜8月いっぱいまで)の4ヶ月間にやったお仕事のまとめ。

Fyusion

5月GW以降の約3週間はサンフランシスコでFyusionの仕事1。新しい画像処理機能の開発と、既存の画像処理パイプラインをMetalで最適化する仕事をやってました。

WWDC/AltConf参加

6月頭、WWDCはチケット外れてしまったので会場には入れなかったのですが、10日間ほどサンノゼ近辺に宿を取り、AltConfに出たり、カフェでセッション動画を見て勉強したり、ということをやっていました2

ドローン利用アプリ

ドローンを利用した屋根点検サービスを提供しているスタートアップ「CLUE」のアプリ開発をお手伝いしました(しています)。

CLUE社はドローンを飛ばせるように都内に専用の場所を借りていて、飛行ライセンスを持った人がテストしています。ドローンは興味がありつつもボーッとしているうちに規制されてしまい乗り遅れてしまっていたので、こうしてしっかりビジネスをやっているところに声をかけていただけたのは幸運でした。

f:id:shu223:20180619113450j:plain

(都内某所で飛行テスト)

とはいえスケジュールが立て込んでいたのであまり多くはお手伝いできていないのが実情。issue対応やちょっとした機能開発しかできていません。もっとがっつりドローンと向かい合いたいところです。

中国でのファームウェア実装のヘルプ

7月のある日、昔一緒にお仕事させていただいたプロダクトデザイナーの方より「ある制作会社に発注したアプリができてこなくて、そろそろ生産に入るデバイスのファームのテストが全くできていない、助けてほしい」という旨の電話が来て、急遽当該デバイスとアプリ間で行うBLE通信の全要件を確認できるテストアプリをつくり、その週には深センまで飛んで中国側のファームウェアエンジニアとテーブルを囲んでがっつりテスト&デバッグ作業をやる、というお仕事でした。テストアプリ開発2日、深セン2日の合計4日間。

f:id:shu223:20180727123338j:plain

(工場とオフィスのある建物)

f:id:shu223:20180727090340j:plain

(泊まったホテルより)

f:id:shu223:20181022031422j:plain

(作業の様子)

動作確認するための通信相手(iOSアプリ)が提供されない状況で実装されたファームですから、最初の確認では繋がることすらできない(接続のための仕様のすりあわせがうまくいっていない)状況でした。そこから、合計4人日でひと通りの機能が動作するところまで持っていったので、なかなか良い貢献ができたと思っています。

Swift Island参加

オランダの「テッセル島」で開催されたカンファレンスに参加。詳細は以前ブログに書きました。

shu223.hatenablog.com

カンファレンス自体は3日間なのですが、初めて行くオランダなのでトータル2週間滞在しました。

BLEプロト

海外から来たお仕事。BLEを利用したコミュニケーション機能の開発。要件ヒアリングから、実装、納品用にiPhone2台で動作させる動画を撮るところまでさくっと5時間でやって、5時間分だけ請求、すぐにPaypalで支払われた超特急案件でした。

上述のオランダ滞在中にやった案件で、僕からすれば海外旅行中のスキマ時間で対応可能/ひさびさのBLE案件で自分の古いコードベースをアップデートする良い機会/手離れが良いetc...というメリットがあり、先方もたったの5時間(当初あちらのメンバーが「調査」だけで何日かかけていた)の料金で済み、win-win案件だったと思います。

Metal、デプス、ARKitを使ったエフェクト実装

こちらも海外から来たお仕事。「こういうエフェクトをつくりたい」という打診があり、もともとのコードベースがARKit(フェイストラッキング使用)+Metalレンダリングだったので、エフェクトもMetalで実装しました。やっていくうちにデプス(深度)も利用することになり、ここで初めてデプスを扱った経験がiOSDCでの発表やiOS-Depth-Samplerの実装のきっかけになりました。これもオランダ滞在中にリモートで請けて完了させたお仕事。

Core MLを使った写真の自動分類機能

「まごチャンネル」という子供写真の共有サービスで、アプリ起動時にバックグラウンドで解析処理が走り、自分で選択しなくても子供が写っている写真だけを自動で抽出してくれる(→すぐにアップロードできる)、という機能を実装しました。

f:id:shu223:20181022034251j:plain:w240

モデル自体は社内の機械学習エンジニアの方がつくったもので、それをCore MLで使えるように変換するところから、iOSアプリに解析機能とUIを実装するところまでを担当しました3

まごチャンネル(チカク社)はその後もアプリ改善等で継続してお手伝いしています。

Core NFCを使ったゲームアプリ

これも前回記事からの継続。非常勤メンバーとして関わっているブルーパドル社でのお仕事で、Core NFCを使ったゲームアプリをつくっています。こちらはアプリ実装をゼロからまるっと担当。

いろいろ発散させて遊んでみるというフェーズから、今は仕様を収束させ、11月末の公開に向けて動いているところです。すでに一度はApp Storeの審査にも通っています。乞うご期待。

ちなみにこの期間、ブルーパドルではコードコーヒーというのもクラウドファンディングで出しました(僕は飲みながら感想言うだけのお仕事)。

Bluetoothモジュールの機能調査

とあるBluetoothモジュールの評価ボードを使って、(iOSアプリと連携して)何ができるのか、どう実装するのか、といったところ調査し、プロトタイプをつくる、というお仕事。ボード購入や問い合わせ待ちで間が空いたりしつつ、今も継続しています。

アプリ側はまだしも、ハードウェア側は「勘」が効かないので、問題解決にいちいち手こずります。このへん、慣れ親しんだiOSばかりやってる自分には良い刺激になっています。

技術顧問

こちらも前回から引き続き。事業計画に沿って、キーとなる技術のフィージビリティ調査(検証のための実装も含む)を行ったりしています。

その他

MIT訪問

ボストン/ケンブリッジに5日間の旅程で行き、MITのMedia Labを見学させていただきました。ラボも良かったし、MITのキャンパスも、ケンブリッジという街の雰囲気も良かった。いまはまだリアルには考えられないですが、何か研究テーマを決めてこういう環境で2年か3年探求するってのは楽しいだろうなぁ、と。

書籍の執筆

iOS 12 Programming」の章を2つ書きました。これについてはアーリーアクセス、あるいはベータ版が公開されたらまた別途記事を書きます。

iOSDC登壇

8月最終週はお客さん仕事を止め、ほぼフルタイムでこれに取り組んでいました。現存するデプス関連APIをすべて棚卸しして、それぞれ動作確認サンプルつくって、という素材集めでまず時間がかかり、集めた素材をどう調理しようかという発表の構成フェーズもまた時間がかかりまして、結局iOSDCの自分の発表前夜までこねくり回してました。工数かかってるのでぜひ見てやってください。

www.youtube.com

おかげさまでベストトーク賞3位を受賞しまして、さらにこのとき作ったサンプルを再構成して新作OSS(後述)も出せたし、本にも書けた4ので、調査や推敲にかけた時間は報われたかなと。

OSS活動

デプス(深度)をiOSで扱う方法を網羅したサンプルコード集「iOS-Depth-Sampler」をGitHubで公開しました。

github.com

デプス(深度)をiOSで扱う方法を網羅したサンプルコード集「iOS-Depth-Sampler」を公開しました - その後のその後

Trendingのデイリー最高2位ぐらい、ウィークリーでも10位以内にランクインしてました。iOS 7〜10のSamplerシリーズは軒並み3000スター以上を獲得していたことを考えるとだいぶひっそりとしたものですが、「iOSにおけるデプス」という切り口でこれだけ横断的にまとまった技術情報は英語でも存在しなかった5ので、世界に貢献するいい仕事ができたなと自己満足しています。

f:id:shu223:20180915110312g:plain

引っ越し

家族構成が変化することを見越して、8月頭に、4年半住んだ6アパートから引っ越しました。フリーランス、しかも前年度の確定申告実績がない7という社会的信用力の低さから、審査は多少難航しました。

妻の希望を優先して目黒区から新宿区になり、ほとんどのお客さんのオフィスから遠ざかってしまった(以前はほぼ自転車移動で済んでいた)のですが、場所や環境が変わればいろいろと新展開が始まるもので、マイナス面よりプラス面の方が遥かに多いです。引っ越しは面倒だけど定期的にやるものだなと。

おわりに

5月〜8月末までのお仕事をまとめました。

というのも、9月1日(iOSDCの登壇日の朝!)に娘が生まれ、働き方がガラッと変わったからです。いや、変わった、というよりいったん仕事ができなくなりました。諸事情で日中の育児は僕が担当することになっているのですが、赤ちゃんが寝てくれている時間しか仕事ができない(いつ起きて泣き出すかは赤ちゃん次第)ので、稼働可能な時間が読めない→ お客さん仕事は入れられない、という。

9月は「iOS 12 Programming」の執筆の続きと、技術書典5向けの執筆があったのでそれでも良かったのですが、僕はお客さんのところにいって顔を合わせてコミュニケーションしながら仕事をするスタイルを本当に楽しんでいたので、そういった働き方ができないのはかなり苦しいですし、そもそもこのままだと収入が止まってしまいます(片働きです)。今のところ平日はベビーシッターさんを呼んだりしていますが、そうすると1日2万円、20人日で40万円(実際は8時間ではカバーできないのでもっと)かかる計算になってしまうし、保育園は認可外ですらすぐには入れない、という悩ましい状況です。

本記事でまとめた「それ以前」のお仕事を振り返ると、あらためて自分はよいお仕事・会社・機会に恵まれているなと思います。いまはまだ完全には仕事に復帰できていない状況ですが、どうにかポジティブに育児も仕事も幸せにこなせるよう画策していく所存です。


  1. これはフリーランスとしての仕事ではなく、アメリカの会社員としての仕事(ビザはH-1B)。別途アメリカで確定申告することになります。

  2. ちなみにこれによる収入はゼロですが、フリーランスiOSエンジニアとしての活動の一環ではあるのでここに書きました。

  3. 本機能については前回記事にも書きましたが、その後もろもろ本実装を行った上で無事リリースされたので、改めて書きました。

  4. これは後日発表します。しっかり練った構成が既にあったのでスイスイ書けた。

  5. WWDCのセッションはよくまとまっているが、それでも3つのセッションに分かれている(2018年現在)し、サンプルコードが提供されていないものがほとんど。

  6. 正確にはそのうち1年半は僕は主にアメリカに拠点を置き1ヶ月ごとに往復する生活をしていたが、妻はずっとこのアパートに住んでいた。

  7. 2017年度は全収益をアメリカで確定申告したので。

技術書の著者になるためにやったこと

$
0
0

この記事はカヤックOBが綴るアドベントカレンダーex-KAYAC Advent Calendar 2018」の4日目の記事となります。

2010年: いつか技術書を書いてみたい

プログラマになる前、「本の書く」というのは自分とは関係ない「どこか遠い世界の話」のように思っていました。しかしプログラマになってカヤックに入ってみると、なんとまぁ、書籍執筆経験のある人の多いこと。 本を書くことが「現実的な憧れ」に変わりました。

しかし、自分は30過ぎてプログラマデビューしたばかりの、技術力も経験もない、うだつの上がらないプログラマ。 有名でもないし、本の執筆が舞い込むようなインパクトのある実績も特にありません。 いつかは自分も、とは思うものの、それは「いつか」でしかありませんでした。

2011年: 会社の広報に「本を書きたいです」とメール

ある日ふとこう考えるようになりました。自分に技術書の著者になるほどのネームバリューがないからこそ、技術界隈でも名の知れている会社の看板の力を借りるべきなんじゃないの、と。

そうとなったら善は急げ、ということで、今の自分にも書けそうな企画として(当時まだあまり出揃っていなかった)iOS関連のライブラリカタログ本的な企画を考え、会社の広報にメールしました。本を書きたいので、出版社に繋げてもらえませんか、と。

(当時メールを出す前に書いた下書きの抜粋)

今期、技術書を書いてどこかの出版社に寄稿したいと考えています。
で、今自分が考えているようなことが可能性があるのかどうか、
カヤックでの出版に数々携わっている◯◯さんにまずは相談してみようということでメールしてみました。


【考えている内容】

オープンソースのiOS用フレームワーク/ライブラリ/カテゴリ/サンプルコードを紹介する
(注:カテゴリというのはObjective-Cの機能で、既存のクラスを拡張することができるものです)


【紙面のイメージ】(添付画像)

・見開き2ページで1つずつライブラリを紹介していくイメージです
・UI/アニメーション/通信/メディア(音声とか画像とか動画とか)/データベース とかで分類
・紹介内容は、どんなライブラリか、そのライブラリを使用することによってどんなメリットがあるか、中身のソースコードについての解説等
・ライセンスや対応iOSバージョン、必要なフレームワークについても記述


 【この本の価値】

・Objective-Cはライブラリやクラスの流用がしやすいわりにまとまったライブラリ情報は少なく、車輪の再開発が目立つ。
・gitHubやappleのdev center、個人サイトなど所在がバラバラなので、なかなか検索だけでオンタイムに欲しいライブラリやサンプルコードを見つけることはできない。
・githubやappleのdev centerは、サンプルを実行したスクリーンショットがないのでビルドしてみるまで実際にどういうコードなのかわからない。特にUIライブラリとかならスクショ見るまで有用性が判断できない。本ならパラパラとめくってよさげなのをさがすことができる。・そのプロジェクト自体に価値はなくても、中のひとつのクラスが有用だったりもする。そういうのは探そうと思って探せるものではない
・少なくとも日本語ではまだこういう本はない(知る限りでは英語でもない)


【ターゲット】

・中級者以上のiOSアプリケーション開発者

ビジュアルがあったほうが伝わるだろう、と考え、本の紙面アイデアも添付しました。もちろん自分で紙面デザインをするような高度なスキルは持ち合わせていないので、こちらの書籍をベースに「プレビュー.app」で線や文字を切り貼りして作成しました。

f:id:shu223:20181203212158p:plain

(当時作成した紙面アイデア画像)

2012年: Web連載開始

広報を宛先に、そしてiOSも書くエースエンジニア陣をCcに入れていたので、すぐに色々と意見をもらえました。いきなり紙の書籍の執筆は時間もかかるし書き上げる難易度も高いので、Web連載から始めるといいのでは、とのことで、これはまさにごもっとも。

そしてその広報の繋がりで、技術評論社(gihyo.jp)の方に会うことになりました。

先の書籍のアイデアを連載用に練り直し、全6回(各回毎に違うテーマを設定し、お役立ちライブラリを紹介する)の連載企画案をつくって会食の場に持っていきました。

無事「いいですね、やりましょう!」とご快諾いただき、連載決定。1回1回、通常業務を終えた後に何日も徹夜してめちゃくちゃがんばって調べまくっては書いてました。会社の看板ありきの連載なので原稿料は自分には入らないし、残業代が出るわけでもないのですが、「Web連載」という新しい実績を獲得できると思うとそれが十分な報酬でした。

2013年: 出版社から技術書を出版

連載とは別に、ブログでのアウトプットも続けていました。当時、ちょうどQiitaが出てきた頃で、自分が今までに書いた技術記事を100本まとめた記事を書いたらはてブのホットエントリー入りする程バズりました。

それを見た出版社の方より本を書きませんかと連絡をいただき、全力で書きたいですと答え、考えていた企画案を提示しました。このへんは先の連載での経験が大いに活きたところだと思います。

無事その案が出版社の企画会議で承認され、2013年5月吉日、晴れて自分も技術書の著者になることができたのでした。

d.hatena.ne.jp

まとめ

カヤック陣で綴るアドベントカレンダーのネタとして何かためになる(かもしれない)思い出話でも、ということで、本の著者になりたいという憧れを、まだ自分の技術力や実績が物足りない頃からアクションを起こし、数年越しでかなえることができた、という経験談を書きました。

まぁ書いてみて思いましたが自分で企画書を書いて広報にメールしたことと、最後に出版社の方から声をかけていただいたこととは明確な因果関係はありません。出版社の方からの連絡は完全に「運」です。ただ、自分から手をあげてWeb連載を経験するとか、技術ブログを地道に書き続けるとか、そういった行動の積み重ねの延長線上にあることも確かかと思います。

紙面案の画像を見て、「こんなのでいいのかw」と思われた方も多いかも知れません。そう、一見自分には手の届かなそうなことでも、案外「こんなことでいいのか」程度の行動の積み重ねで実現できたりするものです。そういうことがこの経験談から伝わって、誰かの勇気になると嬉しいです。

「iOS 12 Programming」のARKitとデプスの章を執筆しました

$
0
0

12月17日、共著で執筆したiOSの技術書「iOS 12 Programming」の一般販売が開始されました!

iOS 12 Programming

iOS 12 Programming

  • 著者:加藤 尋樹,佐藤 紘一,石川 洋資,堤 修一,吉田 悠一,池田 翔,佐藤剛士,大榎一司,所 友太,
  • 製本版,電子版
  • PEAKSで購入する

私は「ARKit」と「デプス」1の章の執筆を担当しました。担当章の詳細については後述します。

中身が良いのはもちろんなのですが、とにかく表紙のデザインがすごく良くて、自分が過去に執筆で関わった書籍では一番のお気に入りです。マットな質感と色合いが好きで、ついつい手にとってしまいます。モノとしての技術書が好き、という方はぜひ製本版をおすすめします!

f:id:shu223:20181221153048j:plain

今のところAmazonでは売ってなくて、PEAKS社のサイトより購入できます。

以下、担当した章の紹介です。

第4章: ARKit

ARKit 2.0の新機能だけではなく、ARKit 1.5で追加された機能、さらにARKit 1.0の中でも前著「iOS 11 Programming」執筆以降に追加発表されたフェイストラッキング2等の機能も網羅しています。

- 4.1 はじめに
- 4.2 垂直平面の検出
  - 4.2.1 検出する平面のタイプを指定する
  - 4.2.2 検出した平面のアラインメントを判別する
- 4.3 平面ジオメトリの取得
  - 4.3.1 ARPlaneGeometry
  - 4.3.2 ARSCNPlaneGeometry
  - 4.3.3 ARPlaneAnchorのgeometryプロパティ
  - 4.3.4 実装
- 4.4 画像検出
  - 4.4.1 ARWorldTrackingConfiguration の detectionImages プロパティ
  - 4.4.2 ARReferenceImage
  - 4.4.3 ARImageAnchor
  - 4.4.4 実装
  - 画像検出のパフォーマンス
- 4.5 画像トラッキング
  - 4.5.1 ARImageTrackingConfiguration
  - 4.5.2 実装
  - 4.5.3 画像トラッキングと画像検出の違い
  - 4.5.4 ワールドトラッキングコンフィギュレーションで画像トラッキング
- 4.6 フェイストラッキング
  - 4.6.1 ARFaceTrackingConfiguration
  - 4.6.2 ARFaceAnchor
  - 4.6.3 ARFaceGeometry
  - 4.6.4 ARSCNFaceGeometry
  - 4.6.5 実装
- 4.7 3D物体検出
  - 4.7.1 ARReferenceObject
  - 4.7.2 detectionObjects
  - 4.7.3 ARObjectAnchor
  - 4.7.4 実装
  - 4.7.5 3D 物体スキャンの公式サンプルと独自実装について
- 4.8 AR体験の永続化と共有
  - 4.8.1 ARWorldMap
  - 4.8.2 ワールドマップの取得
  - 4.8.3 ワールドマップからの復元/initialWorldMap
  - 4.8.4 ワールドマップのアーカイブ/アンアーカイブ
  - 4.8.5 ワールドマップ取得タイミング
- 4.9 ビデオフォーマット
  - 4.9.1 ARConfiguration.VideoFormat
  - 4.9.2 videoFormat
  - 4.9.3 supportedVideoFormats
- 4.10 USDZの利用
  - 4.10.1 USDZファイルからMDLAssetを初期化する
  - 4.10.2 MDLAssetからSCNSceneを初期化する

なお、基礎から順序立ててARKitについて学びたい方は「iOS 11 Programming」の第2章を参照してください(後述)。

第5章: デプス

デプス(深度)が取得可能になったのはiOS 11から、つまり比較的最近のことです。 従来のカメラやGPSが、デジタルの世界と我々が生きる現実世界を繋ぐ重要な役割を担い、 アプリ開発者に多くの創造性を与えてくれたのと同様に、 モバイル端末で「奥行き」がわかるようになったというのはアプリ開発の次元がひとつ増えたようなものです。

そんなデプスですが、登場して間もないということもあり、日本語での情報はまだほとんどありません。 そこで本章ではデプスについて、iOS 12で追加されたAPIの解説だけでなく、 基礎から応用まで順序立てて30ページにわたって解説しています。

- 5.1 はじめに
- 5.2 デプスとは?
- 5.3 Disparity(視差)とDepth(深度)
- 5.4 AVDepthData
- 5.5 iOSにおけるデプス取得方法
- 5.6 デプス取得方法1:撮影済み写真から取得
  - 5.6.1 CGImageSourceオブジェクトを作成する
  - デプスデータをもつ PHAsset だけを取得する
  - 5.6.2 CGImageSource から Auxiliary データを取得する
  - 5.6.3 Auxiliary データから AVDepthData を初期化する
  - デプスマップをCIImageとして取得する
- 5.7 デプス取得方法2:カメラからリアルタイムに取得
  - 5.7.1 デプスが取れるタイプの AVCaptureDevice を使用する
  - 5.7.2 デプスが取れるフォーマットを指定する
  - 5.7.3 セッションの出力に AVCaptureDepthDataOutput を追加する
  - 5.7.4 AVCaptureDepthDataOutputDelegate を実装し、AVDepthData を取得する
  - 5.7.5 AVCaptureDataOutputSynchronizer で出力を同期させる
- 5.8 デプス取得方法3:ARKitから取得
- 5.9 デプス応用1:背景合成
  - 5.9.1 背景合成とは
  - 5.9.2 CIBlendWithMask
  - 5.9.3 デプスデータの加工
- 5.10 デプス応用2:2D写真を3D空間に描画する
- 5.11 PortraitEffectsMatte
  - 5.11.1 AVPortraitEffectsMatte
  - 5.11.2 PortraitEffectsMatteの取得方法
  - 5.11.3 PortraitEffectsMatteの取得条件/制約

iOSにおけるデプスについてこれだけ網羅的に、しかもフレームワークを横断して解説している書籍は英語圏を含めても存在しないのではと思っています。たぶんiOS 13が出ても14が出てもデプスについて詳しく書かれた日本語解説書は出てこないので、「デプスやるならiOS 12 Programming」と末永くご愛読いただけるといいなぁと思っております。

f:id:shu223:20180913012548g:plain

(PortraitEffectsMatteで背景切り抜き)

f:id:shu223:20180915110312g:plain

(2D写真を3D空間に描画)

全体のPR

本書の目次全体は次のようになっております。

  • 第1章 Siri Shortcuts ( @cockscomb 加藤 尋樹)
  • 第2章 Notifications ( @justin999_ 佐藤 紘一)
  • 第3章 Password AutoFillとAuthentication Services( @_ishkawa 石川 洋資)
  • 第4章 ARKit( @shu223 堤 修一)
  • 第5章 デプス( @shu223 堤 修一)
  • 第6章 Core ML 2, Create ML( @sonson_twit 吉田 悠一)
  • 第7章 Swift 4.0からSwift 4.2へのアップデート( @ikesyo 池田 翔)
  • 第8章 Xcode 10の新機能( @hatakenokakashi 佐藤剛士
  • 第9章 Mojaveの新機能( @tamadeveloper 大榎一司)
  • 第10章 tvOS 12の新機能( @tokorom 所 友太)

いかがでしょうか。ここで僕が声を大にして言いたいことはiOS 11のときも言ってますが)

本書はiOS 13, 14, 15...が登場しても価値を持ち続ける

ということです。今後もiOSやSwiftの入門本は多く出てくると思いますが、本書が扱っているような項目について同様の詳細度で解説する書籍はそうそう現れないでしょう。というわけで、ひとつでも興味のある項目があれば、ぜひご検討ください。

iOS 11 Programming」も併せてどうぞ

なお、ついでに言わせていただきますと、同じ理由でiOS 11本も今でも「買い」です。

iOS 11 Programming

iOS 11 Programming

  • 著者:堤 修一,吉田 悠一,池田 翔,坂田 晃一,加藤 尋樹,川邉 雄介,岸川克己,所 友太,永野 哲久,加藤 寛人,
  • 発行日:2017年11月16日
  • 対応フォーマット:製本版,PDF
  • PEAKSで購入する

もう一度改めて目次を見てください。

- 第2章 ARKit
- 第3章 Core ML
- 第4章 Swift 4の新機能とアップデート
- 第5章 Xcode 9 の新機能
- 第6章 Drag and Drop
- 第7章 FilesとDocument Based Application
- 第8章 レイアウト関連の新機能及び変更点
- 第9章 Core NFC
- 第10章 PDF Kit
- 第11章 SiriKit
- 第12章 HomeKit入門とiOS 11のアップデート
- 第13章 Metal
- 第14章 Audio関連アップデート

私が担当したARKitの章、こちらはiOS 12本で書いた内容と一切の重複はありませんiOS 11本のARKitの章では、3行で実現できるARKitのはじめの一歩から、水平面の検出・仮想オブジェクトの設置・インタラクションといった重要な基礎機能の解説、そして現実世界の長さを測るメジャーアプリや空中に絵や文字を描くお絵かきアプリといった応用アプリケーションの実装方法を解説しています。iOS 12が登場した今でも古びない内容ですので、ARKitの実装を基礎から学びたい方はぜひご検討ください。

また同じく私が担当したMetalの章、こちらもiOS 11の新機能だけではなく、基礎からじっくり順序立てて解説しています。OpenGLDirectXGPUに近いレイヤでのグラフィックスプログラミングに親しんで「いない」人達にはMetalはかなりとっつきにくいと思うのですが、そういう方達にとってのわかりやすさにおいては英語の情報ソース含めても随一なのではないかなと勝手に自負しております。

他にもたとえばHomeKitの章。長らく謎に包まれていたHomeKit、対応デバイスもなかなか登場しなかった当然それについて書かれた書籍もありませんでした。そしてポツポツとデバイスが出揃ってきた今、満を持しての所さんによる56ページに及ぶ入門~実践の解説!他の章に用がなくてもHomeKitに興味がある人はこれだけで本書を購入する価値があると思います。

他にもこの本以外では詳細な解説はなかなか出ないんじゃないか、と思われる項目がたくさんあります。しかも、著書やカンファレンスでの講演に定評のある著者陣による執筆です。たまーに見かける、APIリファレンスを翻訳しただけのような、あるいはさわりをちょろっと解説しただけみたいな章はひとつもありません。それぞれが興味深く読めて、ちゃんと頭に入ってきて、実際の現場で役立つように各著者によって噛み砕かれ、再構成されています。

というわけで今でもその価値は色あせてないと思うので、興味のあるトピックがあればぜひiOS 11 Programmingもご検討ください。

まとめ

ついに一般販売が開始された書籍「iOS 12 Programming」について執筆者の立場から紹介させていただきました。ちょっと気になってきた、というみなさま。PEAKSのサイトに無料サンプルもあるので、ぜひぜひチェックしてみてください。

iOS 12 Programming

iOS 12 Programming

  • 著者:加藤 尋樹,佐藤 紘一,石川 洋資,堤 修一,吉田 悠一,池田 翔,佐藤剛士,大榎一司,所 友太,
  • 製本版,電子版
  • PEAKSで購入する

何卒よろしくお願いいたします。


  1. 実はクラウドファンディングで購入者を募った時点ではMetalのiOS 12の新機能について書く予定だったのですが、執筆段階でデプスの章に変更させていただきました。Metalの章を楽しみにしていたクラウドファンディング支援者の方々には申し訳なかったのですが、デプスもまたiOSアプリ開発の新しい可能性を切り拓くものなので、いまこのタイミングで体系だった解説を書くことの意義は大きいと考え、この決断に至りました。この変更については支援者にはメールでベータリリース時お知らせしています。

  2. フェイストラッキングはARKit 1.0に属する機能ですが、ARKitが初めて発表されたWWDC 2017の時点ではまだ隠されており、2017年秋にiPhone X発表と同時にAPIが公開されました。

フリーランスのお仕事まとめ2018年9月〜12月

$
0
0

前回の実績まとめ以降の9月〜12月の4ヶ月間にやったお仕事のまとめ。

ハイライト

  • 「アナログデジタルボドゲ」がついにリリース
  • 機械学習×iOS」案件が増えてきた
  • 採用コンサルや新規の技術顧問契約等、新展開も色々と
  • 本の執筆×2
  • インタビューしていただきました×3
  • Voicyはじめました
  • 娘が生まれました

Core NFCを利用したボドゲ「アナログデジタルボドゲ

f:id:shu223:20181230141249j:plain

非常勤メンバーとして参加しているブルーパドル社でのお仕事。以前から水面下で開発していたアナログ+デジタルなボードゲーム、その名も「アナログデジタルボドゲ」がついにリリースされました1。アプリ実装をまるっと担当してます。

bodoge.blue-puddle.com

あれこれ制約が多く今のところ使いみちがないと言われがちなCore NFCですが、それをゲームで実用するというのは世界でも珍しいのではと。

開発中は作っては遊び、遊んでは作って、というサイクルで、完全に楽しかったです。

機械学習×iOS

機械学習×iOSCoreML登場以前から模索していたもののなかなか仕事に繋げられないでいたのですが、ここにきて実ってきました。前回書いたまごチャンネルの「子どもファインダー」機械学習で子供が写っている写真を自動選別する機能でしたが、今回はそれとは別に新案件が2つ。

TensorFlowモデルをiOSで動かすための実装

作業は完了しているのですが、機能リリースがまだなのでアプリ名やどういう機能かは控えておきます。TensorFlow(以下TF)で学習させたモデルがあって、そのモデルを用いた推論処理とOpenCVの処理を組み合わせたC++のコードがあり、それを既存のiOSプロジェクトに組み込む、というミッションでした。

TFのモデルを使うだけであれば以前別の案件でやったようにCore MLモデルに変換してiOSで用いる、という選択肢もあるのですが、今回の場合はOpenCVと組み合わせてトータルな処理を構成しているのと、そのC++コードは今後も継続的にアップデートされるであろうことから、(少々詳細になりすぎているので中略)つまり何が言いたいかというと、

  • TFはサンプルレベルながらも多少触ったりコードを読んだりしていた
  • Fyusion社でR&Dチームが書いたC++コードをiOSに組み込む仕事をよくやっていた
  • Core MLやiOSGPUまわりについて知見・経験がある
  • Courseraで機械学習の基礎だけは学んでいた

等々が絡んでいて、点と点が繋がって線になっているなぁ、と感じたのでした。

qiita.com

qiita.com

qiita.com

d.hatena.ne.jp

機械学習を利用した機能のSDK

上とは別の会社で、機械学習で実現しようとしていることも全然違います。ここでのお仕事は、既にiOSで動いているCoreMLモデルがあり、その機能をSDK化するというものでした。モデル追加しやすいように内部で抽象化したり、利用側が使いやすいようなAPI設計にしたり、テスト書いたり。公開が楽しみです。

継続的なお手伝い

ドローン利用アプリ

ドローンを利用した屋根点検サービスを提供しているスタートアップ「CLUE」を継続してお手伝いしています。同社はドローンを飛ばせる「ラボ」を都内に持っているのですが、子供が生まれてから外出が難しくなったので、リモートでも可能な(つまりドローン実機が不要な)部分でお手伝いしています。

まごチャンネル

テレビにHDMIケーブルを繋ぐだけの写真・動画サービス「まごチャンネル」を提供しているチカク社を継続してお手伝いしています。細かいUIUXや機能改善等。

技術顧問(継続)

こちらも前回から引き続き。事業計画に沿って、キーとなる技術のフィージビリティ調査(検証のための実装も含む)を行ったりしています。そろそろ新展開がありそうです。

Metal関連

Metalでのフィルタ実装

顔のパーツとかメガネとか背景とかはそのままに、肌だけ平滑化するMetalフィルタを実装。海外案件。

かなり前に同じようなフィルタのシェーダを書いたことがあり(GPUImageにプルリク送ってマージされた)、そのときの知見が役立ちました。

新展開

採用コンサル

こちらも継続的にお手伝いしている会社で、技術面では「Bluetoothモジュールの機能調査」をやっていてNDA的に書けないことしかないのですが、同社のエンジニア採用コンサルもさせていただきました。同社のWantedly採用ページについてエンジニア目線からどのへんがポイントとなるか、あるいはポイントとならないか(クリックしない/読むのをやめる)、といったところを指摘し、僕ならこう書く、というのを書いて解説したりもしました。

記事には書いたことないですが、基本的には手を動かして(コードを書く)お手伝いを軸としつつ、継続する中でこういった採用面でお手伝いすることはちょくちょくあります。(エンジニア募集方法について一緒に検討したり、面接したり、候補者についてコメントしたり、人を紹介したり)

技術顧問(新規)

12月後半から開始しました。(僕の個人的なイメージですが)「技術顧問」は設計とか技術選定とかチーム開発手法とかの比較的大きい枠組みでの技術的アドバイスが求められることが多いと思っていて、僕はそういうところの知見やスキルが特に秀でているわけではないので基本的に技術顧問的ポジションには向いていないと言っているのですが、ここはスタートアップというより、アーティストチームのようなところで、僕自身ずっとファンでもあったし、求められている内容も期待に応えられそうだと感じたので、二つ返事でお受けしました。

ポッドキャスト(Voicy)開始

『技術の小難しい話はおいておいて、「生き様」に焦点をあてていろんなエンジニアにお話を伺う』というコンセプトでPodcastをはじめました。とはいえPodcastアプリで探しても出てこなくて、Voicyというアプリ/Webサイトで聴けます。

voicy.jp

ソフトウェアエンジニアという職業は今や売り手市場で、パソコンとネットがあればどこでも仕事ができ、国や言語を超えて通用し、ブログやオープンソースで発信することでプレゼンスも向上しやすく、「生き方の選択肢が多い」職業のひとつです。エンジニアにもそうでないみなさまにも、人生の可能性を感じてワクワクしていただけるような内容にしたいと思っています。

執筆

「実践ARKit」執筆&技術書典5

【つくりながら学ぶ実践入門書】というコンセプトで、ARKitの入門書「実践ARKit」を個人で出版しました。

note.mu

Boothにて販売しています。

shu223.booth.pm

10月の「技術書典5」で販売してきました。

shu223.hatenablog.com

iOS 12 Programming」執筆

PEAKS刊行の「iOS 12 Programming」で、「ARKit」の章と「デプス」の章の執筆を担当しました。

iOS 12 Programming

iOS 12 Programming

  • 著者:加藤 尋樹,佐藤 紘一,石川 洋資,堤 修一,吉田 悠一,池田 翔,佐藤剛士,大榎一司,所 友太,
  • 製本版,電子版
  • PEAKSで購入する

詳細はこちら:

shu223.hatenablog.com

インタビュー&講演

Qiita:Zineでの対談(フリーナンス広告記事)

フリーランス向け保険その名も「フリーナンス」について、座談会形式でお話を伺いました。広告記事ですが提灯記事にはしたくないです、ってことで『僕にはちょっと当てはまらないかな?』とかかなり正直に話してるので興味のある方はぜひ。

zine.qiita.com

エンジニアHubインタビュー

OSSを軸にしたあのインタビューシリーズに出させていただきました!iOS Samplerシリーズを始めたきっかけや、どういうことを考えてコードを公開しているか、といった話をしています。

employment.en-japan.com

よく「ブログを書いたほうがいいとは思いつつも、書く時間がない」と聞きますが、それは僕からすれば「仕事をしたけど請求書を書く時間がない」と言っているのと同じように感じます。「今月は時間がないから、100万円分の請求書を出しませんでした」っていう人は絶対にいないでしょう(笑)。それと同じ感覚で、面白い仕事を経験したり、新しい技術を身に付けたらそのことを世に発信するのは、僕にとっては明確に実益を伴うことなんです。僕はブログを書くために仕事を断ってでも時間を確保することもあります。

キズナシッターインタビュー

ベビーシッターでいつもお世話になっている「キズナシッター」さんにインタビューしていただきました。うちの👼も同席しました。(隣りにいるのはよく来てくださっているシッターの岩見さん)

sitter.kidsna.com

フェンリル社で講演

アプリ開発等で有名なフェンリル社にお招きいただき、「エンジニアという仕事を楽しみ続けるためのキャリア戦略」というテーマで講演させていただきました。フェンリルさんに許可をいただいたので、その講演内でつかった約60ページのスライド資料をnoteにまとめました。

note.mu

エンジニアを楽しみ「続ける」というところがポイントで、世の中の変化も激しいし自分も飽きたり慣れたり状況や心境が変わったりする中でどうやって楽しみ「続ける」よう工夫しているのか、というのを実体験を多く交えつつ話しています。

昔は楽しかったんだけど最近はどうも惰性でやってるかも」とか、「若くて優秀な人にはもうかなわないなぁ」という感じの方々には共感していただける部分があるかもしれないのでぜひ見てみてください。

おわりに - 育児と両立するための試行錯誤

9/1に娘が生まれ、働き方がそれまでとはガラッと変わりました。育児のために外出すらままならなくなりいったんほぼすべてのフリーランス案件を止め、収入が激減。軽く絶望感すらありました。

これは上のキズナシッターのインタビューからの引用なのですが、

僕はエンジニアで、自分の仕事を楽しんでいて、僕の技術を必要としてくれている会社がたくさんあるのに、赤ちゃんを抱っこしていると働けない、という状況がすごく苦しかったんです。そんな状況を、僕よりも赤ちゃんを上手にあやせるベビーシッターさん達に助けてもらうようになって、本当に救われた気がしました。

というわけで、今は週5でシッターさんに来ていただいてます。僕も奥さんも忙しいときは週末にも来てもらうことがあって、11月は(ちゃんと計算してないですが)たぶん40万円以上(!)2かかっています。

とんでもない金額ですね。×12すると恐ろしいですが、認可どころか認可外保育園でも入れないし、片働きなので僕が赤ちゃんを抱っこしてる限り我が家の収入はゼロになるのだから仕方ないです。

しかし全然悲観的な話ではなくて、「お金で解決できるところはそうしよう」と開き直ってシッターさんに毎日来てもらうようにしてからの10月・11月と、僕のフリーランスとしての売り上げは逆に過去最高になっています。

なぜかというとシンプルな話で、僕が何をしている間も常にベビーシッターさんの時給(約2000円)がかかっているので「もったいない精神」が働いて、移動や飲み会を極限まで減らすようになり、代わりにその間も仕事するようになったからです。(ちなみに受けている仕事はどれもおもしろいので全く苦ではありません)

いや、もともと自分の時給が◯◯円だから、「今こうして飲み会に行っている間も△△円かかっている」という認識はあったつもりなんですよ。でもそういう「機会損失」は実際に自分の財布や口座からお金が出ていくわけじゃないので、行動に影響を与える程ではなかった。そこがシッターさんに時給を払うことで可視化/具現化されて、やっと自分の行動を変えるに至ったと。これはエポックメイキングな気付きでした。

そんなわけで、いろんな新しい体験をしたり気付きを得たりしつつ、楽しくやっております。


  1. 11月末に開催された「ゲームマーケット2018」で限定100個だけ販売したのですが、さくっと初日のお昼ぐらいには売り切れてしまいました。クラウドファンディング準備中です。

  2. 2000円×10時間×20日 = 40万円

[書評]日本語初の「モバイルアプリ開発者向け」機械学習・ディープラーニング解説書

$
0
0

iPhone/Androidアプリ開発者のための機械学習・深層学習 実践入門」をご恵贈いただきました。機械学習関連の技術書は数あれど、モバイルアプリ開発者向けを謳ったものは日本語では初だと思います。

iPhone/Androidアプリ開発者のための機械学習・深層学習 実践入門
布留川 英一
ボーンデジタル (2019-01-26)
売り上げランキング: 171,507

モバイル向けというとCore ML/ML Kit等の学習済みモデルを活用するフレームワークやツール群を想起しますが、本書ではCreate ML、Turi Create、TensorFlow、Cloud AutoMLといったモデル作成側についても解説されています。

また目次を見るとわかりますが、機械学習ディープラーニングの定番である画像分類タスク以外に、類似画像検索、画風変換、活動分類、テキスト分類といったタスクのサンプルも登場します。

f:id:shu223:20190124143240j:plain:w400
カラー480ページの重厚な書籍です

目次

第1章 機械学習フレームワーク

  • 1-1 機械学習の概要
  • 1-2 Core ML
  • 1-3 Create ML
  • 1-4 Turi Create
  • 1-5 ML Kit
  • 1-6 Cloud AutoML
  • 1-7 TensorFlow

第2章 Core ML - 基本

  • 2-1 画像分類(画像)
  • 2-2 画像分類(カメラ映像)
  • 2-3 類似画像検索
  • 2-4 物体検出
  • 2-5 画風変換
  • 2-6 活動分類
  • 2-7 テキスト分類

第3章 Core ML - Vision・Natural Language

第4章 Create ML

  • 4-1 画像分類
  • 4-2 テキスト分類
  • 4-3 分類
  • 4-4 回帰

第5章 Turi Create - タスクベース

  • 5-1 Pythonの開発環境
  • 5-2 Jupyter Notebook
  • 5-3 画像分類
  • 5-4 類似画像検索
  • 5-5 物体検出
  • 5-6 画風変換
  • 5-7 活動分類
  • 5-8 テキスト分類
  • 5-9 レコメンド

第6章 Turi Create - アルゴリズムベース

第7章 ML Kit

  • 7-1 ML Kitの準備
  • 7-2 画像分類(画像)
  • 7-3 画像分類(カメラ映像)
  • 7-4 顔検出
  • 7-5 バーコード検出
  • 7-6 ランドマーク認識
  • 7-7 テキスト認識
  • 7-8 カスタムモデル

第8章 Cloud AutoML

  • 8-1 画像分類(Vision
  • 8-2 テキスト分類(Natural Language)
  • 8-3 翻訳(Translation)
  • 8-4 AutoML API

第9章 TensorFlow

  • 9-1 画像分類
  • 9-2 テキスト分類
  • 9-3 過学習と未学習
  • 9-4 FrozenGraphDefへの変換
  • 9-5 mlmodelファイルへの変換
  • 9-6 tfliteファイルへの変換

個人的な読み方

iOSAndroidもやる、本書に出てくるフレームワークは全部知っておきたい、という方は通読する読み方もありかと思うのですが、私はiOS専業でやっているので、基本的にはiOSに関連しそうなところをつまんで読んでいこうと思います。Core MLやVisionやCreate MLは一通り触っているのですが、Turi Createでモデルをつくるところからはほとんどやったことがない(画風変換だけはつくってみたことがある)ので、

  • Turi Createで画像分類以外のタスクのモデルを一通りつくってみる
    • 類似画像検索, 物体検出, 画風変換, 活動分類, テキスト分類, レコメンド
  • → Core MLで動かしてみる

という感じで読んでいこうかなと。

あと、TensorFlowの章の以下の項は、実務上で必要になったことがあるので、必ず読んでおこうと思います。

  • FrozenGraphDefへの変換
  • tfliteファイルへの変換

前者はmlmodelファイルへの変換に必要で、後者は実際のお仕事でLiteじゃないモデルが提供され、変換ができるのか、どれぐらい大変なのかわからないのでそのまま従来のTFバイナリと一緒にアプリに組み込んで使った、ということがあったので、把握しておきたいなと。

p25 表1-1-1 フレームワークがどういうモデルを扱うか、どのプラットフォームから使えるかetc.の一覧も興味深かったです。ML KitはTensorFlow Liteモデルを使うというのは知らなかったですし、Cloud AutoMLはAPI経由で推論を行うということで、結局どちらもiOSからも使えることになります。

まとめ

日本語初の「モバイルアプリ開発者向け」機械学習ディープラーニング解説書、「iPhone/Androidアプリ開発者のための機械学習・深層学習 実践入門」をご紹介しました!

機械学習がホットな分野なのは間違いありませんが、for モバイルとなるとまだまだ始まったばかりという感じです。興味のある方はぜひ本書をチェックしてみてください。

iPhone/Androidアプリ開発者のための機械学習・深層学習 実践入門
布留川 英一
ボーンデジタル (2019-01-26)
売り上げランキング: 171,507

参考:iOS×機械学習の記事

Viewing all 314 articles
Browse latest View live