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

[雑記]Demoday .Tokyoに登壇しました - オープンソースエコシステム #demodaytokyo

$
0
0

本日渋谷dots.にて開催されたプレゼンテーションイベント、 Demoday.Tokyo #0 に登壇させていだきました。


f:id:shu223:20151129133211p:image:w600


どんなイベントかというと、

昨今、アメリカを中心に盛り上がりを見せている「Demo Day」カルチャー。

クリエイターが集い、自らの作品をデモンストレーションする。

それが、Demo Dayです。(Demoday.Tokyo トップページより)

というわけで、「自らの作品」をデモする場です。


で、僕が話した内容はこちらになります。



仕事以外の、プライベートでやっていること、とのことだったので、iOS Sampler について紹介しつつ、さらに技術の勉強がてらオープンソースにするといいことありますよ、というお話をさせていただいた感じです。


所感

開催前の1週間は、本イベントの元ネタである NEW INC Showcase のサイトの、


f:id:shu223:20151213164620j:image:w400


こんな展示画像を見て、「こんなアーティスティックな作品が集まる場でiOSのサンプルコードが云々って、完全に場違いなんじゃ・・・」と恐々としまして、正直逃げ出したい気持ちもありましたが、結果的にはiOSプログラマー以外の方々にも iOS Sampler の活動について紹介する良い機会になったし、色々なおもしろい活動をされている方々とも知り合えて、本当に参加させていただけてよかったなと。



ちなみにイベント全体のレポートが近日中に公開されるそうです。主催のみなさま、登壇者のみなさま、来てくださった方々、どうもありがとうございました!



[openFrameworks][Mac]『Flying Tokyo #15 Rulr Workshop』受講メモ1日目 #rzmr_ws

$
0
0

Flying Tokyo #15 Rulr Workshop という Rhizomatiks Research 主催の2日間のワークショップを受講しています。本日1日目のメモ。


※アプリケーション自体はまだ公開じゃない気がするので、ダウンロードURL等は控えておきます。写真はOK(NGと明言されたもの以外)とのこと。


ワークショップ概要

http://www.rzm-research.com/rulr/ より)

Elliot氏について

「RULR」の開発者でありアーティストのElliot Woodsが来日し、講師をつとめます。アシスタントは画像認識、画像処理を組み合わせた作品を多く手がけるライゾマティクスリサーチのシニアエンジニア、花井裕也。二日間にわたり、インストールから実際のキャリブレーション、3Dスキャナの創作まで実践的な内容を行います。

RULRとは?

「RULR」は、カメラやキネクトなどのデバイスを用いて、リアルタイムの空間キャリブレーションを可能にする、オープンソースのツールキット。リアルタイムのグラフィックをopenFrameworksやVVVV、Processingなどを用いて生成し、物理空間との融合でインタラクティブなビジュアル体験を生み出すためのものです。例えば、キャリブレーションの結果を動く物体へのハイライトに反映したり、インスタレーションの訪問者の顔の3Dロケーションをカメラによって提供するなどの機能があります。

ちなみに「ルーラー」と発音されていました。


RULRインストール方法

Mac版はライゾマメンバーの方々が今回のワークショップにあたって作成したとのこと。たぶんまだ公開版ではないのでダウンロードリンク掲載は控えておきます。


アプリケーションの操作方法

Patch Panel
  • ノード以外のところをドラッグするとパッチパネルのスクロール
  • ズームは普通のmacの操作
  • ダブルクリックで新規ノード追加
  • ノードを繋ぐときは input pin をドラッグする
  • ノードの接続の解除は、input pin を右クリックする
World Panel
  • 普通にドラッグで回転
  • 右クリックしながらドラッグでズーム
  • Hキーを押しながらドラッグでカメラを上下左右に移動
  • Rキー長押しでリセット

カメラキャリブレーションの手順

準備
  • 1. Item::Camera ノードを追加
    • デバイスは Webcam を選択
    • Inspector Panelの "Clear device" でクリアできる
  • 2. Item::Board ノードを追加
    • 縦横のセル数とサイズを実際に使うボードを合わせる(デフォルト 10x7 0.05m)
  • 3. Procedure::Calibrate::CameraIntrinsics ノードを追加
  • 4. 3の input pin を1,2に繋ぐ
キャリブレーション
  • 5. 3を選択してアクティブにした状態で、カメラにチェッカーボードをかざす(全体が移るように)
  • 6. 認識すると赤線が出るので、スペースキーを押す
    • 「プニョ」的なSEが鳴る
    • →キャリブレーション結果が記録され、画面に粒々が出る
  • 7. 5,6をカメラの画角内のいろんな位置で最低20回ぐらい繰り返す
    • 回数は右のInspector Panelで確認できる
確認
  • 8. Demo::ARCube ノードを追加する
  • 9. 8の input pinを1,2に繋ぐ
  • 10. 8をアクティブにした状態で、カメラにチェッカーボードをかざすと、チェッカーボード上にキューブが表示される(チェッカーボードを動かしても追随する)

f:id:shu223:20151219195210j:image:w600


Coding基礎編

ここでoF実装の基礎編的な話。Rulr とは直接関係ない、oF/C++の一般的な話なので、割愛します。(個人的には普段oF/C++書いてないので大変ありがたかったです)


サンプルコードが下記にあります。


プロジェクタ & Kinect のキャリブレーション

準備
  • 1. Item::Kinect ノードを追加
  • 2. Item::Projector ノードを追加
  • 3. System::VideoOutput ノードを追加
  • 4. Procedure::Calibrate::ProjectorFromDepthCamera ノードを追加
  • 5. 4のinput pinを1,2,3に繋ぐ
キャリブレーション
  • 6. VideoOutput をアクティブにして、Inspector Panelの Show Window ボタン(or Return キー)を押す
    • → チェッカーボードがプロジェクタから投影される
  • 7. スクリーン(会場では壁)の位置、スクリーンより少し手前でそれぞれ Capture ボタン(or Space キー)を押す
  • 8. 最後に Return キー(キャリブレーション実行)
確認
  • 9. Render::NodeThroughView ノードを追加
  • 10. 9の input pin を1,2,3に繋ぐ
  • 11. 4の input pin と 3 との接続を解除しておく

f:id:shu223:20151219195301g:image


キャリブレーション情報のエクスポート

Item::Projector を選択した状態で、Inspector Panel の Export ofxRay ボタンをクリック。(デフォルトのファイル名は Projector.ofxRayCamera)


サンプル作成

Elliotさんが基本的にWindowsユーザーで、Macですぐに動くサンプルがなく、かといって全員が一から実装していたらワークショップが終わらないので、以下の手順でサンプルを作成。

  • ofxMultiKinectV2 の example_pointcloud を複製する

- パスの設定がおかしくなるので別フォルダに移動させない

  • ofxRay を追加する

- Elliot さんによるとここの作業で projectGenerator を使わないほうがいい、とのこと

- マニュアル追加してからsrcフォルダ以外をremove

  • [Build Settings] > [Header Search Path] を追加
../../../addons/ofxRay/src
  • ofApp.cpp を改変
#include "ofxRay.h"
ofxRay::Camera projector;
    • setup() の最後に以下を追加
auto result = ofSystemLoadDialog("Select ofxRay::Camera file for this projector");
if (!result.bSuccess) {
    ofExit();
}
ifstream filein(ofToDataPath(result.filePath), ios::binary | ios::in);
filein >> this->projector;
filein.close();
    • draw() の `ecam.begin()` 〜 `ecam.end()` の部分を ofxRay::Camera オブジェクトを使ったものに置き換える。
if (mesh.getVertices().size()) {
    ofPushStyle();
    glPointSize(2);
    
    projector.beginAsCamera();
    {
        ofDrawAxis(100);
        ofPushMatrix();
        ofScale(0.01, 0.01, 0.01);
        mesh.draw();
        ofPopMatrix();
    }
    projector.endAsCamera();
    
    ofPopStyle();
}

f:id:shu223:20151219195501j:image


所感


とつぶやいた通り、行く前は本当に恐れていたのですが、Elliotさん自身はたぶんそんなに初中級者を振り落とす感じではなく、「oFはさわったことある?」「ポインタは知ってる?」とひとつひとつ丁寧に教えてくれる姿勢だったし、作業に遅れが出る人がいてもライゾマの方々が総出でトラブルシューティングにあたってくれてました(Elliotさん自身も)。


ただ作業自体にはついていけたものの、普段Kinectやプロジェクタとあまり縁がないので、「キャリブレーション」と一口に言っても、もともとどういうズレがどの位あって、どの値を、何を基準に、どのようにキャリブレーションしているのか、といった本質的な部分がパッとイメージできず、そのあたりは結構両隣の受講者の方々に質問させていただきました(助かりました!)。でもこのあたりは一度自分でキャリブレーションなしで試して、キャリブレーションしないとどうにもならないわーということを体感しないとどうにも腹落ちはしないかな・・・とも思います。


個人的には明日の「3Dスキャナの創作」というパートに興味があるので、明日もついていけるようがんばります。


関連記事


[雑記]積読本消化ルール 2015

$
0
0

うちは二人暮らしで36平米とそんなに広くないので本棚は置いてなくて、備え付けの靴箱の余った棚に本を入れています。


2年半前に 海外に行くことになった 際にいったんすべての本を電子化したのでしばらくはそれでよかったのですが、東京に再び住み始めて早2年、さすがに靴箱に収まりきるわけはなく、そこに収まりきらない本はAmazonの箱に入ったまま。。9割は表紙をめくったこともない、というか注文したっきり忘れている。。


で、この年末年始に積読を解消するぞ!と思うわけですが、自分と37年もつきあってると、さすがにわかります。実家に本を大量に持ち帰ったところで、1冊も読まないということが。。


そして何も年末年始にやりたいことは積読本消化だけじゃなくて、

  • FacebookでSaveした記事
  • PocketにSaveした記事
  • QiitaでStockした記事
  • OneTabで収納した記事

等々、「これはあとで絶対に読むべきだ!」とアーカイブしたWeb記事もたまりにたまってるわけでして、あとTODOリストも色々なところに書き散らかしてるのでそれを一旦整理したりとか、とにかく年末年始にやりたいことは積読本消化以外にもたくさんあります。


そんなわけで、積読本消化作業に取り掛かる前に、「ルール」および「分類方針」を決めることにしました。


f:id:shu223:20151227204637j:image:w600

(※うちの本棚ではなく、ただのイメージ写真です)


ルール

雑誌を含むすべての書籍を取り出し、以下の4つに分類する

  1. とっておく
  2. 収納サービス *1 に出す
  3. スキャン代行サービスに出す
  4. 捨てる

「1. とっておく」への分類方針

まず大前提として、とっておく本は棚(幅60センチぐらい、1段)に収まる量に留める。スペースがない、という問題もあるが、いくら「良書」でも、これ以上の量ををとっておいてもどうせ来年も目を通す時間はないと思われるため。

  • 来年強化したい分野の技術書
    • 「ちょっとやろうと思って買ったけど当面やらなそう」な技術書は2か3へ(僕の場合、node.js 関連とか)
  • パラパラと眺めたい系の書籍
    • これを眺めてる時間があったら他のことをした方が有意義だ、と思える程度のものは 3 or 4 へ

はここに分類しつつ、棚に収まらない分は2 or 3 or 4へ。


「2. 収納サービスに出す」への分類方針

迷ったり先送りにしたくなったらここに分類する。時間が一番大事。

  • 1,3からは漏れるが、pdfにすると読みにくい書籍とか、装丁的に惜しい書籍
    • 綺麗に3色刷りされた技術書とか。読むなら紙書籍でパラパラ読みたい、でも来年はその時間なさそう、みたいなものをとりあえず預けておく
  • 1,4から漏れた読み物系書籍
    • pdfにすると読まなそうなので紙版でとっておきたいが、今すぐには読まなそう、でも廃版もありそうなので捨てられない、みたいなもの。

「3. スキャン代行サービスに出す」への分類方針

「1.とっておく」にはあてはまらないけど「4.捨てる」には惜しい、という場合は基本ここ。(2はここの救済措置的な位置付け)


これまでにスキャンしてpdfにした書籍が既に数百冊あり、技術書は必要に応じて参照することはあるが、残念ながら読み物系はマンガ以外ほぼ目を通したことがない・・・ということを鑑みて、「pdfにしても読まなそうな本」は4へ。


「4. 捨てる」への分類方針
  • pdfにしても読まなそうな本
    • 既にpdfにした数百冊の本より読むべき優先度は高いのか?
  • 電子版が買える本
  • 新品なり中古なりで買い戻せる本
    • それなりに定番化してるものとか、数が出たものとか


さて、とりかかります!(あてはまらないものが出てきたらまたルールおよび分類方針を追記します)


(追記)経過メモ

Amazonの箱を開けていく過程で、この結構高い本(7500円!)を2冊も買ってることが判明・・・


Processing:ビジュアルデザイナーとアーティストのためのプログラミング入門
ベン・フライ ケイシー・リース
ビー・エヌ・エヌ新社 (2015-09-20)
売り上げランキング: 155,869

*1:いつも利用しているのは minikura 。箱単位で預けられる。

[制作実績][iOS][IoT][フリーランス]フリーランス2年目の振り返りと反省

$
0
0

2014年2月に独立して、ほぼ2年が経ちました。今日は大晦日ということで、2015年の仕事やらプライベート活動やらを振り返ってみたいと思います。

仕事

今年は全部で13社の開発をお手伝いさせていただきました。


多くの企業様と関わらせていただきましたが、合計10人日以上お手伝いしたのはうち4社だけで、1日や2日だけのところもあります。


・・・という話をするとたまに誤解されることもあるのですが、僕はアドバイザー・コンサル的な仕事はやってなくて、手を動かしてプログラムを書く仕事だけをやっています。(技術顧問としてプレスリリースがあった Sansan さんでも、普通にBLE関連機能の開発をしつつ、ちょっとミーティングにも同席したりもしますという感じでお手伝いさせていただいています)


自分のフリーランスとしての働き方・考え方等はこちらの記事に書いてあります。


f:id:shu223:20151231175554j:image:w400

大晦日(今日)に届いたBONX!


イベント・勉強会への登壇

技術勉強会

新しい技術を勉強しなきゃとは思いつつも誰からもプレッシャーがないフリーランスという身なので、勉強会発表ドリブン *1 で興味のあることを勉強するようにしています。

自分の勉強のためにやっていることではあるのですが、毎回新しく調査して、サンプルつくって検証して、というところからやってるので、調査・発表資料作成を合わせると、丸1日〜3日ぐらいかかっていて、お仕事との兼ね合いが毎回大変です。。


イベント登壇

こっちは技術勉強会とは目的がちょっと違ってて、どっちかというと「iOSアプリ開発を頼める誰か」ではなく「iOSエンジニア堤」を立てたい的な意味合いで、お声がけいただければできるだけ出るようにしています。

ただ自分のトーク力は「いかにもエンジニア」レベルで、話を聞きに来ていた方から次の登壇の依頼が来て・・・と繋がっていかないので、このへんは出させていただくからにはもっとしっかりしないとなぁ、と。


インタビュー等

プライベートワーク

書籍執筆

順番的に記事の下の方での登場になってしまいましたが、BONXと並んで今年一番時間をかけた仕事の一つ。

本気か冗談か、「本の印税で儲かってるんでしょ〜」と言われることがありますが、技術書なんてもともと部数が出ないジャンルで、その中でも Bluetooth Low Energy という超ニッチな分野。どう転んでもベストセラーにはならないでしょうし、開発仕事を数日やった方が儲かる、というレベルです。そして人にもよると思いますが、本を書くというのはかなりの苦行で、開発仕事の方が遥かに楽しいです。本書も例によってかなりの難産でした。。


そんなニッチな本著ですが、この分野に参画する人達の間で地道に売れ続け、なんと増刷の運びになりました。達人出版会さんで販売されている電子書籍版もアップデートされています。サンプルも Swift 2 / Xcode 7 / iOS 9 対応済み です。


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

オープンソース

今年新規公開したもの。

これも地味に大変で、ほっとくと仕事でスケジュールを埋めてしまうので、あえてこれらに取り組む日を確保しておいて開発を進めつつ、正式リリース日が発表されたらその日もオフにしてブログ公開とGitHubでのソース公開に備えたりしてます。


リリース前の感覚として、iOS 9 はあまり開発者の興味を集めてない気がして、iOS-9-Samplerもあんまりニーズないかもなぁ。。とか思ったりしてましたが、出してみると例年通りの反響があり、やはり時間をかけて準備した甲斐があったなと。というわけできっと iOS-10-Sampler もやると思います。


あと Google/Eddystone のコントリビュータになるべくプルリクがんばったり、


もちろん過去にアップしたリポジトリのメンテも。


ハッカソン参加
プライベート開発
  • とあるカジュアルゲームアプリ
    • 友人と週末に開発を進めている
    • 月1日できるかできないか、ぐらいの開発ペースなのでいつリリースできることやら。。

反省

  • ブログをあまり書かなかった

制作実績や、勉強会での発表については書かないともったいないので書いてましたが、それ以外の日常の開発で得た開発ノウハウについてはほとんど書けず。12月になってアドベントカレンダードリブンで何記事か書いたぐらい。


この メモをアップするメソッド でブログ書きまくってた頃とは色々状況が違うので、今にフィットする方針を考え直さないと、と思っています。


  • 新しい専門領域を開拓できなかった

