GoogleのCloud Vision APIを試してみた

Googleの画像認識&分類APIを試してみました。
http://jp.techcrunch.com/2016/02/19/20160218google-opens-its-cloud-vision-api-to-all-developers/
 
まずは登録
https://cloud.google.com/vision/
 
登録後、ドキュメンテーション読む
https://cloud.google.com/vision/reference/rest/v1/images/annotate?hl=ja
 
で、ドキュメンテーションの下方にTry it!と入力フォームが用意されているのでそれを使って試す。
フォーム入力の場合はURIの入力が不要だが、フォーム以外の入力の場合はAPI Keyが必要。
 

POST https://vision.googleapis.com/v1/images:annotate?key={YOUR_API_KEY}

{
	"requests": [{
		"image": {
			"source": {
				"gcsImageUri": "gs://[BUCKET_NAME]/fuga.jpg"
			}
		},
		"features": [{
			"type": "TYPE_UNSPECIFIED",
			"maxResults": 3
		}, {
			"type": "LANDMARK_DETECTION",
			"maxResults": 3
		}]
	}]
}

 
gcsImageUriはGoogle Cloud Storageに事前にアップロードされたファイルを指定し使用する。
直接アップする方法もあるようだが今回は省略。
 
入力フォームの場合、これでExecuteボタンを押すと実行される。
この例ではランドマークを解析。
 
で結果
やはり万能ではない様子。だが特徴的な建物などは高精度で認識された。
自然風景は無理か?ウユニ塩湖は認識されなかった。
顔認識はなかなか高精度。ただサンプル画像では手にりんごを持っていたがりんごは認識されなかった。

iOS9.3でobserveValueForKeyPathが2度呼ばれる話

昨日公開されたiOS9.3の話。まずはコードを。

- (void)buttonTapped:(id)sender {
    NSLog(@"buttonTapped");
    
    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:@"1" forKey:@"hogehogehoge"];
    [defaults synchronize];
}

- (void)viewDidLoad {
    [super viewDidLoad];   
    // Do any additional setup after loading the view, typically from a nib.
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn1 addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
    [btn1 setFrame:CGRectMake(0, 20, 100, 44)];
    [btn1 setTitle:@"test" forState:UIControlStateNormal];
    [self.view addSubview:btn1];
    
    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
    [defaults addObserver:self forKeyPath:@"hogehogehoge" options:0 context:nil];    
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{    
    if ([keyPath isEqualToString:@"hogehogehoge"]) {
        NSLog(@"observeValueForKeyPath object = %@ change = %@ context = %@", object, change, context);
    }
}

で実行結果
iOS9.2

016-03-23 17:54:44.916 ios93Test[11457:4534369] buttonTapped
2016-03-23 17:54:44.920 ios93Test[11457:4534369] observeValueForKeyPath object = <NSUserDefaults: 0x13ed06d90> change = {
    kind = 1;
} context = (null)
2016-03-23 17:55:00.574 ios93Test[11457:4534369] buttonTapped
2016-03-23 17:55:00.575 ios93Test[11457:4534369] observeValueForKeyPath object = <NSUserDefaults: 0x13ed06d90> change = {
    kind = 1;
} context = (null)

iOS9.3

2016-03-23 18:07:19.694 ios93Test[1467:322189] buttonTapped
2016-03-23 18:07:19.697 ios93Test[1467:322189] observeValueForKeyPath object = <NSUserDefaults: 0x13d608c20> change = {
    kind = 1;
} context = (null)
2016-03-23 18:07:19.698 ios93Test[1467:322189] observeValueForKeyPath object = <NSUserDefaults: 0x13d608c20> change = {
    kind = 1;
} context = (null)
2016-03-23 18:07:23.509 ios93Test[1467:322189] buttonTapped
2016-03-23 18:07:23.509 ios93Test[1467:322189] observeValueForKeyPath object = <NSUserDefaults: 0x13d608c20> change = {
    kind = 1;
} context = (null)
2016-03-23 18:07:23.509 ios93Test[1467:322189] observeValueForKeyPath object = <NSUserDefaults: 0x13d608c20> change = {
    kind = 1;
} context = (null)

なーぜか、2回呼ばれる。
UnityのPlayerPrefsから来る時も2回。

さてググっても全くヒットしないのですが、僕だけでしょうか・・

画面のロック、アンロックを検知する方法

厳密には画面のロック状態が変更されたことを検知する方法、になります。

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                        NULL, // observer
                                        displayStatusChanged, // callback
                                        CFSTR("com.apple.springboard.lockcomplete"), // event name
                                        NULL, // object
                                        CFNotificationSuspensionBehaviorDeliverImmediately);
        
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                        NULL, // observer
                                        displayStatusChanged, // callback
                                        CFSTR("com.apple.springboard.lockstate"), // event name
                                        NULL, // object
                                        CFNotificationSuspensionBehaviorDeliverImmediately);

----

static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
}

参考
http://stackoverflow.com/questions/14229955/is-there-a-way-to-check-if-the-ios-device-is-locked-unlocked

新アプリ「もしも」をリリースしました

新アプリ「もしも」をリリースしました。
長時間ロック状態が続くとメールを送ってくれる、もしもの時に活躍するかもしれないアプリです。

もともとは一人暮らし向けの、急病で寝るしかなくて
スマホにまで気が回らない時にあると助かるアプリとして考えたのですが、
小中高生のお子様にスマホを持たせている親御さんが
お子様のスマホにインストールしてあげても使えるかもしれません。
いや使われないに越したことはないのですが。

設定画面。画面はこれだけ。
位置情報の送信やFacebook, Twitterへの送信もここで有効、無効にできます。

常時バックグラウンドで稼働し、画面がロックされるとONになります。

画面がロック解除されるとOFFになります。

ダウンロードはこちら
https://itunes.apple.com/jp/app/moshimo-zhang-shi-jianrokku/id847342417?mt=8

mmView 1.1.0アップデート申請

プライベート制作の時間がなかなか取れない今日このごろ。
皆様如何お過ごしでしょうか。


さてmmViewのアップデートです。
正月休みで少し時間が出来たので一気にやりました。
・ソース作り直し。UIは同じだけど中身は一新。
・ARC対応
・iOS7対応。ようやくできた。
 普段は画像パーツをふんだんに使ったものを作っているので
 ここはあえて基本的なUIKitの部材のみを使ったもので継続。
・アルバム編集後に落ちる、アルバム編集時にチェックボックスが違う画像に付くなどのバグを修正。


です。

mmView 1.0.5アップデート申請

mmViewのアップデート申請を行いました。
・アルバムの数が増えてくると広告に隠れて追加できない問題を修正
・編集、削除アイコンをリニューアル
・広告SDKを最新版に差し替え

しかしこのアプリ、DL数こそ少ないものの
結構使って頂いているようで、非常に有難いです。

私自身も、毎日使ってます。
DL数が増えないのは便利だけどニッチ過ぎるのかもなあ・・

【ハマった】libpng error: Incompatible libpng version in application and library【困った】

どうもです。
コーディングしていてハマった話。


iOS6.1になってから実行しようとすると
タイトルのようなエラーが出てアプリがクラッシュするようになってしまいました。
分かったことは以下の2点
iOS5系だと発生しない
・プロジェクト内にlibpngがあると何らか競合するっぽい。


ただlibpngを外すとビルドできないしなあ・・
他でpng読み込んでいるところって、画像パーツを読み込む標準機能そのものってことになるし・・


で結論
プロジェクト設定からリンクする順番を変更して解決した。
(さらっと書いてますが解決するまでに1週間くらい悩みました)