2014年はBLEというちょっとニッチだけどあまりそこで経験・実績のある人がいない分野を開拓することができました。今年は「海外から仕事を受ける」という新しい挑戦は始まったものの、そしてBLEに関してはより深掘りできたものの、「新しい技術的な強みの獲得」という面ではあまり何もできなかったなと。(今年よくやった新しい分野の仕事として「watchOS」もあるのですが、こちらは技術的な面ではあまり強みとはいえないと思っています)


足がかりはいくつかできたので、来年がんばります。


来年の抱負

当面は海外のお仕事をがんばります。年明けからベルリンに *2 行ってきます!



*1:発表ネタをつくらなきゃというプレッシャーを自らに課す

*2:バンベルクのスタートアップとは別の、新しいお客さんとのお仕事

[Deep Learning][機械学習][Python]Caffe(PyCaffe)のインストールでハマったメモ

$
0
0

Caffe をインストールしてて大いにハマった際の、トラブルシューティングメモ。


環境は Mac OS X 10.11 El Capitan です。


問題1: numpy のバージョン違いと El Capitan の System Integrity Protection

PyCaffe をビルドしたあと動作確認として

$ python 
>>> import caffe

ってやると、

RuntimeError: module compiled against API version a but this version of numpy is 9

って怒られた。


そこでnumpy をアップデートしようと、

$ sudo pip install -U numpy

をしたら、パーミッションがどうのこうの、どうやら El Capitan の "System Integrity Protection" という新機能が邪魔をしてるらしい。


$ sudo pip install --upgrade numpy --ignore-installed six

ってやるとコマンドは通るが、古いnumpy(1.8.0rc1)がまたインストールされるだけ・・・

Collecting numpy
  Downloading numpy-1.10.2-cp27-none-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (3.7MB)
(中略)
Successfully installed numpy-1.8.0rc1 six-1.4.1

対処1: HomebrewでPythonをインストール & numpyアップデート

あれこれ試してうまくいかず困って、こちらの Mario さんの回答 を参考に(ベストアンサーの System Integrity Protection を無効にする方法は怖いのでやらなかった)Homebrew で Python をインストールして、

$ brew install python

その後もう一度

$ sudo pip install -U numpy

したら最新の 1.10.2 にアップデート成功。

$ sudo pip list
numpy (1.10.2)

ただ `$ brew doctor` してその指示に従って `$ brew prune` したりもしたのでそちらが効いたのかもしれない。。


問題2: 古いnumpyが利用される

numpyのアップデートに成功したものの、まだ

>>> import numpy
>>> print numpy.__version__
1.8.0rc1

となる。(1.10.2 の方を見ていない)


パスを出力してみると、Mac標準の方が使用されている。

>>> import numpy
>>> print numpy.__path__
['/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy']

この記事 に書いてある方法だとMacに標準で入ってた方をリネームしているが、そういう操作は El Capitan だと怒られるので基本的にできない。


対処2: 環境変数のPATHを変更

python コマンドの場所を見てみる。

$ which python
/usr/bin/python

PATH の優先度を変更するため、~/.bash_profile を編集

  • 修正前
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin
  • 修正後
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin

反映

$ source ~/.bash_profile

確認

$ which python
/usr/local/bin/python

問題3: Segmentation fault: 11

このままmakeやらをやりなして動作確認しようとしたら、

>>> import caffe
Segmentation fault: 11

でクラッシュ。

対処3: Makefile.config を修正

こちらのページ を見ていて思い出したが、Python の場所を変えたので Makefile.config のパスを修正してから諸々やりなおさないといけない。


  • 修正前
PYTHON_INCLUDE := /System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 \
    /usr/local/lib/python2.7/site-packages/numpy/core/include/
  • 修正後
PYTHON_INCLUDE := /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/include/python2.7 \
    /usr/local/lib/python2.7/site-packages/numpy/core/include/

  • 修正前
PYTHON_LIB := /usr/lib
  • 修正後
PYTHON_LIB := /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib

問題4: ValueError: unknown locale: UTF-8

import caffe したら今度は

ValueError: unknown locale: UTF-8

ってのが出た


対処4: ビルドのやりなおし

http://stackoverflow.com/questions/19961239/pelican-3-3-pelican-quickstart-error-valueerror-unknown-locale-utf-8:こちらの回答] の通りに

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
$ source ~/.bash_profile 

動作確認

インタプリタを起動して

>>> import caffe
>>> 

やっと成功・・・!



こういう苦労の果てに書いた記事がこちら:


[Deep Learning][機械学習][Python][画像処理]ディープラーニングの有名ライブラリ5種を最短距離で試す半日コース(TensorFlow, Chainer, Caffe, DeepDream, 画風変換)

$
0
0

「いつか勉強しよう」と人工知能/機械学習/ディープラーニング(Deep Learning)といったトピックの記事の見つけてはアーカイブしてきたものの、結局2015年は何一つやらずに終わってしまったので、とにかく一歩でも足を踏み出すべく、本質的な理解等はさておき、とにかく試してみるということをやってみました。


試したのは、TensorFlow、Chainer、Caffe といった機械学習およびディープラーニングの代表的なライブラリ/フレームワーク3種と、2015年に話題になったディープラーニングを利用したアプリケーション2種(DeepDream、chainer-gogh)。


f:id:shu223:20160105091448j:image:w600

(DeepDreamで試した結果画像)


タイトルに半日と書きましたが、たとえばTensorFlowは環境構築だけなら10分もあれば終わるでしょうし、Chainerなんてコマンド一発なので5秒くらいです。Caffeは僕はハマりましたが、うまくいった最短手順を書いているので、同じ環境の方はすんなりいくかもしれません。


おすすめは、Chaffe&DeepDream(要Caffe) は飛ばして、TensorFlow, Chainer&画風変換を試すコースです。環境構築にハマらないので簡単に終わると思います(実行時間はかかりますが)。僕のように「気にはなってたけど全然触ってない」という方はぜひ今日の昼休みにでもお試しください!


試した環境:

  • Mac OS X 10.11.1 El Capitan
  • Xcode 7.2 インストール済み

TensorFlow

2015年11月に発表された、Google製の機械学習ライブラリ。「テンソルフロー」と読むそうです。同社のサービスでも実際に使われているとのこと。

よく話を聞く音声認識や翻訳だけでなく、Googleフォトの被写体認識や顔認識、ウェブ検索結果の最適化、Gmailのメール分別、新生メールソフトInboxの自動返信文作成、さらにYouTubeや広告事業まで、ほとんどのプロダクトを支える新たな根幹技術となっています。

TensorFlow の特徴は、データフローグラフとして表せればなんでも処理でき、その気になればローレベルのオペレータも手書きできる汎用性、Googleの実製品で使われる高いパフォーマンス、CPUでもGPUでも走りノートPCから巨大なデータセンターまで同じコードで動きモバイル端末にもデプロイできるスケーラビリティ、計算機科学の研究から実プロダクトまで扱える効率性、ドキュメンテーションやサンプルが揃いPythonでもC++でも書ける扱いやすさなどなど。


オープン化の狙い

ライセンスは商用利用も可能な Apache 2.0 で、自社製品のコアにもなっているこんなすごいものをなぜ Google はオープン化したのか?というところは気になるところです。

TensorFlowをオープンソース化することで、学術研究者からエンジニア、趣味として取り組むユーザーまで、あらゆる人々の機械学習コミュニティーが、研究論文よりも動作するコードを介してアイデアを格段にすばやく交換できるようになると期待している。これが機械学習に関する研究の促進につながり、最終的に技術がすべての人々にとってより適切に機能するものになるだろう。さらに、TensorFlowの応用分野は機械学習だけにとどまらない。タンパク質のフォールディングから宇宙データの処理にいたるまで、非常に複雑なデータの解明に取り組むあらゆる分野の研究者らにとって有用であるかもしれない。


Googleいわく、機械学習はこれからの画期的なプロダクトや技術に欠かせない重要な要素となるもので、世界中で研究が進められているものの、標準となるツールが存在していないことが課題。Google では TensorFlow を研究者から学生、製品開発者まで使える標準ツールとして提供することで、機械学習や機械知能そのものの研究と普及を加速したい考えです。


環境構築手順(所要時間:10分)

OS X El Capitan (10.11.1) へのインストール手順です。


1. pip をインストール

$ sudo easy_install pip

2. Virtualenv をインストール

$ sudo pip install --upgrade virtualenv

3. Virtualenv 環境を作成(下記コマンドだと `~/tensorflow` につくられる)

$ virtualenv --system-site-packages ~/tensorflow

4. つくった環境をアクティベート

$ source ~/tensorflow/bin/activate

→ コマンドプロンプトが変わる


5. TensorFlow をインストール

(tensorflow)$ pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl

Successfully installed numpy-1.10.2 six-1.10.0 tensorflow-0.5.0


以上です。


動作確認:Hello World を実行してみる

スクリプトを作成し、適当なファイル名で保存します。

import tensorflow as tf
import multiprocessing as mp
 
core_num = mp.cpu_count()
config = tf.ConfigProto(
    inter_op_parallelism_threads=core_num,
    intra_op_parallelism_threads=core_num )
sess = tf.Session(config=config)
 
hello = tf.constant('hello, tensorflow!')
print sess.run(hello)

TensorFlow 環境で実行します。

(tensorflow)$ python {ファイル名}.py

実行結果:

I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4

I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4

hello, tensorflow!


参考ページ:


手書き数字を学習してみる

TensorFlow オフィシャルページに、「MNIST For ML Beginners」という手書き文字データセットを利用したチュートリアルがあります。

f:id:shu223:20160105090618p:image

(MNISTデータセット)


ここでは一番手っ取り早そうな、公式チュートリアルのコード(GitHubにある)を実行する方法を試すことにします。


ソースコードを clone してきて、

$ git clone --recurse-submodules https://github.com/tensorflow/tensorflow

fully_connected_feed.py の30,31行目を次のように修正します。*1

  • 修正前
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.examples.tutorials.mnist import mnist
  • 修正後
import input_data
import mnist

fully_connected_feed.py を実行します。

$ cd tensorflow/
$ python tensorflow/examples/tutorials/mnist/fully_connected_feed.py 

MNISTデータセットを手動でダウンロードしたりする必要はなく、このスクリプトがデータセットの取得からモデルの学習までやってくれます。


実行結果:

Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.

Extracting data/train-images-idx3-ubyte.gz

//中略

Step 0: loss = 2.32 (0.025 sec)

Step 100: loss = 2.19 (0.003 sec)

Step 200: loss = 1.97 (0.003 sec)

//中略

Step 1900: loss = 0.46 (0.004 sec)

Training Data Eval:

Num examples: 55000 Num correct: 49489 Precision @ 1: 0.8998

Validation Data Eval:

Num examples: 5000 Num correct: 4534 Precision @ 1: 0.9068

Test Data Eval:

Num examples: 10000 Num correct: 9019 Precision @ 1: 0.9019

データセットのダウンロード、トレーニング、テストデータでの評価が行われています。最終的な精度は約90%。


参考ページ:


学習結果を可視化する TensorBoard を試す

なんと、学習結果をグラフにしてくれたり、モデルをビジュアライズして表示してくれる TensorBoard というものも用意してくれているようです。


学習経過のログデータのあるディレクトリを絶対パスで指定 *2 して `tensorboard` コマンドを実行すると、

$ tensorboard --logdir=/Users/xxxx/xxxx/tensorflow/tensorflow/data

TensorBoard が起動します。

Starting TensorBoard on port 6006

(You can navigate to http://localhost:6006)


で、このURLにブラウザからアクセスするとGUIが表示され、


学習回数とxentropy_mean(交差エントロピー)の関係を示すグラフや、


f:id:shu223:20160105090658j:image:w400


モデル(ニューラルネットワーク)を可視化したものを見ることができます。


f:id:shu223:20160105090721j:image:w538


More

Chainer

Preferred Networks社が開発したニューラルネットワークを実装するためのライブラリ。2015年6月公開。特徴としては、

  • Python のライブラリとして提供
  • あらゆるニューラルネットの構造に柔軟に対応
  • 動的な計算グラフ構築による直感的なコード
  • GPU をサポートし、複数 GPU をつかった学習も直感的に記述可能

が挙げられています。


TensorFlow との比較

上記特徴を見ると TensorFlow とポジショニング的には似ているように見えたので、どんな違いがあるのかググッてみました。

たぶんできることそのものに大きな違いはないんだろうけど、Chainerの場合マルチGPUにするときには自分でGPUの管理をしなきゃなんないのが、TenrorFlowだともうちょっとラクなのかなあと思ったりする。


TensorFlow、GPU使うのにリビルドが必要で、そのためにbazelが必要で、そのためにJava8が必要で、しかもGPUにCC3.5以上の制約があるみたいで、使えるなら使えば?感が凄い。同じPythonならChainerの方が敷居が低く感じる。


TensorFlowはDistBeliefの2倍の速いそうなのですが、Chainerはそれを上回っていました。

記述量的にはそこまで変わらないですし個人的にはChainerの方が扱い易いというのが感想です(慣れの問題だとは思いますが。)。


TensorFlow,Chainerとも精度は同じでした。そもそもMNISTは問題が簡単なのでDeep Learningでなくても高い精度が出るそうです。実行時間はChainerの方が速かったのです。


インストール手順(所要時間:5秒)

公式ドキュメントに Install Guide というページがあるのですが、Ubuntu, CentOS 向けに書かれているようなので、Mac向けのはないかなと探してたら、本家Webサイトに QUICK START という項目がありました。


やることは

$ pip install chainer

これだけ。


Successfully installed chainer-1.5.1 filelock-2.0.5

素晴らしい!


手書き数字を学習してみる

公式リポジトリにサンプルが用意されています。cloneしてきてスクリプトを実行するだけ。

$ git clone https://github.com/pfnet/chainer.git
$ python chainer/examples/mnist/train_mnist.py

MNISTデータセットのダウンロードと、学習、テストが行われます。

load MNIST dataset

Downloading train-images-idx3-ubyte.gz...

(中略)

epoch 1

graph generated

train mean loss=0.190947790003, accuracy=0.942850003242

test mean loss=0.0990746175707, accuracy=0.96930000484

(中略)

epoch 20

train mean loss=0.0104963570454, accuracy=0.996966669559

test mean loss=0.102703116325, accuracy=0.982000006437

最終的な識別精度は98%になったようです。


More

Caffe

C++で実装されたディープラーニングのオープンソースライブラリ。カリフォルニア大学バークレー校の研究センターBVLCが中心となって開発、C++・Python・MATLABで利用可能。


具体的な公開日はわかりませんが、ChainerやTensorFlowの登場以前から存在する分、ネットで見つかるおもしろそうなディープラーニングを利用した研究や試みはCaffeをベースにしたものを多く見かける気がします。


環境構築手順(所要時間:約4時間)

所要時間は個人差(環境差)があると思いますが、確実にTensorFlowやChainerよりは時間がかかると思います。依存ライブラリが多く、その中にはインストールの待ち時間が長いものがありますし、各自の環境に依存した設定を手動で行う必要があるので、そのあたりでハマることもあると思います。また個人的にはnumpyのバージョンが違うというエラーにかなり悩まされました。


GPUが絡むとハマりそうなのでCPUモードで、インストールしていきます。PyCaffeも入れます。


1. 諸々インストール

$ brew install --fresh -vd snappy leveldb gflags glog szip lmdb
$ brew tap homebrew/science
$ brew install hdf5 opencv
$ brew install --build-from-source --with-python --fresh -vd protobuf
$ brew install --build-from-source --fresh -vd boost boost-python
$ brew install openblas

※1 opencv のインストールはかなり時間がかかります。

※2 OpenBLAS は入れなくてもいいそうですが(Macでは標準でBLASが入っているとのこと)、この後の手順で Makefile の `BLAS_INCLUDE` のパスを修正したりしてから make を実行しても `fatal error: 'cblas.h' file not found` が出てしまうので、入れることにしました。


2. caffe をclone してきます。

$ git clone https://github.com/BVLC/caffe.git

3. Makefile.config を雛形からコピーしてきて、編集します。

$ cd caffe
$ cp Makefile.config.example Makefile.config

  • `# CPU_ONLY := 1` のコメントアウトを外す
  • `BLAS := atlas` を `BLAS := open` に変更する
  • 以下のコメントアウトを外す
# BLAS_INCLUDE := $(shell brew --prefix openblas)/include
# BLAS_LIB := $(shell brew --prefix openblas)/lib
  • `PYTHON_INCLUDE` のパスを自分の環境に合わせて書き換える *3
    • 修正前
PYTHON_INCLUDE := /usr/include/python2.7 \
    /usr/lib/python2.7/dist-packages/numpy/core/include
    • 修正後
PYTHON_INCLUDE := /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/include/python2.7 \
    /usr/local/lib/python2.7/site-packages/numpy/core/include/


4. ビルド&テスト。

$ make clean
$ make all -j4
$ make test -j4
$ make runtest

ここでエラーがでなければインストール成功です。

[ PASSED ] 927 tests.


5. caffe/python フォルダに移動し、PyCaffe に必要なライブラリをインストールします。

$ cd python/
$ for li in $(cat requirements.txt); do sudo pip install $li; done 

6. PyCaffe のビルド

$ cd ../
$ make pycaffe
$ make distribute

7. Caffe用の環境変数を設定します。~/.bashrc に下記を追記し、

export PYTHONPATH={caffe/pythonのパス}:$PYTHONPATH

`source ~/.bashrc` で反映します。


8. 動作確認

PythonのインタプリタからCaffeをimportしてみて、問題が起きなければOK。

$ python 
>>> import caffe

ちなみに本記事では最終的にうまくいった手順のみを書いていますが、大いにハマったトラブルシューティングの過程も別記事として書いておきました。


参考ページ:


DeepDream

ここからひとつレイヤーは上がって、ディープラーニングライブラリ/フレームワークを利用した応用アプリケーション的なものをいくつか試してみます。


DeepDream は 2015年7月にGoogleが公開 したOSSで、

画像から少しでも見覚えのある物体を見つけ出し、それを再構成して出力する

人工神経回路網は10〜30のレイヤーから構成されており、1枚目のレイヤーは画像の情報をインプットして「角」や「端」を探し、2枚目・3枚目と続くレイヤーは基本的な物体の情報を把握、最終的なレイヤーが情報を組み立てて物体が「何か」を判断する、という仕組みです。

というもの。


環境構築の手順(所要時間:10分)

要Caffe(インストール手順は上述)。Caffeさえ入っていればさっくり試せます。


1. iPython notebook を入れます。*4

$ pip install ipython
$ pip install ipython[notebook]

2. Caffe のあるフォルダと同階層に DeepDream のソースを clone します。

$ git clone git@github.com:google/deepdream.git

3. ここ から学習済みのcaffeモデルをダウンロードし、{caffeのパス}/models/bvlc_googlenet/ に保存します。


試す

cloneしてきたdeepdreamフォルダに移動し、iPython notebookを起動します。

$ cd deepdream
$ ipython trust dream.ipynb
$ ipython notebook

ブラウザが立ち上がるので、dream.ipynb を選択して、上部にある再生ボタンをポチポチ押していき、最後まで到達したらしばらく待っていると・・・ deepdream/frames/ フォルダに結果画像が 0000.jpg, 0001.jpg, ...と出力されていきます。


f:id:shu223:20160105091354j:image:w600

(左:0000.jpg と、右 0010.jpg)



手っ取り早く好きな画像で試したい場合は、sky1024px.jpg にリネームして同じ場所に置いておけばOKです。または dream.ipynb の画像名を指定している箇所を編集します。


さわやかな食事風景が、

f:id:shu223:20160105091426j:image:w600


こうなりました。

f:id:shu223:20160105091448j:image:w600



参考記事:


画風変換アルゴリズム chainer-gogh

mattya氏が2015年9月に公開した、Deep Neural Networkを使って画像を好きな画風に変換できるプログラム。


Chainerを利用。アルゴリズムの元論文は A Neural Algorithm of Artistic Stlye


環境構築の手順(所要時間:1分)

1. ソースを clone してきます。

$ git clone https://github.com/mattya/chainer-gogh.git

2. モデルを下記URLからダウンロードし、cloneしてきた chainer-gogh フォルダ配下に置きます。


実行する

お手軽にCPU実行してみます。コンテンツ画像(input.png)とスタイル画像(style.png)を用意して chainer-gogh フォルダ配下に置き、スクリプトを実行するだけ。

python chainer-gogh.py -m nin -i input.png -s style.png -o output_dir -g -1

f:id:shu223:20160105091523j:image:w600

(左:input.png、右:style.png)


f:id:shu223:20160105091655p:image

(結果画像)


今後の展望

今回は環境構築と既に用意されているサンプルを実行してみただけなので、次のステップとしては、下記記事の例のように、OpenCVを活用して自前データセットつくって、Chainer なり TensorFlow なりで画像識別をやってみたいと思っています。

ただデータセット収集はそれなりに時間かかりそうなので、下記記事のように既存のデータセットを Chainer および TensorFlow に食わせるところから始めるのが現実的かも。


また、iOSエンジニアとしては、モバイルデバイスでの利用についても模索したいと思っています。

あらかじめ学習済みモデルを用意して識別専用として利用するだけなら可能なのか、学習機能自体をモバイル側でやってみたらどんだけ重いのか(そもそもできるのか)とか。TensorFlow は「モバイル端末にもデプロイ可能」と謳ってますし。


あと、画像以外にも、自然言語処理への利用等も試してみたいです。


おわり。


*1:これをやらないと、実行時に "ImportError: No module named examples.tutorials.mnist" というエラーが出ます。

*2:パスが間違ってても TensorBoard は起動するのですが、アクセスしてもグラフ等は表示されません。

*3:`/usr/include` が最近のOSXでなくなってることに関しては、`$ xcode-select --install` をすればいいみたいなのですが、古いコマンドラインツールをダウンロードしないといけないっぽく、あまりXcodeまわりの環境をいじりたくないので直接pythonのincludeパスを指定するようにしました

*4:なぜか ipython: command not found になったので こちら を参考にインストールしなおしました

[機械学習][Deep Learning][iOS][Swift]Swiftで書かれた人工知能・機械学習ライブラリ「Swift-AI」をiOSで動かしてみる

$
0
0

全編Swiftで書かれたオープンソースの人工知能/機械学習ライブラリが出てきました。その名も「Swift-AI」。


デモが入っていて、こんな感じで手書き文字認識してくれます(詳細は後述します)。


f:id:shu223:20160124095306g:image


今のところ iOS と OS X をサポート しているとのこと。MITライセンス。


できること

README の Features を見ると、2016年1月現在、フィードフォワード(順伝播型)ニューラルネットワークと、高速行列演算ライブラリはできあがっているようです。


それぞれドキュメントがあります。


ベクトル・行列演算には Accelerate Framework を利用しているとのことで、パフォーマンス面も考慮されてそうです。


デモを試してみる

同梱されているデモプロジェクト「Swift-AI-iOS」を実行してみると、下記のように、「サイン波(sin)のグラフがあって、トレーニング開始するとオレンジの点の集合がそのサイン波のグラフに近づいていく」というものでした。


f:id:shu223:20160124095129j:image



・・・学習の過程を視覚化したデモなのかもしれませんが、ちょっとありがたみがわかりにくいなと。


で、そのXcodeプロジェクトの中を見てみると「HandwritingViewController」というソースコードがありました。


あれ、手描き文字認識のデモもあるのかなと思ってソースを追いかけてみると、どうやら他にもデモがあるらしい。デモを起動して画面を見てみて、もしや、と思い左上のSwift燕画像をタップしてみると・・・


f:id:shu223:20160124095428j:image

ハンバーガーメニューが出てきました。なんともわかりにくいUI。。


まぁそれはここでは本質的な問題ではないので置いといて、Handwriting のデモを試してみると、


f:id:shu223:20160124095306g:image


バシッと手書き認識してくれました。


手書き文字認識デモの実装

ライブラリの中身を読んでもたぶん理解できないので、あくまでライブラリを利用する側として、デモではどう実装しているのか「Handwriting」デモのソースを見てみました。


フィードフォワードニューラルネットワーク(FFNN)の準備

学習済みデータのファイルを指定して、FFNNクラスを初期化します。

let url = NSBundle.mainBundle().URLForResource("handwriting-ffnn", withExtension: nil)!
self.network = FFNN.fromFile(url)

ニューラルネットの準備としてはこれだけ。


手書き画像の領域を切り出す

認識するタイミングですが、本デモでは `touchesEnded` イベントが検出さてから0.4s以内に次の `touchesBegan` もしくは `touchesMoved` が検出されなければ認識処理が走るように実装されています。


で、手書き画像領域の切り出しは `scanImage()` というメソッドで行われています。

private func scanImage() -> [Float]? {
    var pixelsArray = [Float]()
    guard let image = self.handwritingView.canvas.image else {
        return nil
    }
    // Extract drawing from canvas and remove surrounding whitespace
    let croppedImage = self.cropImage(image, toRect: self.boundingBox!)
    // Scale character to max 20px in either dimension
    let scaledImage = self.scaleImageToSize(croppedImage, maxLength: 20)
    // Center character in 28x28 white box
    let character = self.addBorderToImage(scaledImage)
    
    self.handwritingView.imageView.image = character
    
    let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(character.CGImage))
    let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    let bytesPerRow = CGImageGetBytesPerRow(character.CGImage)
    let bytesPerPixel = (CGImageGetBitsPerPixel(character.CGImage) / 8)
    var position = 0
    for _ in 0..<Int(character.size.height) {
        for _ in 0..<Int(character.size.width) {
            let alpha = Float(data[position + 3])
            pixelsArray.append(alpha / 255)
            position += bytesPerPixel
        }
        if position % bytesPerRow != 0 {
            position += (bytesPerRow - (position % bytesPerRow))
        }
    }
    return pixelsArray
}

画像をクロップしたりリサイズしたり、といった処理は本ライブラリを利用するにあたって本質的な部分ではないので割愛しようと思ったのですが、あえて載せたのは、その後の処理に渡すにあたって、出力データの型が重要だと思ったからです。ポイントとしては、RGBAではなくA1チャンネルだけを取り出していること(手書き文字認識なので色情報は利用しない)と、UIImage型ではなくFloatの配列としてピクセルデータを返していること、といったあたりでしょうか。


認識処理の実行

上述した処理で取り出した手書き画像情報(Floatの配列)を引数に渡して、FFNNクラスの `update` メソッドを実行します。

let output = try self.network.update(inputs: imageArray)

認識結果を取り出す

先ほどの `update` メソッドの返り値である Float の配列は、数字0〜9を配列のインデックスとして、値には Confidence(信頼度/その数字である可能性の高さ?)が入っているようです。


なので、次のように、最も Confidence の高い数字(=認識結果)を探し、その認識結果の数字の値と、Confidenceを取り出しています。

private func outputToLabel(output: [Float]) -> (label: Int, confidence: Double)? {
    guard let max = output.maxElement() else {
        return nil
    }
    return (output.indexOf(max)!, Double(max / 1.0))
}

こうしてみてみると、実質的には

  • FFNNクラスの初期化
  • `update:` メソッドを呼ぶ

この2ステップだけで手書き文字認識ができていることがわかります。非常に簡単そうです。


自分のプロジェクトへの導入方法

CocoaPodsやCarthageはサポートしてないとのこと。

Swift is open-source now, and it remains to be seen how these dependency managers will cooperate with other platforms.


まだ試してないですが、デモプロジェクトを見る限り、

  • FFNN.swift
  • Storage.swift
  • FFNN+Storage.swift

あたりのファイルを追加すれば使えそうです。


他にも設定がいるかもしれませんが、ちゃんと動くデモプロジェクトが用意されているので、何かあればそちらと比較してみればよいかと。


所感

ピュアSwift、MITライセンスなオープンソースで、ちゃんとパフォーマンスも考慮されていて、簡単に使える、ということでかなり期待の持てるライブラリではないでしょうか。


今後いろんな学習済みデータや応用事例が出てくるとさらに楽しくなりそうです。


[Swift][iOS][海外]ドイツのSwift勉強会「swift.berlin #14」参加レポート #swiftberlin @swiftberlin

$
0
0

所用でドイツはベルリンに来てまして、1/18に開催されたSwiftのミートアップ「swift.berlin」に参加してきました。


f:id:shu223:20160130094509j:image


つい最近まで猛烈に英語に対して苦手意識があり *1、WWDC等でサンフランシスコ周辺に行く機会があってもあまりミートアップには参加してこなかったので、海外ミートアップ参加は3年ぶり人生2回目です。


概要

募集は meetup.com にて。


イベントページによると、参加人数は97人。実際に会場にそんなにいたかわかりませんが、50人は確実にいたと思います。


f:id:shu223:20160130094423j:image:w600


会場提供は wimdu 社、またビール等の飲み物もスポンサー(すみません、社名は失念)から提供されていました。


言語について

ドイツの公用語はもちろんドイツ語なわけですが、イベントは特に断りもなく(イベントページにそういう記載もなく)当然のように英語で始まり、その後のプレゼンも質疑応答もすべて英語でした。こちらでは当然なのかもしれませんが、日本ではなかなかないことなので、軽く一人でカルチャーショックを受けてました。。


※そういえば、前回参加したドイツのハッカソンでも当然のようにチーム内コミュニケーションもプレゼンも英語でした。


あと、こちらはプログラミング言語の話ですが、最初の主催者の方のトークで、「Swift書いてる人〜?」という質問があり、ほとんどの人が手を挙げていました。


で、次に、「まだObjective-Cしか書いてない人〜?」という質問があったとき、参加者側からクスクスと笑いが起きました。で、挙手した人はゼロ。


Swiftのミートアップなのでそりゃそうだという話はありますが、未だにObjCから移行しようとしないというのはそういうムードなんだなと。


発表1: Swift Package Manager

トップバッターは「try! Swift」にも登壇される Boris Bügling (@neonacho) さん。

Borisはベルリン在住のCocoaデベロッパーです。現在はContentfulでiOSのSDKを開発に携わっています。Java開発者としての一面や、たくさんのiOSアプリを開発した経験を持っています。彼はまたオープンソースの強力なコントリビュータでもあります。Xcodeをより使いやすくするためのプラグインを開発したり、“Senior VP of Evil”という肩書きでCocoaPodsの不具合を直しています。Ya tu sabes.(それじゃ、また。)

(try! Swift の紹介文より)


発表内容は先日のSwiftオープンソース化に合わせて公開された「Swift Package Manager」について。



簡単な使い方から始まり、現在の制限事項、自作パッケージのつくり方、テスト方法、パッケージマネージャの内部モジュールやビルドプロセスの解説、Packega.swiftの書き方、CocoaPodsやCarthageとの比較(この方は CocoaPods のコミッタでもある)等々、実に詳しい解説でした。


発表2: Beyond JSON with FlatBuffers

Maxim Zaks (@iceX33) さんの発表。JSONパーサ「FlatBuffersJson」について。



CocoaPods で swift, json で検索すると300以上のOSSが見つかるそうで、FlatBuffersSwift はその決定版になるとのこと。

そもそも FlatBuffers というのは Googleがゲーム開発またはパフォーマンスがクリティカルなアプリケーション用に作成 した serialization library だそうです。


発表3: Taking Swift to the Server

最後は Jens Ravens (@JensRavens) さんによる発表。Swift でサーバーサイドのコードを書く話です。



僕はサーバーサイドはできないので聞いてもポカーンとしそう、と思いましたが、スライドを見ればお分かりの通り、ブラウザにURLを入力するとHTMLが返ってくるまでにDNSサーバやアプリケーションサーバが何をするのかというところから始まり、リクエストやレスポンスをSwiftで書いてみましょう、次はルーティング処理を書いてみましょう、という感じでうまく噛み砕いて説明してくれて、わかりやすく面白かったです。


Swiftは今やとても人気のある言語ですし、Railsやnode.jsに代わるWebフレームワークの作者になれるかも、という一大チャンスが転がっている時期なんだということに今更ながら気づきました。この分野が今後どうなるか非常に楽しみです。


所感

各発表30分〜60分あり、プラス質疑応答は無限に受け付ける感じで、かなりのボリューム感でした。大変勉強になりました。またタイミングが合えばぜひ参加させていただきたいと思います。


ベルリンのデベロッパーの方々と知り合いになるべく発表側にもなってみたいところですが、発表枠を公募してる感じではないような気もします(僕がイベントを見つけたときには発表枠が決まっていた)。中心人物的な人に話しかけて「こういう発表がしたい」的なことを言えば入れてもらえるとかでしょうか。次回はもっとコミュニケーションもがんばろうと思います。


*1:ここ半年ほど、あえて英語を使わざるを得ない状況に自分を追い込むようにしていて、苦手意識はだいぶ改善されてきました


[海外][フリーランス][iOS][制作実績][働き方]第2回フリーランス海外遠征と2016年の生存戦略

$
0
0

1/12〜30の19日間、とあるスタートアップのお手伝いでドイツの首都ベルリンに行ってまいりました。


f:id:shu223:20160201082426j:image:w600

(今回の雇い主、Norman氏と、ベルリン大聖堂前にて。)


「あれ、前も行ってなかったっけ?」と思ったかもしれませんが昨年11月に行ったのは同じドイツでもバンベルクという都市で、今回とはお手伝いした会社も別です。


きっかけ

昨年9月に Hacker Paradise へ参加するためにベルリンに行った際にお会いした方よりご紹介いただきました。今回お手伝いした会社のCEO、Norman氏がiOSエンジニアを探してるという話が出た際に、僕のことを思い出して繋いでくれたと。


「フリーランスです、iOSが得意です、海外のお仕事大歓迎です」と何ができる/やりたい人かをなるべく多くの人に言っておくといいことある、とつくづく思いました。


条件面の調整

既にNorman氏の中でタスクリストとスケジュールが決まってて、全日程分の報酬+航空券+住居(後述)が最初のメールで提示されていました。僕を使うかどうか判断するための面接みたいなものはなく、たぶんLinkedInプロフィールやGitHubアカウントでスクリーニング的なことは完了していたものと思われます。


で、少しだけ金額面で交渉させてもらって *1、あとはスケジュールについて「順調にいけばそんなな感じのスケジュールで進むかもしれないけど、大抵なんやかんや想定外のことが起こるものなので、全部のタスクはできないかもしれないよ」というところは事前に言って承知していただきました。(このあたりの見積もりの考え方は こちらの記事 にも書きました)


やったこと

例によって詳しい内容はconfidentialですが、もちろんiOSアプリ開発ではあります。


利用技術的にはわりとオーソドックスなもの(一般的なUI+画像処理+ソーシャル機能)なので、漫然と既存スキルで時間を切り売りするようなことにならないよう、個人的なこだわりとして、なるべく「Swift的」な書き方を意識して書くようにしたりはしてました。(たとえば今まではCスタイルのfor文で書いてたところをSwiftスタイルで書いたりとか)


あと数年ぶりに In-App Purchase の実装をしたのも勉強になりました。*2


勤務時間は8:30〜17:30ぐらい。後述するように僕が住んでいたところがオフィスでもあるので、朝Normanが来て、一緒に仕事して、17:00〜17:30のキリがいいところでNormanが帰る、という感じでした *3


休日

当初の予定では 12日間 + 残りはフリータイムというスケジュールでしたが、10日で前倒しで作業が無事完了したので、余った2日分はお金いらないのでそこもフリータイムにしてほしい、と申し出ました。


というわけでまるまる1週間を自由に過ごせることになり、現地のSwift勉強会に行ったり、


f:id:shu223:20160130094423j:image:w600


あとは去年から始めたもののなかなか手を付けられてなかったプライベートな開発をやったりしてました。このへんはベルリンじゃなくてもできることですが、超有意義に過ごせたと思っています。*4


暮らし

オフィスが普通に住めるアパートなので、そこに住まわせてもらってました。ベルリンの一等地にあるビルの最上階にあり、見晴らしもよく、シャワーやら何やらすべて完備で最高に快適でした。


f:id:shu223:20160201083129j:image:w600

(オフィス兼宿。ベッドはロフトにあります)


食事は周囲にレストランがたくさんあるので、毎日「今日は○○料理が食べたい」みたいな感じでリクエストして、Normanにおすすめの店に連れて行ってもらう、みたいな感じで飽きることがなく、食生活の面でも充実してました。


英語

最近海外案件を受けるようにしているのは、単純に海外に行くのが楽しいし嬉しい、という以外に、ずっと苦手意識のある英語をそろそろ何とかしないと、ということで自分を英語を使わざるをえない環境に追い込むという目的もあります。


たかが2週間ちょっとでいきなり飛躍的に英語力が向上するわけもないのですが、マシになってきた気はします。Normanと飲みにいってわりと込み入った話をしたり。この仕様はこうこうこういう理由でおかしいからやめたほうがいい、と進言したり。まぁ、彼が文脈を大いに汲んで理解してくれる、というところも大きいですが。。


ただやっぱりまだまだまだまだ。なんというか、相手が自分のスキルを認めて雇ってくれて、こっちに歩み寄りつつコミュニケーションしてくれる、という前提の上であれば大丈夫なのですが、そうでないケースでの雑談とかはまだまだ厳しいです。引き続き機会を増やしていこうと思います。


今後の展望

まず、海外で仕事して毎回感じることですが、同じようなコードを書いてるだけでもめちゃくちゃ楽しいです。AutoLayoutのconstraintをポチポチ貼ってるだけでも「うぉー楽しい!」って思います。こういう高揚感は大事にしていきたいなと。


一方、これもベルリンだけでなくシリコンバレー等に行っても毎回感じることですが、無力感が半端ないです。仕事をやってみたりハッカソンに出てみたりして、技術的に通用しないということはないと思ってますが、誰も僕のことを知らないし(知名度以前に知り合いがいないという意味で)、そういう僕がベルリンに行ったところで、現地の他のスタートアップの方から「会いたい」とか言われることはありません。ミートアップに出ても誰にも話しかけられないし、ましてや人に紹介されることもありません。


で、自分から現地のスタートアップにアポとって会いに行ったり、ミートアップで話しかけたり、といったことをすればいいのですが、それは対症療法的だと思っていて、やはり日本でそうしてきたように、英語でブログ書いて、現地の勉強会でLTして、できれば英語で本を出す、ということをしないといけないなぁと。


たとえば僕の数々のBLE関連プロダクトに関わった経験・実績は世界のiOSエンジニアの中でも(今のところは)貴重な方だと思ってますが、


僕がニュースとかで海外のそういう系の魅力的なプロダクトを見るタイミングではもう遅くて(メディアに出て話題になっているということはある程度開発が進んでいるか完了しているケースが多い)ファウンダーが資金調達して本格的に開発をしようとするタイミングであちらから見つけてもらえるようにならないといけない。


で、LinkedIn や AngelList で人を探す場合は大抵「住んでいる場所」でフィルタされてしまうので *5英語ブログという「海外スタートアップに自分を見つけてもらうためのチャネル」を用意する必要があるなと。


僕のGitHubアカウントは今でも多少そういう感じの機能をしてくれてますが、

iOS Samplerシリーズのスター数に関して言えば、スクリーニングフェーズで僕が悪くないエンジニアであることを判断する材料にはなってるものの、海外に住んでるエンジニアを選ぶ「きっかけ」にはなっていない、と思っています。エンジニアにとって役立つ内容なので多くのスターをもらえてはいるものの、要素技術でみれば誰にでもつくれるものではあるので。


逆に、watchOS-2-Sampler はそんなにスターついてないけど、「(現時点ではニッチな)watchOS 2 の開発経験のあるエンジニア」というところで海外から僕を選ぶ「きっかけ」になってくれたわけで、そういうリポジトリを増やしていかないと、と。


長々と書きましたが、2016年の方針としては、もっと海外のお客さんに自分を見つけてもらえるように、

  • 英語でブログを書く
  • 「ニッチスキルに関わる」OSSをGitHubに積極的に上げていく
  • 海外にいったらLT枠とかに応募してみる

といったあたりをがんばっていきます。


*1:貴重な海外オファーなので最初に提示された価格でも受けたとは思いますが、普段の半分以下だったので一応

*2:数年前にローカルにまとめてた実装手順のメモがあったのですが、その頃のコードの酷いこと。。

*3:僕のプライベートを邪魔しないように気遣ってくれてるのか、いつもいそいそと帰る。あと絶対にいきなり部屋に来たりしない

*4:ひとりだとサボるので、現地で起業した日本人スタートアップのオフィスに毎日のようにお邪魔して作業させてもらったり、知り合いのエンジニアをさそってもくもく開発したりしてました

*5:本当にそうなのか実際のところ知らないのですが、住所がマウンテンビューだったときはめちゃくちゃメール来たのでそうだと思っています

[制作実績][iOS]4年ぶりに友人とカジュアルゲームをつくった話

$
0
0

もうかなり前のことになりますが、会社で働いていたころに、『モンスターを集めてまいれ』(1,2)や『タップ忍者』『KOFすれちがいバトル』『バウンドモンスターズ』『EncountMe』等々を一緒につくった盟友と言っても過言ではない嶋田さんという人がいまして、また一緒にゲームつくりませんかとお声がけをいただいて、実に4年ぶりに二人でカジュアルゲームをつくってリリースしました。


f:id:shu223:20160309053636p:image

スーパークエスト


ちょうど仕事が忙しい時期だったので、とある連休に嶋田さんちに行って半合宿状態で3日でつくりきる予定だったのですが、当然連休最終日にできたのはクソゲー、「これじゃ出せないな」ということで夜中・週末にチマチマ進めて今の形になりました。


最低限の機能でいいからとにかくいったんリリースまで漕ぎ着けよう、とリリースしたのが先週。で、クリティカルなバグの修正や、多少の改善を入れたアップデートが本日出たので、お知らせさせていただこうかと。


概要

昨今のひとクセふたクセあるカジュアルゲーム界にあって、わりと王道の放置系RPGです。



モンスターを倒して経験値とゴールドを稼いで、武器とか防具を買って強くなったらボスを倒して次のクエストへ・・・という一連の「あの」フォーマットを、片手でスキマ時間にお手軽に遊べるようにしてあります。


f:id:shu223:20160225155840g:image

(攻撃はスワイプするだけ)


f:id:shu223:20160225155917j:image

(マップ移動はスクロールするだけ)


その他詳しいアプリの紹介は、techjoさん(旧 iPhone女史さん)や、


スマホゲームCHさんの記事をどうぞ!



無料・アプリ内課金も一切なしなので、ぜひ!



ちなみに「スーパークエスト」というのはもともとスー◯ァミのカセットを模したアイコンデザインだったからで、お上から「第三者のハードウェアを彷彿とさせる」という理由でリジェクトいただきまして、こういうタイトルだけが残った、という経緯があります。。


f:id:shu223:20160225160042p:image


クレジットと技術面の話

  • 企画:嶋田さん
  • モンスター含むすべてのデザイン:嶋田さん
  • BGM・SE:嶋田さん
  • ドット絵風フォント:嶋田さん
  • ストーリー等の全テキスト:嶋田さん
  • レベルデザイン:嶋田さん
  • プログラム:堤

マップのタイルやモンスター、それらのアニメーションもぜんぶ嶋田さんの描き下ろし、そしてなんと、フォントまで嶋田さんの自作となっております。


f:id:shu223:20160225160116p:image



ではせめて、プログラム担当として、技術的な話を・・・


・・・書きたいところなのですが、本作では何も新しいことはやっていません。Unity も cocos2d-x も SpriteKit も OpenGL も Metal も使ってなくて、UIKit オンリーです。


まぁ、60fpsが要求されるようなヌルヌルアニメーションもないし、かつてのタップ忍者やバウンドモンスターズ *1 のようにアクション性のあるゲームでもないので、UIKitで十分かなと。タップ/スワイプで攻撃する部分でもしパフォーマンス的に厳しそうであれば SpriteKit か cocos2-x を使うつもりでしたが、手元の端末ではそこらへんも全然大丈夫でした。


ちなみに、嶋田さんはFlashとアニメーションの名人なので、プログラム的に動かしている部分はほとんどないです。ほとんどの動きはパラパラ連番アニメーション on UIImageView です。


今後の予定

比較的サクッとクリアできるバランスになってるので、ステージ追加はやる予定です。あと、HP回復待ちが長い、とお叱りのレビューをちょこちょこいただいてるので、一応放置ゲームなので待ちは仕方ないとして、もうちょっと待ちを楽しめるように何らかの対策は入れる予定です。今週末に作業するので、もうクリアしてしまった方は審査期間も考慮してアプリを削除せずにあと1週間ほどお待ちいただければと。


引き続き「スーパークエスト」をよろしくお願いします!


f:id:shu223:20160225155527p:image


*1:どちらも cocos2d を利用

[Swift][iOS]「try! Swift」1日目の復習 #tryswiftconf

$
0
0

iOSのカンファレンス「try! Swift」がいよいよ昨日から始まりました。恥をさらすようですが、半分ぐらいのセッションでリアルタイムについていけませんでした。。


ので既に上がっている発表資料やレポート記事を参照しつつ復習をしていこうかと。(WWDCもリアルタイムでは理解できないのでいつもスライドpdfが出てから自分のペースで手を動かしながら勉強する、というスタイルでやってます)


オーバービュー的な話、考え方的な話はありがたく参考にさせていただきつつ、ここでは主に実装面のセッションについて復習していきたいと思います。


実践的クロスプラットフォームSwift / Practical Cross-Platform Swift

Realm の JP Simard さんの話。

SwiftはApple以外のプラットフォームでも利用できるようになりました。iOSアプリ以外でも好きなようにSwiftを書けます。この講演では、CocoaやObjective-Cの機能を犠牲にせずに、クロスプラットフォームでSwiftを用いるときの実践的な書き方、テスト・デバッグ手法、について解説します。



開発環境

まず開発環境の話。できるだけ統一したいよねーというので、次の3つが挙げられていました。

  • Xcode
  • Xcode + Toolchain
  • Docker + CLI + Editor

そういう選択肢があるよねという話としてはわかるのですが、何が腹落ちしなかったのか考えてみると、

  • この3つのメリット・デメリットがよくわからない
    • たとえば、Xcode単体だと何らかのプラットフォーム向けの開発時に困るという話なのか?それとも開発環境としてXcodeやMacに縛られたくないという話なのか?
  • Toolchainがよくわかってない
    • ([Xcode] > [Toolchains] というメニューがある)
  • Docker使ってCLI+好きなエディタで開発できますという話とかは、サーバーサイド開発とかで普段そうしてる人だとピンと来る話なのかもしれない

そもそも非マルチプラットフォーム(MacでiOS開発しかやってない)、エディタとかにもこだわりがない(Xcodeで不満がない)人間なので、とりあえず何がわからなかったのかを列挙できたのでいったんokとします。。*1


Swift Package Manager

なぜSPMの話がクロスプラットフォーム開発の話で出てきたのかよくわからなかったのですが、niwatakoさんの書き起こし記事 みて、


是非オススメしたいのはSPMを使う時に自分のコードを細かいプロジェクトに分けることです。


使いまわしやすいように細かく分けてSPMで管理しよう、という話だと解釈しました。違ってたらすみません。*2


Objective-C 依存

これもリアルタイムでそもそも何についての話なのか(依存性の話だということが)理解できないまま聞いてましたが、niwatakoさんの書き起こしで理解。


#if がたくさん必要になる。 アーキテクチャチェック、AppleFrameworkを使っていないか、Objective-Cランタイムを使っていないかなど。この辺離れていくしか無い。時間がたてば軽減していくと思われる。


今のところは大変そうだ。。(JPさん荒野の開拓ありがとうございます)


Q&A: クロスプラットフォーム&オープンソースなXcode

これもniwatakoさんの記事で理解。Darwin以外でも動くXcodeはオープンソースとして出るか?という質問だったらしい。で、回答としては、Xcode自体は出ないと思うけど、SourceKitとかほとんどのIDEサポートはオープンソースになってるし、クロスプラットフォームで使えるものもあるので、実質的には別プラットフォームでIDEサポートはできると思います、と。


平常心で型を消し去る / Keep Calm and Type Erase On

型を明確にすることがSwiftらしいやり方であると気づいた時、同時に時には型を消す必要があると分かります。この講演では、型とは何か、型を消すことが何を意味するか、なぜそうしたいかについて解説します。


あとで手を動かしてコード書いてみよう、と思ってたら既に @hkato193 さんが試されてて、


@norio_nomura さんがgistにアップされてました。

ありがたや。


こんな風に書けるのか。。

class AnyPokemon<PokemonType>: Pokemon {
    let _attack: PokemonType -> Void
    required init<U: Pokemon where U.PokemonType == PokemonType>(_ pokemon: U) {
        _attack = pokemon.attack
    }
    func attack(move: PokemonType) {
        _attack(move)
    }
}

で、こんな感じで使えると。

let pika = AnyPokemon(Pikachu())
let hito = AnyPokemon(Hitokage())
pika.attack(3)
hito.attack(3.0)

勉強になりました。



  • 別の登壇者の方の実装:


  • 関連トーク:




Swiftのエラー処理についての三つの話 / Three Stories about Error Handling in Swift

エラー処理は安全なコードを書く上で重要です。私のプレゼンテーションでは、主に私の経験と考えに基いて、また `Error Handling Rationale and Proposal` と swift-evolution のメーリングリストでの議論にも触れながら、 Swift におけるエラー処理の論点を整理します。" : "Error handling is important to write safe codes. In my presentation, I will organize the issues of error handling in Swift mainly based on my experience and thinking referring to `Error Handling Rationale and Proposal` and discussions on the swift-evolution mailing list.")


後ほど復習:


プロトコルと約束の地 / Protocols and the Promised Land

Swiftの設計はジェネリクスや第一級プロトコルなど言語の機能がアプリケーション開発のカギとなることを推進しています。しかし、Objective-Cから導入されたものを含む論理的パターンの多くは期待した通りには動作しません。多くの場合、Swiftの型システムは、プロパティをクラスとプロトコルの両方に拘束したりする素直なパターンとうまく動きません。この講演ではいくつかの課題に着目し、内部に潜む原因を議論し、対応策について考えます。


後ほど復習:


文化を調和させる / Blending Cultures

Swiftでアプリケーションを書くということはObjective-Cで書かれたアプリケーションをただSwiftに書き換えるだけでなく、Swiftの特徴や哲学を受け入れる必要があります。この講演では、標準的なMVCで構成されたテーブルビューを使用したアプリケーションをSwiftに書き換えるところから始まり、よりSwiftらしいコードにするために、関数型プログラミング、オブジェクト指向プログラミング、デザインパターン、プロトコル指向プログラミングの考え方を適用していきます。


まずは niwatako さんの書き起こし を読んで理解しようと試みたのですが、


・・・わからない。コードの意味、やってることそのものはわかるのですが、一枚一枚のスライドとその間にある「その心は?」的なところがわからない。。


ただ、結局何をやっているのか、というのは最後にひとことで要約されてました。

さて、何をしましたか、いろんな簡素化しました。変更しないコードを外に追い出しました。


実際にサンプルコードを書いてくれた方がいます。


このコード内の HandVC.swift という UITableViewController サブクラスを見ると、効果が一目瞭然です。

class HandVC: UITableViewController {
    
    private var dataSource = HandDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = dataSource
        tableView.delegate = self
        navigationItem.leftBarButtonItem = editButtonItem()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction private func addNewCard(sender: UIBarButtonItem) {
        dataSource.addItemTo(tableView)
    }
}

なんとこれで全部。肥大化しやすい VC がこうもスッキリするのかと。ちょうどVCを肥大化させてしまった個人プロジェクトがあるので、この考え方でリファクタリングしてみようと思います。


Core Animationで作る高度なグラフィックス / Advanced Graphics with Core Animation

理解はできたので復習は省略しますが、発表に関連する話で、Core Animation を使ったライブラリを公開しています。



カスタマイズ性のためにいろいろとプロパティが多くなってしまってますが、基本的にはシンプルで、

  • CABasicAnimation で scale をアニメーションさせつつ、
  • CAKeyframeAnimation で opacity をアニメーション

させてます。また複数のパルスを発生させるために、(スライドにも出てきた) CAReplicatorLayer を利用 してます *3


我ながらAPIがいけてないのですが、実装時間3分ぐらいでそれなりにインパクトのあるアニメーションを入れられるので費用対効果抜群です。自分でも、WHILL、Moff、BONX、iOS×BLE本のサンプル、その他iOS Samplerシリーズやハッカソンでの作品、プロトタイプ案件等々、Bluetoothや位置情報を使う場合にしょっちゅう利用してます。


f:id:shu223:20141104132131g:image:left

f:id:shu223:20141104132209g:image:left



近々Swiftでつくりなおそうと思ってます。(あ、ObjCです、すいません try! Swift なのに)


スマートホームのためのコード / Code for the Smart Home

上に同じく、理解はできたので復習は省略しますが、ちらほらタイムラインで見かけた意見について。



上記記事にも書いてあるのですが、HomeKit Accessory Protocol は次のような構造になっています。


f:id:shu223:20140623070646p:image:w500


対応デバイスも海外ではちらほら出てきている *4 ので、近々記事を書こうと思います。



*1:たぶん上記疑問に答えてもらっても、「なるほどー(ポカーン)」ってなりそう

*2:JPさんの英語がハキハキしてて何とかついていけそうな気がしてこの時点では同時通訳聞いてなかったので、たぶん聞き逃しまくってたのかと

*3:@dealforest さんプルリクありがとうございました!

*4:昨年WWDCでSFに行ってきたときに買ってきて、まだ触ってない。。

[iOS][デザイン][Swift]Sketch買ったばかりのプログラマがアイコンデザインに挑戦してみたメモ #tryswiftconf

$
0
0

「try! Swift」2日目のセッション "Live Design:🎙🎨" (日本語タイトル:ライブデザイニング)で、Sketchを使ってサクサクとアイコンをつくっていく過程を見て、



と思い *1、さっそくダウンロードして同じ手順をなぞってみることにしました。


f:id:shu223:20160303231308p:image

Sketch - Professional Digital Design for Mac


ちなみに購入する気満々だったのでこういうタイトルにしたものの、Free Trialで30日間は無料で使えるようです。


@niwatako さんの聞き起こし記事を参考に手順をなぞっていきます。

(※杞憂だとは思いますが、「こんなのは単なるツールのオペレーションであってデザインとは言わない!」みたいな話はご容赦ください。。)


新規プロジェクト(?)作成

iOS App Iconというテンプレートがあるが、使わない。普通に [File] > [New] する。


アイコン外枠の矩形をつくる

  • 左上の+ボタン(Insert) > [Shape] > [Rectangle]、もしくはRボタン押下で矩形描画。
    • Shift押しながらドラッグすると正方形になる。
  • 1024x1024にする(iOSのアイコンサイズ)
  • 色をつける

f:id:shu223:20160303230052p:image:w600


角丸の線を引く

  • 白い矩形の背景をつくる
  • 細長い矩形の線(LineではなくあくまでRectangle)を引く
  • 線を角丸にする
  • 線をコピペする

f:id:shu223:20160303230143p:image:w600


青空をつくる

  • 矩形を作成
  • Fill の欄でグラデーションのアイコンを選択
  • 薄い方の色、濃い方の色を選ぶ

f:id:shu223:20160303230322p:image:w600


ビルをつくる

  • 矩形をたくさんつくる

f:id:shu223:20160303230403p:image:w600


  • 左ペインからビル矩形のレイヤーを全部選択する
  • 右クリック > [Group Selection] (グループ化)
  • 全部選択した状態で、いっぺんにプロパティ(ここでは色)を変えられる

f:id:shu223:20160303230522p:image:w600


雲をつくる

  • たくさん楕円を書く
    • 楕円は +ボタン(Insert)> [Shape] > [Oval] か oボタン

f:id:shu223:20160303230627p:image:w600


  • Shiftを押しながら複数の楕円を選択して [Union] (結合)
  • グラデーションさせる(アルファの値を変える)
  • レイヤーをビルより後ろに持っていく

f:id:shu223:20160303230651p:image:w600


地球とか

(ちょっと飽きてきたので)巻きでいきます。。


f:id:shu223:20160303230743p:image:w600


下の何か

  • これまでつくってきたものを全部グループ化しておく
  • 下に長方形を作成
  • 横方向にグラデーション(グラデーションの◯をドラッグすると向きを変えられる)

f:id:shu223:20160303230848p:image:w600


(セッションのときから思ってたけど、これは何なんだろう・・・?)


エクスポート

  • 全レイヤー(グループ)をグループにまとめてiconと命名する
  • [File] > [New from Template] > [iOS App Icon] でテンプレート作成
  • 先ほどのiconグループを貼り付ける
  • 大きさ、位置を調整

f:id:shu223:20160303230921p:image:w600


  • 左ペインの下の方に "Mask" というレイヤー(?)があるので削除する(角丸不要なので)

f:id:shu223:20160303231018p:image:w600


  • 選択して、右下の Export ボタンを押す

出来上がり

f:id:shu223:20160303231111p:image:w256


所感

イラレが食わず嫌いだったのかはわかりませんが、ものすごく簡単でした。アプリのアイコンデザインを自分でやることはあんまりないかもしれないとは思うのですが(重要すぎるのでやはりここはプロに任せたい)、プレゼン資料等の図を作成するのに良さそう、と思いました。


とりあえず30日はタダですし、本日のセッションみてやってみようかなと思った方、ぜひお試しください!


使った操作リスト

  • 矩形(角丸)作成・・・R
  • 楕円作成・・・O
  • 線・・・L
  • 曲線・・・V
  • 塗りつぶし
  • グラデーション
  • グループ化
  • 一括色変更
  • 結合

*1:かつて Adobe の Illustlator を買ったものの、何となく難しそうで結局使ったことがない

[Swift][iOS][海外]try! Swift振り返り/英語/国際カンファレンス #tryswiftconf

$
0
0

国内初のiOSの国際カンファレンス「try! Swift」に全日程(3日間)参加してきました。技術的な振り返り(復習)は別記事でやるとして、ここでは感想的なものを。


f:id:shu223:20160307104442j:image:w400

(今回の主催者であり、Natasha The Robot / This Week in Swift の中の人、ナターシャさんと)


参加してよかったこと

自分のヤバさが認識できた

昨年まではほとんどの場合でObjective-Cを書き、たまーに見栄をはりたいとき(発表スライドに載せるちょっとしたコードとか、書籍のサンプルとか)にちょろっと付け焼き刃のSwiftを書いていた程度でした。


が、このカンファレンスのチケットを買ってからは意識してSwiftを書くようになり、最近やっと ObjC より Swift が気持ちよく書けるようになってきたところです *1


で、本カンファレンスに参加して、言語的な話にはほとんどついていけず、iOSしかやってない自分がiOSの話についていけないなんて、どんだけおれしょぼいんだ、と。そういう自分の置かれている状況を自覚して悔い改める機会になってよかったです。


目線が上がった

最近、所用(後述)で他のさまざまなiOS関連カンファレンスとそのプレゼン内容を調べてたのですが、今回登壇されたスピーカー陣の多くは国際カンファレンスの常連です。


で、ああいうすごい人達に混じれるように勉強がんばるぞーという面もあるのですが、いくつかの自分の得意な分野の話(Core Animation、HomeKit、Core Image等)を聞くにつけ、今の僕でも国際的な舞台で提供できる価値というのはあるんじゃないかと。





もちろん僕の知識はまだまだ浅いところがあるので、もっと深掘りしないといけないし、英語力的にはカタコトレベルなので登壇するならめちゃめちゃ練習しないといけないだろうし、プロフィールがもっと国際的に通用するものになるように意識して行動していかないといけない。


そういう努力をしていこう、と今回参加したことでより強く思えるようになりました。


人間模様に感動した

人間模様というか、それぞれの生き様というか、多くの方から刺激を受けまくった3日間でした。一例を挙げると、

  • 岸川さん・・・これだけの規模のイベントを主催するというのはどれほど大変なことか想像もつきません。iOSエンジニアコミュニティへの貢献度が本当に素晴らしすぎる。
  • 日本人スピーカーの方々・・・よく練られた構成と鮮やかでインパクトのあるライブコーディングで国内外の人達にawesomeと言わしめた石川さん、ハイレベルな話を堂々とした英語で話す稲見さん等々、みなさんかっこよかったです。
  • niwatakoさん・・・クオリティの高い全文聞き起こし記事がリアルタイムに(たった5分の休憩の間に)上がってくるのには誰もが度肝を抜かれてました(日本語読めない海外の人達の間でも話題になってました)。こういうそれぞれの得意なところでポジションをとっていく(貢献する)姿勢はぜひ見習いたいところ。

  • とある方・・・みんなが「素晴らしかった」「最高だった」と言ってる中で、(僕)「どの発表がよかったですか?」(その方)「期待してたセッションはxxxだけでしたがそれもイマイチでしたね」とスパッと。悪意もなにもなく正直な感想なので全然アリだと思いますし、こういう「流されなさ」ってすごいなと。僕は人の意見や雰囲気に影響受けやすいので憧れます。
  • 同時通訳の方々・・・日本語と英語両方できますとかってレベルじゃなくて、感動を覚えるレベルでした。これがプロか、と。


英語

参加者の多くが触れている英語の話。会期中はセッションについていくのに必死であんまり海外の方としゃべってないのですが、ベルリンから来られた CocoaPods コミッタの Boris さん(初日にtvOSの話をされていた)や、



アフターパーティでは冒頭写真にあったように主催者の Natasha さん、Core Image の話をされていた Simon さん、Core Animation の話をされていた Tim さん(この方は日本語ペラペラだけど。。)、UIKonf/objc.io主催の Chris さん、Tokyo iOS Meetup の Matthew さん等々とお話させていただきました。


で、僕は昨年までマジで英語に苦手意識があり *2、WWDCでSFにいってもミートアップにも出ず、英語コミュニケーションには恐怖すら覚えていたわけですが、ここ最近の「英語を使わざるを得ない環境に飛び込んで場数を踏む」作戦が功を奏し、コミュニケーション力に関してはずいぶん改善したなと。


もちろんヒアリング力は一朝一夕では伸びないし、スピーキングも表現力がなさすぎる(Nice とか Good とか Wow ばっかり言ってる)のですが、質問するとか、自己アピールするとか、とにかく「自分から話しかけて何らかのことを伝えてこれるようになった」(雑談/フリートークはまだできない)というのは大きな進歩だなと。


英語力の本質的な向上には量をこなすしかないと思うのですが、僕の場合はいくつかのことを「あきらめる」ことでブレークスルーがあったと思っていて、このへんのことはいつか整理して書いてみたいと思います。(もうちょいマシになってからの方が説得力あるかな・・・?)


国際カンファレンス

try! Swift きっかけというわけではないのですが、この記事の末尾に以下のように書きました。

ベルリンだけでなくシリコンバレー等に行っても毎回感じることですが、無力感が半端ないです。仕事をやってみたりハッカソンに出てみたりして、技術的に通用しないということはないと思ってますが、誰も僕のことを知らないし(知名度以前に知り合いがいないという意味で)、そういう僕がベルリンに行ったところで、現地の他のスタートアップの方から「会いたい」とか言われることはありません。


(中略)


僕がニュースとかで海外のそういう系の魅力的なプロダクトを見るタイミングではもう遅くて(メディアに出て話題になっているということはある程度開発が進んでいるか完了しているケースが多い)ファウンダーが資金調達して本格的に開発をしようとするタイミングであちらから見つけてもらえるようにならないといけない。


で、LinkedIn や AngelList で人を探す場合は大抵「住んでいる場所」でフィルタされてしまうので、英語ブログという「海外スタートアップに自分を見つけてもらうためのチャネル」を用意する必要があるなと。


僕のGitHubアカウントは今でも多少そういう感じの機能をしてくれてますが、(後略)


で、この「自分を見つけてもらうためのチャネル」として、「国際カンファレンスで話す」というのは

  • 著名な常連スピーカーの方々に自分の話が届く
  • ログに残る(→ 英語でググッて見つかる「入り口」になる)

という理由から効果大かも、と思いまして、UIKonf というヨーロッパのiOSカンファレンス *3CFPに応募してみました。



運営による Pre-Selection は通過(!)しまして、現在最終投票フェーズです *4。もし採択されたら必死で準備して臨みたいと思っております。


お知らせ

今週末、ひさびさに登壇させていただきます。

パネルディスカッションを通じて『エンジニアの最初の一歩』について、 これからプログラミングをはじめてみようかな〜と考えている方 にも一緒に考えていただき、

とのことで、try! Swift 参加者のみなさまはちょっと違うのかもしれませんが、無料とのことですのでご興味があればぜひ!


try! Swift復習記事

書いたら追記していきます。


*1:以前はObjCなら5秒で書けるところを、Swiftの場合はググラないといけなかったりしてそれがストレスだった

*22013年にアメリカに行ってからこの苦手意識がますます強くなった

*3:今回 try! Swift に登壇された Chris さんは主催の一人

*4:審査や投票は匿名で進めるとのことで、僕のProposalがどれというのは採択されるまでは書けないっぽいです

[iOS][Swift][参考書籍]「本気ではじめるiPhoneアプリ作り」の紹介/iOSアプリ開発の勉強法について

$
0
0

Yahoo!のiOS黒帯エンジニア、西さん(および SB Creative さま)よりご献本いただきました。


f:id:shu223:20160320105728j:image:w400


『本気ではじめるiPhoneアプリ作り 黒帯エンジニアがしっかり教える基本テクニック』というタイトルで、環境構築からアプリのリリースまでをカバーした実践的入門書です。まだ発売されたばかりで、Xcode 7、Swift 2 の最新開発環境に対応 しているのもポイントです。



書籍の特長

冒頭にも書きましたが、著者の西さんは ヤフーで「黒帯」として認定 されている方で、つまり現場でバリバリのエキスパートとして認められている方です。


というわけで本書は入門書でありつつ、AutoLayout、データの永続化、サウンド、アニメーション、通信処理といった 昨今のアプリ開発には不可欠な要素 を、ToDoリストアプリや商品検索アプリといった 具体的なサンプルをつくりながら学べる「実践的」な内容となっています。

(目次より一部抜粋)

  • Chapter4 アプリの基本をマスターしよう
    • 割引計算アプリで学ぶ画面レイアウトとボタン操作
  • Chapter5 永続的なデータを扱う
    • ToDoリストアプリで学ぶデータ操作
  • Chapter6 サウンドとアニメーションの処理
    • クイズアプリで学ぶサウンド・バイブレーション・グラフィックス操作
  • Chapter7 通信できるアプリを作ろう
    • 商品検索アプリで学ぶ通信の方法

ちなみに通信処理が入るアプリにはAPIを提供するサーバー側も必要ですが、そこはYahoo!のWeb APIを利用し、サーバーサイドの実装なしで実現できるように配慮されていました。

let entryUrl: String = "https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch"

下記は、著者自身による紹介記事です。

アプリを作り上げていくにはさまざまな基礎知識が必要になるわけですが、本書ではiOSアプリ開発において重点的に押さえておくべき基本をまとめつつ、実際にApp Storeへリリースできるアプリを開発できるようになるまでを爆速で支援するように書いています。


また、koogawaさんのブログでも各章ごとの詳しい書評が書かれています。


おまけ:iOSアプリ開発の勉強法について

こういう話もあって、「iOSアプリ開発はどう勉強したらいいか?」「おすすめの入門書は?」みたいな質問をされることがよくあります。なかなかそういう話をブログに書く機会もないので、今回の入門書の紹介に乗じて書かせていただこうかと。


とはいえ普遍的な話はできないし、正解もないので、あくまで「僕の場合はこうでした」という話として、参考程度にお読みいただければと。


入門書購入

iOSアプリ開発を始めたとき、まず入門書を数冊買いました。はじめてのMacbookを買った帰り、有楽町のビックカメラの技術書コーナーでパラパラめくって、「話が理解できそうなもの」を選んだ記憶があります。


当時のブログに書いた記事がこちら。

この本に載ってたサンプルアプリを、

内容を理解することなく手順をなぞって実装し、

とりあえず動かしてみました。


意味を理解しないまま手順通りにXcodeでプロジェクトをつくって、3行ぐらい、意味を理解しないまま本に書かれている文字列(プログラム)を打ち込んで、本に書いてある通りにビルドのボタンを押すと・・・シミュレータで「ブラウザアプリ」が動作したのです。ブラウザってめっちゃ難しそうって思ってたので、これはちょっとした感動でした。


第一作目のアプリ

その後「ビルドして実機で動作させる」手順まで覚えた僕が次にやったのは、本の通読ではなく、本質を理解しようとすることでもなく、

  • 手元にある書籍のサンプルコードを一通りビルドして試してみる
  • そのサンプルコードからの改変でつくれそうなアプリを考えてみる

ということでした。


で、つくってストアでのリリースまで漕ぎ着けたのが、「余命電卓」というアプリです。


『iPhone SDKの教科書』という書籍に収録されていた、年齢を計算する『Age』というサンプルが元になっています。

  • ピッカーで誕生日を設定できる
  • 設定した誕生日から算出した「現在の年齢」が表示される

というサンプルで、僕のつくった余命電卓は、単にその「現在の年齢」の代わりに「余命」(78 - 現在の年齢)を表示するようにしただけでした *1


f:id:shu223:20160320231930p:image:w280:left

f:id:shu223:20160320231928p:image:w280:left



このサンプルコードの改変に必要だった知識は、

  • アイコンなどの画像リソースの入れ替え
  • ボタンを押したら設定画面に遷移するようにする
  • 年齢の代わりに「平均寿命 - 年齢」で計算した余命を表示する
  • 余命を時間・分・秒等に換算する
  • タイマーで秒数カウントダウン

これぐらいです。画面遷移やタイマー等は、同様の機能を実現している他のサンプルをあたって、該当するコードを持ってきました。


挫折しないコツ1:わからないことには目を瞑る

Xcodeプロジェクトを新規作成するだけで、わらわらとわけのわからないファイルがたくさん生成され、プログラムを書く 〜.h や 〜.m (今だと 〜.swift)にも最初からわけのわからないことが色々と書かれています。


そういうのを 全部理解しようとしなかった、のが途中で挫折しなかった秘訣かなと。


Objective-Cでいうと、@interface, @implementation って何なのかとか。assign だとか nonatomic とか。


もちろん大事ではあるのですが、プログラミングを始めたばかりの人がそういうのをひとつひとつしっかり理解してから前に進もうとすると、動くものをつくれるようになるまでが遠すぎて、挫折してしまうのかなと。


挫折しないコツ2:できないことはあきらめる

余命電卓の最初のバージョンでは、日本男性の平均寿命78歳から誕生日を引く、という超シンプルなロジックだったのですが、次に僕がやろうとしたのは、「性別を選ぶと男女それぞれの平均寿命から引き算する」というものでした。


・・・が、なぜかクラッシュする・・・


当時の僕は解決方法がわからなくて、その機能をあきらめました


プログラミングにおいて、的確にトラブルシューティングを行うことは、(ものにもよりますが)しっかりした理解と経験を必要とするわりと高等な技術だと思っています。ここで挫折して二度とプログラムをやらないよりは、あきらめて別のできそうなことを探す、というのもひとつの手かと。


サンプルドリブン勉強法

そんなわけで、僕が「Age」から「余命電卓」をつくったように、最初からある程度機能があって、動くコード、つまりサンプルコードから始めて、そこに書いてある色んなわけのわからないことには目を瞑りつつ、画像を入れ替えてみるとか、計算の足し算してるところを引き算にしてみるとか、そういう わかること/できることだけでまずはやってみる、というのも、挫折せずにプログラミングの楽しさを知る=入門するためのひとつの方法かなと、僕の経験から思います。


入門書の選び方

上記の経験をふまえつつ、個人的に入門書を選ぶ際の観点としては以下をオススメしています。

  • 自分がつくりたいアプリに近いサンプルが載っている
  • 出版年月が新しい
    • 古いと、サンプルが動かない可能性がある
    • 動かないサンプルを動くようにするのは入門者には厳しいかも
  • パラパラとめくって、自分にとって説明がわかりやすそうか?をみる
    • 人によって前提知識は全然違うし、文章の好みとかもあるので

まとめ

最新の開発環境に対応した実践的入門書「本気ではじめるiPhoneアプリ作り」を紹介しつつ、僕がアプリ開発を始めたころの勉強法についても書かせていただきました。どなたかの参考になれば幸いです!


*1:今は広告とかツイート機能とか入ってますが、リリース当初はもちろんそんな機能はありません。

[iOS][登壇][BLE][海外]海外の国際カンファレンスに登壇する - 応募編 #potatotips

$
0
0

本日、potatotips #28(iOS/Androidの開発Tips共有会)にて標題の発表をさせていただきました。



iOSのカンファレンスに自分で応募して、採択されるまでの話です。


以下、スライド内容の抜粋。


はじめに

iOSのカンファレンス、UIKonf 2016(ベルリン), iOSCon 2016(ロンドン) に登壇させていただくことになりました!

  • どちらも国内外からスピーカーが来る国際カンファレンス
  • チケット代
    • UIKonf:€450+VAT19%(約66,000円)
    • iOSCon:£650(約101,500円)
  • どちらも登壇者は計18人

f:id:shu223:20160420232101j:image:w600


・・・と言っても

  • 招待されたわけではない
  • 自分で応募して、投票・審査の上で採択された

アジェンダ

1. なぜ応募したか

2. CFPをどう見つけたか

3. Proposalをどう書いたか

4. 審査過程はどうだったか

1. なぜ応募したか?

国際カンファレンスに登壇する(僕にとっての)メリット

  • ログに残る
    • 英語でググッて見つかる「入り口」になる
  • 著名な常連スピーカーの方々に自分の話が届く
    • 海外から仕事がくるきっかけになるかもしれない
    • 別のカンファレンスにも呼ばれるかもしれない
  • 海外に行けるのが嬉しい/楽しい
    • 旅行もいいけど個人的には本業と絡んだほうが楽しい
    • 航空券代・ホテル代は出る(カンファレンスによるかもしれない)
  • 英語を「必死で」練習する機会になる
    • 30分ぶんの、自分の得意な分野について話す英語表現の「引き出し」 をつくる機会にもなる
  • 経歴に書ける

メリットだらけ


2. CFPをどう見つけたか

CFPとは
  • Call for Proposal (Papers / Participation)
  • 登壇者を募集してます、の意味
カンファレンスの探し方
CFPを見つける
  • カンファレンス開催予定はわかっても、CFPは見つけづらい
  • 招待講演だけ(CFPなし)のカンファレンスも多い

探し方

  • ググる
    • "ios conference 2016 "cfp""
    • "ios conference 2016 "call for""
  • Calls for participation | Lanyrd
  • カンファレンス常連の方々のTwitterアカウントをフォローしておく
    • 中の人とつながってたり、中の人だったりするので、たまにCFPのツイートが流れてくる


3. Proposalをどう書いたか

当初案

「いつもの勉強会」と同じように話したいネタを棚卸し

  • iOS×機械学習
  • OpenCV 3
  • iOS×BLE
過去のカンファレンスの登壇内容を見てみた
  • [altconf.com/schedule/:title=AltConf 2015 Schedule]
    • タイトルと概要が一覧で見れて参考にしやすい
  • WWDC
    • iOSエンジニアには馴染み深い
  • その他諸々
  • (※応募当時は try! Swift 開催前)
歓迎されるっぽいTALK
  • スピーカーがその分野で十分な経験がある
    • 「このライブラリをちょっと触ってみました」的な話はさすが にない(そのライブラリの作者で、設計思想等も含めて話せる場合は別)
    • 「その人ならでは」の話(バックグラウンドが活きる話)
  • 体系立てて話せる
    • ↔ 雑多な、箇条書き的な話

これと自分のネタを照らしあわせてみると・・・

  • iOS×機械学習
  • OpenCV 3

→ 専門家でもなければ、 がっつりやった経験もない。発表のプレッシャードリブンで 「これから」勉強したいだけ

  • iOS×BLE

→ (BLE自体にめちゃめちゃ詳しいわけじゃないが、)iOSエンジニアとしてハードウェアプロジェクトに関わった経験数としては多い方だと思う。書籍も書いたので多少は体系立てて話せそう。

完成品

f:id:shu223:20160420203729p:image:w500


4. 審査過程はどうだったか

UIKonf
  • 匿名フィードバックがあり、Proposalをアップデートできる
  • 匿名投票(GitHubアカウントでログイン/8つ選択)
  • 運営によってさらに絞り込まれる
  • 採択率 8 / 60ぐらい?(スピーカー全18人中8人がCFP枠?)
iOSCon
  • 運営による審査
  • 応募数不明
  • 登壇者計18人、うち招待講演は6人(スケジュールが単独で組まれている)

まとめ

  • なぜ応募したか
    • フリーランスとしての海外進出の足がかり
    • 英語の練習
    • 海外に行きたい
  • CFPをどう見つけたか
    • ググる/常連スピーカーをウォッチする
  • Proposalをどう書いたか
    • 過去のカンファレンスを参考にしつつ持ちネタを絞り込んだ
  • 審査過程はどうだったか
    • カンファレンスによって色々(投票/運営による審査)

おわりに

準備と練習をしっかりして臨みます!



以上、スライドより。


主催/会場提供のエウレカさん(広くて天井高くてものすごい良かった)、登壇者のみなさま、参加者のみなさま、ありがとうございました!



[OpenGL][画像処理][動画処理]GLKView の描画内容を AVAssetWriter を用いて動画としてエクスポートする

$
0
0

すごい雑なメモですが、ちゃんと書くにはまだ理解が足りてなくて、かといってローカルに放置するとまた同じことを一から自分で調べそうな気がするので、とりあえずアップ。


※古いコードを流用している部分もあるため、一部ObjC、一部Swiftです。


やりたかったこと

標題の通り、「GLKView の描画内容を AVAssetWriter に渡して動画として書き出す」ということがやりたかった。リアルタイムに処理する必要があって、要件としては20fps。


AVAssetWriterInputPixelBufferAdaptor オブジェクトがあって、

@property (nonatomic, strong) AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor;

こう生成した CVPixelBufferRef があって、

CVPixelBufferRef pixelBuffer = NULL;
CVPixelBufferPoolCreatePixelBuffer(nil, self.pixelBufferAdaptor.pixelBufferPool, &pixelBuffer);

ここに GLKView への描画内容を反映すれば、

[self.pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:timestamp];

こんな感じで AVAssetWriter で動画エクスポートできる。


・・・ということはわかっていたけど、CVPixelBuffer に GLKView の描画内容をどうやったら渡せるのかがわからなかった。


試した方法1: テクスチャキャッシュを利用して OpenGL の FBO を書き出す

ググッてこちらで見つけた方法。以下にコードがある。

`CVOpenGLESTextureCacheCreate` と `CVOpenGLESTextureCacheCreateTextureFromImage` なるメソッドを使用してテクスチャキャッシュなるものを生成して Frame Buffer Object (FBO) を云々する(処理内容を理解できていないので適切な説明ができない)。GPUImage と同様の方法らしい。


自分のプロジェクトに移植してみたがうまく動かず、上のコードと何が違うのかにらめっこしていたが、READMEをよく読むと 元コードもちゃんと動作してない と書いてあり、リファレンスコードなしであれこれ試行錯誤する時間もないので、いったん別の方法を考えることに。


試した方法2: GLKView のスナップショットを取得する

UIView のスナップショット取得はそれなりに重い印象があったのと、リアルタイム処理(20fps)の必要がありなるべくUIKitのレイヤーで処理したくなかったので当初は思いついても頭から除外していた選択肢。


ただ方法1が頓挫して、今日中に落とし所を見つけたかったので、少々フレームレートが落ちてもいいので試してみよう、ということでこっちでやることに。


下記によると、GLKView の描画内容は `renderInContext:` ではスナップショットとれないらしい。Core Graphics だからそりゃそうか。

You need to grab the view's framebuffer pixel data using OpenGL ES. You can't do it with renderInContext:.


で、同回答にリンクがあったのが下記。

GPUImage の作者 Brad Larson さんの回答。`glReadPixels()` でピクセルデータを取り出す方法と、テクスチャキャッシュを利用する方法が提示されている。後者は方法1で断念した方向なので厳しい・・・


前者の `glReadPixels()` を利用する方法は、下記に UIImage に変換するまでのコードがあった。

- (UIImage*)snapshotRenderBuffer {

    // Bind the color renderbuffer used to render the OpenGL ES view
    // If your application only creates a single color renderbuffer which is already bound at this point, 
    // this call is redundant, but it is needed if you're dealing with multiple renderbuffers.
    // Note, replace "_colorRenderbuffer" with the actual name of the renderbuffer object defined in your class.
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

    NSInteger dataLength = backingWidth * backingHeight * 4;
    GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

    // Read pixel data from the framebuffer
    glPixelStorei(GL_PACK_ALIGNMENT, 4);
    glReadPixels(0.0f, 0.0f, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);

    // Create a CGImage with the pixel data
    // If your OpenGL ES content is opaque, use kCGImageAlphaNoneSkipLast to ignore the alpha channel
    // otherwise, use kCGImageAlphaPremultipliedLast
    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGImageRef iref = CGImageCreate(
                                    backingWidth, backingHeight, 8, 32, backingWidth * 4, colorspace, 
                                    kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast,
                                    ref, NULL, true, kCGRenderingIntentDefault);

    // (sayeth abd)
    // This creates a context with the device pixel dimensions -- not points. 
    // To be compatible with all devices, you're meant to keep everything as points and a scale factor;  but,
    // this gives us a scaled down image for purposes of saving.  So, keep everything in device resolution,
    // and worry about it later...
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(backingWidth, backingHeight), NO, 0.0f);
    CGContextRef cgcontext = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
    CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, backingWidth, backingHeight), iref);

    // Retrieve the UIImage from the current context
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    // Clean up
    free(data);

    return image;
}

(結局 Core Graphics を経由するのか。。)


で、最終的に以下の回答に行きつく。


あれ、`snapshot` なんてメソッドあったっけ?と思って調べてみたら、GLKView に元から用意されていた・・・!

@property (readonly, strong) UIImage *snapshot;

最終的にうまくいった方法

guard let cisnapshot = CIImage(image: snapshot) else { fatalError() }
drawImage = cisnapshot.imageByCompositingOverImage(drawImage)

glView.ciContext.render(
    drawImage,
    toCVPixelBuffer: pixelBuffer,
    bounds: drawImage.extent,
    colorSpace: CGColorSpaceCreateDeviceRGB())

上記コードの前提

  • GLKView の `snapshot` メソッドで取得した UIImage が `snapshot` に入っている
  • `drawImage` は諸々の処理を経由した CIImage オブジェクト

[iOS][海外][登壇][BLE]ベルリンとロンドンのiOSカンファレンスで登壇した話 #UIKonf #iOSCon

$
0
0

先週、ベルリンで開催された UIKonf と、ロンドンで開催された iOSCon の両カンファレンスにスピーカーとして参加してきました。


f:id:shu223:20160529205622j:image:w600

UIKonfの会場(登壇してるのはDaniel氏)


まだロンドンにいまして、興奮冷めやらぬうちに記事に書いておきたいと思います。


UIKonf、iOSCon とは?

どちらもiOSの開発者向けカンファレンスです。


同時期の開催で、同じEU内でのカンファレンスではありますが、それぞれ全く関連のない母体によって運営されています。*1


f:id:shu223:20160530065207j:image:w600


チケット代はそれぞれ、

  • UIKonf:€450+VAT19%(約66,000円
  • iOSCon:£650(約101,500円)+VAT(いくらか忘れた)

と、日本の感覚からいくとかなり高額です。


UIKonfの方は著名ブログ "RAYWENDERLICH" の "Top 10 iOS Conferences" でも紹介されていて、チケットも早々にソールドアウトとなった人気カンファレンスです。


登壇の経緯

UIKonfは登壇者は計18人、iOSConは計20人です。それぞれカンファレンス側から招待された著名スピーカー陣が何人かいますが、僕は招待されたわけではなく、自分で応募して、投票・審査の上で採択されたCFP枠です。


なお、CFP応募・採択までの経緯の詳細は、下記記事にまとめてあります。


準備

僕はそもそも英語にずっと苦手意識があり、WWDCでSFに行ってもセッションを聞きに行かずにネットで(日本にいても見れる)PDFを見てたり、スカイプ面接はトラウマになってたりするほどでした。


ただ今回はどちらのカンファレンスもお客さんは高額のチケット代を払って話を聞きにくるわけで、英語はしっかりやろう、ということで英語の短期指導やってるところをググって探したりしていました。


そんな中で知り合いの方から紹介していただいたのが、ジョセフ・テイム先生。TEDxTokyoとかのコーチもされている方で、技術もわかる、そして信頼している人からの推薦、ということでパーソナルコーチをお願いしました。 *2


f:id:shu223:20160530040355j:image:w540

(レッスン中の様子@先生の自宅)


もともとは僕の方でスライドとTranscript(話す内容の原稿)をつくりあげて、先生の前で練習して変なところを修正してもらう、というつもりだったのですが、実際にはなかなかスライドもTranscriptも完成しなくて、下記のサイクルをぐるぐる回しながらで進んで行った感じです。

  1. スライドの改善作業
  2. 先生のレッスンで新しいスライドにTranscriptをつけていく
  3. 別の誰かに聞いてもらう(改善点が浮き彫りになる)→ 1に戻る


「誰かに聞いてもらう」という話でいうと、知り合いのiOSエンジニアが集まるもくもく会がちょうど出発前日に渋谷dots.さんであり、そこで突発的に発表練習をさせていただく機会もありました。


f:id:shu223:20160530075209j:image:w600

(Photo by Himiさん)


try! Swiftを主催されたRealmの岸川さんにはそもそも一度フィードバックをもらいたいと思っていたし、僕より英語が堪能な方々ばかりだったり、dots.さんは講演の場として臨場感ありまくりだったりで、大変ありがたかったです。


登壇@UIKonf

5/23、いよいよ初の登壇。冒頭の写真の通り、UIKonfは体育館みたいな吹き抜けのでかい会場で、ドイツっぽい古い感じの造りでものすごく素敵な場所でした。


ライブストリーミングがあり、恥を晒すことになるかもしれないのでシェアするか迷いましたが、こんな機会も二度とないかもしれない、と思い発表直前にTwitterでシェア。

おかげで日本からも結構多くの方が観ていてくれたみたいです。


緊張は意外とそんなにしませんでした。Maxの緊張を100とすると10か20ぐらい。


f:id:shu223:20160530040218j:image:w600

(UIKonfのステージより。Photo by 他の登壇者の方)


f:id:shu223:20160530040652j:image:w500

(舞台袖からスタッフが撮ってくれた貴重な一枚)


結果的には大成功で、途中で笑いも起きたし、終わった後いろんな人から「まじで良かったよ!」と声をかけてもらいました。他の登壇者の方々からもお褒めの言葉をたくさんいただきました。*3


下記に動画が公開されています。



とはいえ実は質疑応答は大失敗で、最初の質問への回答はイケてなかったし、2つ目の質問はまったく聞き取れず、テンパってしまいました。終了直後はそれで凹んでたりもしてたのですが、今思えば謝りつつももっと堂々としてればよかったなと。そういうことも経験したからこそ学べたことなので、とにかく良かったです。


f:id:shu223:20160530055219j:image:w540

(スピーカーへのプレゼントで「アーキテクチャ」のレゴ(ベルリン仕様)をいただきました)


登壇@iOSCon

出番は5/26、UIKonfの最終日には出ずにロンドンに移動して、その翌日にはもう発表でした。


基本的には同じ内容なのですが、UIKonfは持ち時間30分、こちらは45分なので、少々スライドを付け足し、デモも用意して臨みました。


(こちらの会場は打って変わってオフィス的な雰囲気)


こちらは・・・質疑応答こそUIKonfのときよりまともにできたものの、講演全体としてはUIKonfの方が出来が良かったかもしれない、と思っています。


話し方、内容、いろいろ具体的な反省点はあるのですが、どうダメだったかを一言でいうと、オーディエンスとの一体感を醸成できなかったという点につきます。


質問はそこそこあったので伝わっていたとは思いますが、UIKonfのときのような、「めっちゃよかったよー」みたいな興奮を伴う反応がなかった。発表中も終始淡々としたムードだったので、冒頭からずっとお客さんの関心というかテンションを掴み損なっていた気がします。


良かった点と、反省点

良かった点

今回の発表内容を構築するにあたって一番悩ましかったのは、とっつきやすさと深さのバランスです。


Core Bluetooth を使ったことがあるiOSエンジニアは世界にいくらでもいると思いますが、「ちゃんとエンドユーザーの手に渡った」ハードウェアプロダクトに「がっつり手を動かす立場で」「複数案件」関わったことがあるiOSエンジニアとなると世界でもまだそれほど多くはないと思っていて、そここそが僕のプロポーザルが採用されたポイントなわけで、そういう「僕ならではのバックグラウンド」を活かした話をしないと、わざわざ海外から呼んでくれた意味がありません。


とはいえBLE/Core BluetoothなんてiOSエンジニア全体から取ってみればやはりニッチな話。いきなり「BLEの経験がある人だけがわかるディープな話」をしてしまうと多くの人の脳内で「この話は自分には関係ないな」枠に分類されてしまいます。


というわけでこだわったポイントは、

  • BLEがわからない、Core Bluetooth に興味がなくても楽しめる
  • たくさんの実案件を経験してきたからこそ話せる

という(一見)相反する2つの要件を満たすこと。


そのために構成やら図解やらデモ動画やら何度も何度も改善を繰り返して今の形になりました。それなりのアプリを1つ作れるぐらいにはスライド作成に時間をかけたと思います。



で、このこだわりポイントはUIKonf(@ベルリン)ではめちゃくちゃ狙い通りにヒットしました。講演がシングルトラック(同時に複数の講演が行われることがない)なので、もともとBLE/Core Bluetoothに興味がなかった人も巻き込んで、多くの人に "really great" と言ってもらえました。


反省点

一方iOSCon(ロンドン)では講演がマルチトラックで、しかもサブ会場なので、そもそも興味のない人は来なかったんじゃないかと思います。


f:id:shu223:20160530041220j:image:w300

(iOSConスケジュールより抜粋)


で、お客さんは多くはなかったし、そんな中で僕は柔軟にアドリブでお客さんの気持ちを掴んだりすることもできず、前述の通り淡々とした雰囲気のまま進めてしまいました。



ひとつやればよかったなと思うのは、もっと非経験者も興味を持てるタイトル・概要にすること。タイトルが "Practical Core Bluetooth" だと、Core Bluetoothに興味がない人がわざわざ選ぶことはあまりないんじゃないかと思います。プロポーザル提出時点ではこの辺のことがまだ見えてなかった。


あと、何度も同じ話をしてると自分自身のテンションが乗らなくなってくる、というのもあるので、そういうページはどんどん削除して、自分も話していて楽しいものに差し替えていく、とかも必要。


try! Swift では多くの登壇者がポケモンを題材にしていてその度に笑いが起きていたのは記憶に新しいところですが、今回 iOSCon でも @ayanonagon さんの "Boundaries In Practice" の話を聞く機会があり、そこにはポケモンの影はなく、掴みの話もアップデートされていました。その国の文化・カンファレンスのカラー・他の登壇者の発表といった文脈を汲んで、発表内容に少しでもアレンジを加えて最適化するのは大事だなと。


その他のアクティビティ

UIKonfはカンファレンスとして素晴らしく、参加者みんなの一体感があったのですが、その理由のひとつとして、開催日前日の「Social Event」が非常に良く機能していたと思います。


「Social Event」は、自転車ツアーやビール工房ツアー、ボートトリップツアー等から選べて、僕は(英語コミュニケーションが未だに怖いし発表の前日なのでスキップしようかと迷いながらも前々日ぐらいに)自転車ツアーに申し込みました。


f:id:shu223:20160529201310g:image


結果的にめちゃめちゃ参加して良かったです。


まず、自転車ツアーなので、そんなに周りの人とずっとしゃべってなくても良くて、たまーに横に並んだときにちょっとしゃべることがある、ぐらいの緩いコミュニケーションが僕にはちょうど良かった。


で、それぐらいでも効果は絶大で、翌日の本編では数百人の参加者が訪れるわけですが、そんな中で前日に数時間一緒にチャリこいだ人と会うと、妙な親近感がありました(しゃべったのは少しだけだとしても)。


あと、開催前夜にはキックオフパーティー、初日の夜にはスピーカーディナー、2日目の夜にはアフターパーティ*4と、毎晩何かしらの懇親会がありました。


f:id:shu223:20160529201311j:image:w600

(スピーカーディナー。ネイティブ && 超饒舌な人達に囲まれて全く話についていけず。。)


iOSConも開催前夜にスピーカーディナー*5、初日の夜にパーティがありました。


コスト

旅費・滞在費はカンファレンス側が出してくれました。なので、日本 ↔ ベルリン、ベルリン ↔ ロンドンの飛行機代、(会期中の)ベルリンとロンドンでのホテル代はかかっていません。もちろんカンファレンスのチケット代もかかっていません。


ただ、僕はフリーランスなのですが、前述の通り5月はほとんどスライド作成と練習に費やしました。結局仕事をしたのは2人日。僕は定期収入的な契約は一切してないので、5月の収入は2日分だけです。


得られたもの

そもそもカンファレンスに応募したのは、フリーランスとしての活動の場を海外に広げるための「入り口」を増やすための活動の一環でした。

ベルリンだけでなくシリコンバレー等に行っても毎回感じることですが、無力感が半端ないです。仕事をやってみたりハッカソンに出てみたりして、技術的に通用しないということはないと思ってますが、誰も僕のことを知らないし(知名度以前に知り合いがいないという意味で)、そういう僕がベルリンに行ったところで、現地の他のスタートアップの方から「会いたい」とか言われることはありません。


(中略)


僕がニュースとかで海外のそういう系の魅力的なプロダクトを見るタイミングではもう遅くて(メディアに出て話題になっているということはある程度開発が進んでいるか完了しているケースが多い)ファウンダーが資金調達して本格的に開発をしようとするタイミングであちらから見つけてもらえるようにならないといけない。


で、LinkedIn や AngelList で人を探す場合は大抵「住んでいる場所」でフィルタされてしまうので、英語ブログという「海外スタートアップに自分を見つけてもらうためのチャネル」を用意する必要があるなと。


僕のGitHubアカウントは今でも多少そういう感じの機能をしてくれてますが、(後略)

(以前書いた記事より)


で、具体的に考えていた「海外カンファレンスに登壇するメリット」は以下の通りです。

  • ログに残る
    • 英語でググッて見つかる「入り口」になる
  • 著名な常連スピーカーの方々に自分の話が届く
    • 別のカンファレンスにも呼ばれるかもしれない
  • 海外から仕事がくるきっかけになるかもしれない
  • 海外に行けるのが嬉しい/楽しい
    • 旅行もいいけど個人的には本業と絡んだほうが楽しい
    • 航空券代・ホテル代は出る(カンファレンスによるかもしれない)
  • 英語を「必死で」練習する機会になる
    • 30分ぶんの、自分の得意な分野について話す英語表現の「引き出し」 をつくる機会にもなる
  • 経歴に書ける

このうち、ログに残る、海外に行ける、英語表現の引き出し、あたりは参加した時点で自動的に達成されたわけですが、他の著名スピーカーが別のカンファレンスにも推薦してくれそうかというと、それにはまだまだかなと。


また「海外から仕事がくるきっかけになるかもしれない」という点については、今のところその気配はありませんが、仕事の話というのはいつでも忘れた頃に思わぬところから来るものなので、いつか今回の発表に起因する話が来るかもしれない、とは楽観的に思っています。ドイツから仕事が来るようになったときもそうでした)


経歴に書ける、というのは忘れてたので後でレジュメやLinkedInプロフィールに追記しておこうと思います。


あと、上記の目論見には書いてませんでしたが、何よりも良かったのは、「海外のカンファレンスに応募し、登壇する」という選択肢が自分の中で増えたことです。


未体験のものはいつでも何だって恐ろしくて、振り返ってみれば日本の勉強会に初めて参加したときは、参加すること自体が怖かったし、周りの人に話しかけることもできず逃げるように帰ったわけで、自分が発表するなんて考えられないことでした。こうやってひとつひとつ恐怖心を克服してコツコツ前進してきたので、(クオリティはまだまだですが)「できること」がまた増えて前進できたことが嬉しいなと。


評判

Twitterより


まとめ

書きたいことをずいぶん端折ったのですがそれでも長くなってしまいました。思い出に残る体験としても、キャリアの面からも、スキルアップの面からも、すごく良い経験ができたと思っています。


素晴らしいカンファレンスを主催されたオーガナイザーの方々、コーチしてくれた先生、未熟なプレゼン練習につきあってくれた方々、皆様に感謝いたします。



ちなみに来月、もうひとつ海外カンファレンスでの登壇が決まりました。

こちらもマルチトラック型、しかも(最近もらったスケジュールによると)とある百戦錬磨のスピーカーの裏・・・がんばります!


*1:僕のプロポーザルが両方で受理されたのもたまたまです。実際、両者の審査フローはまったく違っていました。

*2:ちなみに先生、東京マラソンに毎年仮装して出ていて、すごく有名な方です: http://josephta.me/

*3:気の利いた返しができなかったことが悔やまれますが。。Thank you しか言えなかった。

*4:会場が遠かったのとまだロンドン講演が控えてたので参加せず

*5:所用で参加できず

[BLE][iOS][電子工作][IoT]BLEを利用した汎用ロボットコアユニット「bCore」を触ってみる

$
0
0

バガボンド・ワークスさんが制作・販売されている「bCore」というハックしがいのある楽しいデバイスを紹介させていただきます。


f:id:shu223:20160601000549j:image:w600


サイトには「汎用多目的超小型リモコンロボットコアユニット」とあります。少し噛み砕くと、スマホからBLEでモーターとサーボをリモコン操作するユニットです。好きなプラモデルやおもちゃがスマホから操作できるようになります。


たとえばミニ四駆を1分でラジコンに改造したり、



もうちょっとメカに凝るとこんなロボットもつくれたりするようです。



現在スイッチサイエンスにて購入可能です。


以下は公式サイトの解説です。

技適対応のBLEモジュール(BLE113 )と周辺回路を組み込んだ超小型基板にファームウェアを焼きこんだ bCore と、iOS上で動くアプリケーションソフト bDriver を用いることで、誰もが簡単にiPhoneなどからコントロールできる超小型ロボットを製作できることを目的としています。


ファームは既に焼かれているので、ユーザーはラジコンサーボとモーターと電池をbCoreに繋ぎ、スチロール素材や木材、3Dプリンタなど、好みの方法でロボットのガワを制作するだけで自由に自分のロボットを開発できます。

技適、FCC、CE対応のBLEモジュールをしようしているため、日本、アメリカ、EU各国での使用が可能です。


キットの構成

某青い本を書いた縁で、バガボンドワークスさんよりbCore と、サーボやモーター等の互換パーツ一式をいただきました。


f:id:shu223:20160531153403j:image:w600


上記の各パーツもbCore同様に販売ページにて購入できます。キットとしての販売も予定されているそうです。


bCore をとりあえず試してみる

以下、まずはミニ四駆等の外部パーツを必要としない最小構成でbCoreを体験する手順を紹介します。すべてハンダ付け不要です。


ステップ1: iOSアプリからbCoreに接続してみる

まずは最初の一歩として、「bCoreにバッテリーボックスを繋げてアプリと接続する」ところまでをやってみます。


電源を繋げる

bCore の裏面を見ると、"Bat" と書いてあるところがあります。



該当するコネクタにバッテリーボックスを繋げます。一方向でしか挿せないので、極性を間違える心配もありません*1


f:id:shu223:20160531162621j:image:w500


これだけでもうBLEのペリフェラルデバイスとしての動作は開始しています。


(電源についての詳細 from 公式ページ)

bCoreの電源接続コネクタは、1.25mmピッチの2ピンコネクタ(Molex Pico Blade)で、入力可能な最大電圧は5.5Vとなっています。

アルカリ乾電池3本直列(4.5V)、LiPo電池1セル直列(3.6V)、LiFe電池1セル直列(3.3V)、カメラ用リチウム電池1本直列(3.0V)などが利用できます。ラジコンサーボやモーター駆動をするため、ある程度電流放出能力のある電池が必要になります。そのためボタン電池は使うことはできません。

なお、ラジコンサーボやモーターを繋がない場合は2.3V程度の電源での使用が可能です。


bDriver からスキャン・接続

bDriver というiOSアプリが公開されているので、ダウンロードします。


起動するとこんな感じの画面なので、


f:id:shu223:20160601114625j:image


"Start Scan" ボタンをタップしてスキャン開始します。


上述した通り bCore は電源が供給された時点でアドバタイズを開始するので、すぐに発見されリストに表示されます。


f:id:shu223:20160601114712j:image:w426


発見した bCore を選択すると接続が確立され、次のようなコントロール画面に遷移します。


f:id:shu223:20160601114741j:image:w426


たったこれだけです。要は、バッテリーボックスをコネクタに挿し、アプリをダウンロードして繋げるだけです。


ステップ2: サーボを動かしてみる

とりあえず動かしてみることに成功したところで、「ロボットコアユニット」らしく、キットに同梱されていたサーボをアプリから動かしてみます。


bCore にサーボを接続する

bCore 裏面に Srv1〜4 と書いてあるので、


f:id:shu223:20160531162222j:image:w400


該当するコネクタにサーボを接続します。


f:id:shu223:20160531171742j:image:w500


で、再び bDriver で接続して Srv1〜4 とあるスライダーを操作すると・・・


f:id:shu223:20160601115117g:image


サーボをスマホからリモコン操作できました!


ステップ3: モーターを動かす&LEDを光らせる

サーボと同じ(裏面で確認して該当するコネクタに挿すだけ)なので、全部繋げた写真だけ載せときます!


f:id:shu223:20160601000549j:image:w600


ミニ四駆をbCoreでラジコン化する

ここからが bCore の楽しいところです。サーボやモーターを動力として、色んなおもちゃやプラモデルをスマホから操作するように改造できるわけです。


バガボンドワークスさんのサイトにはいろんな作例が掲載されてまして、たとえばこのミニ四駆をラジコン化するレシピを見ると、

改造するのにプログラミンや電子回路の知識は不要です。

本当に1分でできます。

とあります。


必要なもののリストも「ハンダゴテ」「テープ」といったレベルで載っていて、手順も写真付きで非常に丁寧に書かれていて、本当に電気回路や電子工作の知識がなくてもこの手順通りにやればできそうです。


僕はいま諸事情で出先(海外)でこの記事を書いているのですぐに試せないのですが、ミニ四駆・ハンダゴテ・半田を既にAmazonで注文して家の方に送ってあるので、帰宅次第試してみたい所存です。


自作アプリに組み込む

GATTが公開されているので、Core Bluetooth を利用してアプリを自由に作成することも可能です。


このあたり、ソフトウェアエンジニアにとってはIRKitと同様のロマンがありますね。


下記ページからiOS向けのサンプルコードがダウンロードできます。


また同ページでは参考書籍として下記がオススメされています。


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

なお、iOSのBLEアプリ開発を真面目に学びたい人は、

iOS×BLE Core Bluetoothプログラミング 堤 修一 (著), 松村 礼央 (著)

断然おすすめです。bCoreの開発にもこの本を利用させていただきました。


・・・いや、結果的にステマっぽいですが、僕がバガボンドワークスさんと連絡を取り合い始めるずっと前にこれは書かれてたんですよ。。ほんとに。。

(エゴサーチしててたまたま発見しました)


ファームウェアを書き換える

ファームウェア書き込み用の端子も用意されているので、GATTを自分流に変えたいとか、何かしら特殊な処理をbCore側でしたい場合に、自分で書き換えることもできます。


BLE113なのでBGScriptやファーム書き込み等の開発環境をMacに構築したい場合には下記記事も参考になるかもしれません。


おわりに

大変ワクワクする、大人も子供も楽しめそうなプロダクトではないでしょうか。早く家に帰って僕のアバンテJr.をラジコン化したいです。


*1:間違えられませんが、仮に間違えても保護回路が入っているので壊れないそうです

[iOS][Swift]【iOS 10】API Diffsから見る iOS 10 の新機能 #WWDC2016

$
0
0

タイムラインでは「つまんねー」「Apple終わってる」「ジョブズがいればこんなことには・・・」という落胆の声をたくさん見かけましたが、"iOS 10.0 API Diffs" や "What’s New in iOS" 等のプレリリースドキュメントを見ると今回も新しい機能が数多く追加されていて、個人的には非常にワクワクしております。


f:id:shu223:20160614084804j:image:w600


以下、気になったものを列挙していきます。


VoIP API / CallKit

BONXというVoIP通話するプロダクトを手伝っている関係で、IP通話がどんな感じでできるようになるのか(サーバーは自分で用意するのかとか)、非常に気になります。


"Speakerbox: Using CallKit to create a VoIP app" という公式サンプルが公開されているので、後でコードを見てみようと思います。


SiriKit / Intents / IntentsUI

ついにSiriのAPIが開発者に開放されました。What's New in iOS でも一番上に書かれているので、Appleとしても iOS 10 の目玉と考えているのではないでしょうか。


SiriKit というフレームワークがあるわけではなくて、Intents / Intents UI というフレームワークがその実体となるようです。以下の6つのドメインをサポートする、とのこと。

  • Audio or video calling
  • Messaging
  • Sending or receiving payments
  • Searching photos
  • Booking a ride
  • Managing workouts

これだけ見ても何がどんな感じでどこまでできるのか、全然ピンと来ないので、後ほど以下の公式サンプルを試してみます。

  • IntentHandling: Using the Intents framework to handle custom Siri request
  • UnicornChat: Extending Your Apps with SiriKit

音声認識API / Speech

SiriKitとは別に、音声認識のAPIが追加されました。リアルタイム音声にも、録音済み音声にも使えるようです。

let recognizer = SFSpeechRecognizer()
let request = SFSpeechURLRecognitionRequest(url: audioFileURL)
recognizer?.recognitionTask(with: request, resultHandler: { (result, error) in
     print (result?.bestTranscription.formattedString)
})

"SpeakToMe: Using Speech Recognition with AVAudioEngine" という公式サンプルが公開されているので、すぐに試せます。SFSpeechRecognizerの初期化時に Locale を渡せるようになってますが、日本語もいけるのでしょうか(あとでやってみます)

private let speechRecognizer = SFSpeechRecognizer(locale: Locale(localeIdentifier: "en-US"))!

(2016.6.15追記)実際に触ってみて記事を書きました!


AVFoundation

AVCapturePhotoOutput

AVFoudationで写真を撮る際に使用していた AVCaptureStillImageOutput が deprecated になり、iOS 10 では AVCapturePhotoOutput という新クラスを使うようです。すべての写真ワークフローにunifiedなパイプラインを提供する、とのことですがカメラに詳しいわけでもないので使ってみないとわからないのですが、AddedなAPIを見ていると、Live Photo 撮影機能が開発者に開放されてたりと、色々とできることが増えてそうです。

AVCapturePhotoCaptureDelegate.capture(_: AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt: URL, duration: CMTime, photoDisplay: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: NSError?)
AVCapturePhotoCaptureDelegate.capture(_: AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt: URL, resolvedSettings: AVCaptureResolvedPhotoSettings)
AVCapturePhotoOutput.isLivePhotoAutoTrimmingEnabled
AVCapturePhotoOutput.isLivePhotoCaptureEnabled
AVCapturePhotoOutput.isLivePhotoCaptureSupported
AVCapturePhotoOutput.isLivePhotoCaptureSuspended
AVCapturePhotoSettings.livePhotoMovieFileURL
AVCapturePhotoSettings.livePhotoMovieMetadata
AVCaptureResolvedPhotoSettings.livePhotoMovieDimensions

AVPlayerLooper

メディア(オーディオ・ビデオのことだと思われる)の特定箇所を簡単にループさせられるクラス、とのこと。


Messages

長々とキーノートで紹介されたMessagesアプリの新機能。「使ってないし。。」という声を多くタイムラインで見かけました。が、Messagesというフレームワークが追加され、開発者ができることも何やら増えたようです。


What's New によると、App ExtensionをつくってMessagesアプリと自分のアプリを連携させられるようです。つくれるApp Extensionは以下の2種類:

  • ステッカーパック(ユーザーがMessagesで使うことができる)
  • Messages内で使えるカスタムUI(iMessage appと呼ぶ)

"Ice Cream Builder: A simple Messages app extension" という公式サンプルが公開されています。あとリファレンスもパッと見ですがプログラミングガイド的にわかりやすく書かれてそうでした。


Core Image

キーノートでのPhotosの話の中で、顔だけじゃなくて「乗馬」みたいなシーンも認識するようになった、という話があって、CIDetector, CIFeatureにもそのへん追加されてるのかなと思ったら API Diffs には残念ながらそういう変更が見当たりませんでした


フィルタは以下の5つが追加されたとのこと。アップサンプリングフィルタはちょっと試してみたい。

  • CINinePartTiled
  • CINinePartStretched
  • CIHueSaturationValueGradient
  • CIEdgePreserveUpsampleFilter
  • CIClamp

僕は一眼レフユーザではないので使わなそうですが、RAW画像を扱えるようになったとのこと。

RAW image file support is now available on iOS devices that use the A8 or A9 CPU. Core Image can decode RAW images produced by several third-party cameras as well as images produced by the iSight camera of supported iOS devices (to learn more, see AVFoundation). To process RAW images, use filterWithImageData:options: or filterWithImageURL:options: to create a CIFilter object, adjust RAW processing options with the keys listed in RAW Image Options, and read the processed image from the filter’s outputImage property.


あと、`imageWithExtent:processorDescription:argumentDigest:inputFormat:outputFormat:options:roiCallback:processor:` というメソッドが何か重要そうなのですが、理解に自信がないのでWWDCのセッション見てからコメントします。

You can now insert custom processing into a Core Image filter graph by using the imageWithExtent:processorDescription:argumentDigest:inputFormat:outputFormat:options:roiCallback:processor: method. This method adds a callback block that Core Image invokes in between filters when processing an image for display or output; in the block, you can access the pixel buffers or Metal textures containing the current state of the processed image and apply your own image processing algorithms.


MapKit

Addedは以下の3つだけ。

MKAnnotationView.init(coder: NSCoder)
NSUserActivity.mapItem
MKLaunchOptionsDirectionsModeDefault

キーノートではMapアプリの新機能の話があったのに、これだけ?と一瞬思いましたが、NSUserActivity に追加された `mapItem` というプロパティが重要っぽいです。What's New の Proactive Suggestions の項に以下のように解説されています。

In iOS 10, the NSUserActivity object includes the mapItem property, which lets you provide location information that can be used in other contexts. For example, if your app displays hotel reviews, you can use the mapItem property to hold the location of the hotel the user is viewing so that when the user switches to a travel planning app, that hotel’s location is automatically available. And if you support app search, you can use the new text-based address component properties in CSSearchableItemAttributeSet, such as thoroughfare and postalCode, to fully specify locations to which the user may want to go. Note that when you use the mapItem property, the system automatically populates the contentAttributeSet property, too.

キーノートで話してた機能と関連することだとは思いますが、正直これも自分で試してみないとよくわからない。。


Core Bluetooth

ある程度枯れてるのでハード的にBluetooth 5.0がサポートされるとかがない限りはそんなに変更ないかなと思ってましたが、やはりそんなに大きな変更はありませんでした。


主な変更点としては、

CBCentralManager.state
CBPeripheralManager.state

がなくなって、代わりにこれらの状態を管理するクラス CBManager というのが追加された、という点です。Bluetoothの状態をこのクラスから取るようになった、というだけかと。

CBManager.state
CBManagerState [enum]
CBManagerState.poweredOff
CBManagerState.poweredOn
CBManagerState.resetting
CBManagerState.unauthorized
CBManagerState.unknown
CBManagerState.unsupported

また、CBCentralManager と CBPeripheralManager に引数なしの初期化メソッドが追加されました。

CBCentralManager.init()
CBPeripheralManager.init()

あと、キャラクタリスティックのValueの有効範囲を指定する Descriptor の UUID を示す定数が追加されています。

CBUUIDCharacteristicValidRangeString

(Valid Range ディスクリプタのドキュメント)


Core Motion

Significant Elevation まわりのAPIが追加されていて、(Core Locationの)Significant Location のようにバックグラウンドでバッテリーを節約しつつ大まかな高度の変化を取れるような感じになったのかなと。

CMAltimeter.isSignificantElevationAvailable() -> Bool [class]
CMAltimeter.querySignificantElevationChange(from: Date, to: Date, withHandler: CoreMotion.CMSignificantElevationSampleHandler)
CMAltimeter.startSignificantElevationUpdates(handler: CoreMotion.CMSignificantElevationSampleHandler)
CMAltimeter.stopSignificantElevationUpdates()
CMSignificantElevationSample
CMSignificantElevationSample.elevationAscended
CMSignificantElevationSample.elevationDescended
CMSignificantElevationSample.endDate
CMSignificantElevationSample.startDate
CMSignificantElevationSampleHandler

新App Extension

個人的にはExtensionは全然つくってないのですが、「開発者ができること」としては重要なので、何が追加されて何ができるようになったのか、はおさえておきたいと思っています。


iOS 10 では以下の Extension Points が追加になったようです。

  • Call Directory
  • Intents
  • Intents UI
  • Messages
  • Notification Content
  • Notification Service
  • Sticker Pack

あと、サードパーティ製のキーボードのExtensionが強化されたとのこと。


あとで見る

Proactive Suggestions

いろいろ賢くなったよ、という話っぽいが、What's New で長めに書かれていて、関連フレームワーク・クラスも多いので後で読む。


UserNotifications / UserNotificationsUI / VideoSubscriberAccount

新フレームワークだけど、名前的には必要になったときに見ればいいかな、と思うのでまた後ほど。


その他、あまり変更がなかったフレームワーク

ここに書いた以外にもたくさんありますが、API Diffsでページを開いて見たものの中で、追加APIがなかった、もしくは「ほとんど」なかったものもまとめておきます。


以下はAddedなAPIなし。

  • AudioUnit
  • CoreLocation
  • CoreAudioKit
  • ExternalAccessory
  • OpenAL
  • MultipeerConnectivity
  • HealthKitUI

以下はほとんどAddedなし、もしくは気になる変更がなかった。

  • AVKit
  • CoreAudio
  • OpenGLES

watchOS 3 の新機能

量が多いので、別記事としてまとめました。個人的には改善して欲しかったところがちゃんと改善されてて好印象です。


[watchOS][IoT][iOS][Swift]【watchOS 3】API Diffsから見る watchOS 3 の新機能 #WWDC2016

$
0
0

世間から「コレジャナイ」と見放されつつある印象のある Apple Watch / watchOS ですが、APIの面では改善して欲しかった点がちゃんと改善されて、個人的にはまた久々に触ってみたくなっています。


watch.png


以下、「watchOS 3.0 API Diffs」「What’s New in watchOS」等のプレリリースドキュメントを見て気になった新APIを列挙していきます。


WKCrownSequencer / WKCrownDelegate

ついに!やっと!デジタルクラウンの状態が取れるようになったようです。watchOS 2ではスクロール系のUI操作に使えるだけで、操作をフックしたり、値を取ったりできなかったですからね。。

WKCrownDelegate
WKCrownDelegate.crownDidBecomeIdle(_: WKCrownSequencer?)
Added WKCrownDelegate.crownDidRotate(_: WKCrownSequencer?, rotationalDelta: Double)
WKCrownSequencer
WKCrownSequencer.delegate
WKCrownSequencer.focus()
WKCrownSequencer.isIdle
WKCrownSequencer.resignFocus()
WKCrownSequencer.rotationsPerSecond

WKGestureRecognizer

Gesture Recognizer が watchOS でも使えるようになりました。

  • WKLongPressGestureRecognizer
  • WKPanGestureRecognizer
  • WKSwipeGestureRecognizer
  • WKTapGestureRecognizer.

いや、これ自体嬉しいのですが、そもそもの不満として、これまでユーザーがタップした座標を開発者が知るすべがなかったのですが、

WKGestureRecognizer.locationInObject() -> CGPoint

WKPanGestureRecognizer.translationInObject() -> CGPoint

が追加されて、タップした座標とかパンした移動先とかを取れるようになるってことがとにかく重要かと。watchOS 2 の頃はこれができないためにあきらめた機能が色々とあった気がします。今すぐに良い例が思い浮かばないのですが、たとえばタップした位置にCore Graphicsで何かを描画するとか。


バックグラウンドタスク

ついに来たという感じです。watchOS 2 のころ色々と辛かったのが、アプリが最大75秒でdeactivateされるという制約で、せっかく「ウェアラブル」、つまり「つけっぱなしにできる」のに、アプリは動かしっぱなしにはできない、という事態になってました。お客さんから「こういうことやりたい」と相談されたアイデアのうち、この制約のせいで実現できないものがなんと多かったことか。。


で、watchOS 3 では(いくつかのケースで)バックグラウンドで処理を実行できるようになりました。以下の種類があるそうです。

Background App Refresh

Use the `WKApplicationRefreshBackgroundTask` class to update your app’s state in the background. You often use a background app refresh task to drive other tasks. For example, you might use a background app refresh task to start an NSURLSession background transfer or to schedule a background snapshot refresh task.

Background Snapshot Refresh

Use the `WKSnapshotRefreshBackgroundTask` class to update your app’s user interface. You can push, pop, or present other interface controllers, and then update the content of the desired interface controller. The system automatically takes a snapshot of your user interface as soon as this task completes.

Background Watch Connectivity

When you receive background data from the paired iPhone, the system launches your app in the background, instantiates a `WKWatchConnectivityRefreshBackgroundTask` object, and passes the task object to your extension delegate’s handleBackgroundTasks: method.

Background URL Session

When a background transfer requires authorization, or when a background transfer completes (successfully or unsuccessfully), the system creates a background NSURLSession event, instantiates a `WKURLSessionRefreshBackgroundTask` object, and passes the task object to your extension delegate’s handleBackgroundTasks: method

To learn more about handling background tasks in general, see Background Refresh Tasks.


解説を端折ると語弊が生じる気がするので What's New の記述をそのまま引用しました。それぞれの解説だけざっと読むと結構色んなことができるんじゃ、という気がしてきますが、こういうのは実際に試してみないとわからないですね。


WatchConnectivityを用いた本体側(iOS)との通信は、watchOS 2では ウォッチ側はフォアグラウンドじゃないと通信できなかった のでこれは嬉しいアップデート。


Workoutのバックグラウンドサポート

Workoutもバックグランドで動作させられるようになったとのこと。対応方法は Info.plist の WKBackgroundModes キーに `workout-processing` を追加するだけ。ちなみに Xcode 8 の Capabilities からも On/Off できます。(NDA期間中につきスクショは自粛)


AVFoundation

watchOS でも AVFoudation が使えるように!


全部のクラスが移行されるわけではないのですが、オーディオファイル再生クラスである `AVAudioPlayerNode` とか、オーディオ処理諸々(各種エフェクトとか)を司る `AVAudioEngine` (詳しくはこちら)とか、音声合成の `AVSpeechSynthesizer` とか、色々入ってます。ちゃんと動くかは実際に試してみないとわかりませんが。*1


ジャイロスコープの値の取得

API的には2からあったんですが、`gyroAvailable` プロパティで必ず `false` が返ってきて実質的に非サポートでした。Apple Watch 2 とか新しいハードが出たら使えるようになるのかなと思ってましたが、wathcOS 3 で取得できるようになるようです。


ジェスチャー・姿勢認識をやろうと思ったら加速度センサだけじゃなくてジャイロの値も大抵必要になるのでこれも嬉しい更新。


あと、iOS 10 編 で書いた Significant Elevation関連と、CMPedometer関連のAPIが追加されています。


ちなみに最大100Hz周期で取れるそうです。

Device Motion, which fuses outputs from the accelerometer and gyroscope into orientation and motion dynamics updates. Apps can register to receive these updates at rates up to 100Hz.


Core Motion の歩数取得イベントはバックグランドでも取れるらしい。

On supported devices, apps can use CMPedometer APIs to register to receive live pedometer events while running in the foreground or the background.


WKInterfaceInlineMovie

動画再生インターフェース。watchOS 1 の頃、動画再生っぽいことをやるために、動画をアプリ側で動的にフレーム毎に分解して間引いてpngシーケンスアニメーションを生成(いわゆるパラパラ漫画)してウォッチ側で再生する、ということをやってましたが(たぶんみんなこうしてた)、今となっては普通に動画を再生できるようになったようです。


SceneKit / SpriteKit サポート

  • WKInterfaceSCNScene
  • WKInterfaceSKScene

詳細は後で読む。


HomeKit

HomeKitのカメラ・ドアベル(日本で言えば呼び鈴)アクセサリをサポートしたとか。それ用のサービス・キャラクタリスティックが追加されたらしい。


WKInterfaceHMCamera というインターフェースのクラスも追加されていて、これはHomeKitのIPカメラのデータにアクセスするためのインターフェースだそうです。*2


iOS 10 の新機能

量が多いので別記事としてまとめました。


*1:APIとしては存在しても実際はサポートされてない、ということもたまにあります。

*2:そもそも HomeKit 対応のネットワークカメラがまだ日本では販売されてないわけですが。。(されてたらすみません)

Viewing all 317 articles
Browse latest View live