Hatena::ブログ(Diary)

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

2012-05-26

『第2回 iphone_dev_jp 東京iPhone/Mac勉強会』で vImage について発表・・するつもりで参加してきました

めんどくさいタイトルですいません。。


僕がこの勉強会のATNDに気づいたころには120人の参加者枠もとっくにうまり、発表者枠も既に10人に達していたのですが、「時間がもし余ったら」と @k_katsumi さんの粋な計らいでLT補欠として参加させていただいた、というわけでこのタイトルになりました。


で、結果として時間はちょうどいい感じに10人の発表で終了時間となりLT枠はなかったのですが、いちおう資料とサンプルコードはつくってアップしておいたのでこちらにも載せておきます。



iOS 5 から追加された vImage について紹介しています。


資料の内容抜粋

  • vImageとは
    • Accelerate.framework内のライブラリ
    • iOSデバイスのハードウェア向けに最適化されていて高速
    • 畳み込みや幾何変換,ヒストグラム計算などの画像処理系の関数をまとめたものでiOS5から利用可能
  • 何がいいの?
    • シンプルに書ける
    • 速い・・・14倍高速!!
    • 省電力・・・90%off!!
  • vImageの使い方
    • Accelerateフレームワークをプロジェクトに追加し、 Accelerate.hをインポートすればOK
#import <Accelerate/Accelerate.h>
  • OpenCV vs vImage
  • ドキュメント
    • WWDC2011のセッションビデオ&スライド
      • 概要を知るには一番わかりやすい
    • vImage Programming Guide
      • 処理前後のサンプル画像や、フィルタ配列の図もあってわかりやすい
    • vImageリファレンス
      • たくさんあるので必要に応じてどうぞ・・・
      • Conversion / Convolution / Decompression / Geometry / Histogram / Morphology / Transform etc...
  • vImageを使用している画像処理ライブラリ

サンプルコード

githubに上げたサンプルコードは UIImage のカテゴリとして作ってあってAPIも下記のようにシンプルにしてあります。

-(UIImage*)gaussianBlur;
-(UIImage*)edgeDetection;
-(UIImage*)emboss;
-(UIImage*)sharpen;
-(UIImage*)unsharpen;

実行して画面をタッチするとこんな感じで vImage による画像処理が適用されます。


f:id:shu223:20120526174615p:image:w320


※左上がオリジナル画像です。


補足など

資料に書いてなくて発表のときに口頭で話そうと思ってたこととして、「畳み込みと色空間変換と拡大縮小とヒストグラムでかなり色んな画像処理ができる」ということがあります。


で、一番処理的に重いのが畳み込みなので、畳み込みが高速化されるようになるということは画像処理にとって相当ありがたいことです。


というわけで資料では vImageConvolve_ARGB8888() しか紹介していませんがこれだけでも結構 vImage の恩恵があるんじゃないかと思っております。



ちなみに他の発表者の皆様のスライドが下記にまとまっていて、とても勉強になります。

http://slidrs.net/sessions/13


で、このなかに @kamiyan さんの『簡単!OpenGL ES2.0フラグメントシェーダー』という発表がありまして、これを見てると、本気で画像処理を高速化するのであればシェーダを書いてOpenGL ES2.0で処理するのが一番速そうです。(ちなみにこの発表はシェーダをiPhone上で書けて実行できるサンプルアプリつき!!!)


このあたりはまた勉強して新しく知ったことなどを別記事でまとめたいと思います。



2012-05-25

Assets Library を利用した高速フォトビューア

1年以上前にこちらの記事で Assets Library の読み込みを高速化する試行錯誤について書かせていただきましたが、そのときに作った『i走馬灯』という高速フォトビューアアプリを作り直して再リリースしました。


f:id:shu223:20120525083606p:image

i走馬灯 〜超高速フォトビューア

※無料です



再リリースの経緯

もともと iPhone 4 のカメラの解像度でも高速表示は厳しかったのですが、iPhone4S になってさらにカメラの解像度が上がり、もはや「走馬灯」といえるスピードは出せなくなっていました。(iPhone 4Sの処理速度でも)


描画をOpenGLで行うことも検討してみましたが、

ALAsset *aseet = (ALAsset *)[self.assets objectAtIndex:currentAssetIndex];
ALAssetRepresentation *representation = [asset defaultRepresentation];
UIImage *img = [UIImage imageWithCGImage:[representation fullResolutionImage]
                                   scale:[representation scale]
                             orientation:[representation orientation]];

結局この ALAssetRepresentation から fullScreenImage なり fullResolutionImage なりで CGImageRef を取り出しているところが時間かかってるっぽくて、描画を高速化してもここがボトルネックになるんではと思い断念しました。


で、

ALAsset *asset = (ALAsset *)[self.assets objectAtIndex:currentAssetIndex_];
UIImage *img = [UIImage imageWithCGImage:[asset thumbnail]];

このように『ALAsset から直接 thumbnail メソッドで CGImageRef を取り出す』方式だと非常に高速で、それを6個、12個、24個と増やしても相変わらずチョッパヤだったので、もうサムネイル表示だけでいこうってことで、「サムネイルを高速表示するアプリ」として作り直した次第です。


f:id:shu223:20120525090111p:image:w480


ちょっといい感じの写真が iPhone に入ってなくてスクリーンショットを用意しなかったのですが、上記6分割、12分割の他にも、24分割モードがあります。


無料なのでぜひお試しいただけると幸いです!



2012-05-12

逆ジオコーディングで取得した CLPlacemark の住所情報の内容

先日CLGeocoder を用いた逆ジオコーディングの記事を書きましたが、その結果得られる CLPlacemark 型の addressDictionary プロパティに入っている住所情報について、どのキーがどういう情報なのか、国ごとにどういう違いがあるのか、毎回調べるのが面倒なのでここに書いておきます。


近所で位置情報を取得し逆ジオコーディングし、addressDictionaryの内容をログ出力するとこんな感じでした。(エンコードおかしいですが気にしないでください・・・)

City = "\U938c\U5009\U5e02";
Country = "\U65e5\U672c";
CountryCode = JP;
FormattedAddressLines =     (
                             "\U3012248-0007 \U795e\U5948\U5ddd \U938c\U5009\U5e02 \U5927\U753a 2\U4e01\U76ee6\U756a13\U53f7"
                             );
Name = "\U5927\U753a 2\U4e01\U76ee6\U756a13\U53f7";
State = "\U795e\U5948\U5ddd";
Street = "\U5927\U753a 2\U4e01\U76ee6\U756a13\U53f7";
SubLocality = "\U5927\U753a";
SubThoroughfare = "6\U756a13\U53f7";
Thoroughfare = "\U5927\U753a 2\U4e01\U76ee";
ZIP = "\U3012248-0007";

ここからわかることは、

  • FormattedAddressLines には、"ZIP", "State", "City", "Street"の順に入っている
  • 日本でいうと、"State"は都道府県、"City"は市区町村にあたり、"Street"には「小町 2丁目3番1号」といったような町名地番が入る
  • "Street" は、"Thoroughfare" と "SubThoroughfare" を繋げたもので、"SubLocality" は町名(市区町村以降の地名。"Thoroughfare" にも含まれる)


ただどの国でもこれらの項目が得られるかというとそうではなく、たとえばチュニジアの緯度経度で逆ジオコーディングすると、

Country = "\U30c1\U30e5\U30cb\U30b8\U30a2";
CountryCode = TN;
FormattedAddressLines =     (
"RN 3E",
"\U30c1\U30e5\U30cb\U30b8\U30a2"
);
Name = "RN 3E";
State = "\U30b7\U30c7\U30a3\U30d6\U30b8\U30c3\U30c9";
Street = "RN 3E";
Thoroughfare = "RN 3E";

addressDictionaryにはこういう感じの結果が返ってきました。


"City" や "SubThoroughfare" 、"SubLocality" といった項目がはいっていません。データがないのか、もともと住所の構造がシンプルなのかわかりませんが、日本と同様に市区町村にあたる項目があるという前提で処理を書くとおかしなことになりそうです。



そもそもこういうのは世界共通で規格みたいなものがあるのかもしれないので、こういう場当たり的な調べ方は的外れなのかもしれません。悪しからず・・・



2012-05-06

iOS 5.0 より追加された CLGeocoder を使用して逆ジオコーディング

Appleのドキュメントによると

iOS 5.0では、MKReverseGeocoderとMKReverseGeocoderDelegateは非推奨になっているの で、新たにアプリケーションを開発する場合はCLGeocoderを使ってください。

とのことなので、逆ジオコーディングを CLGeocoder を使用してやってみたのでその手順をこちらにメモしておきます。

(上記Appleのドキュメントのコードは少しずつ変数名が間違ってたり、独自定義のクラスが引数の型に指定されていたりして、そのままでは使いづらい・・・)


で、手順といってもヘッダのインポートやオブジェクトの生成とかを除けば、

  • reverseGeocodeLocation:completionHandler: を呼ぶ

これしかありません・・・


僕の場合は下記のようにクラスメソッドを定義しました。

+ (void)reverseGeocodeLocation:(CLLocation *)location
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:
     ^(NSArray* placemarks, NSError* error) {
         if ([placemarks count] > 0) {
             
             CLPlacemark *placemark = (CLPlacemark *)[placemarks lastObject];

             // 取得したplacemarkを格納したNSNotificationを発行
         }
     }];
}

Blocksで非同期に処理されるので、CLPlacemarkオブジェクトを取得したらNSNotificationを発行して必要なオブジェクトに通知するようにしました。


なお、reverseGeocodeLocation:completionHandler: で得られる値が NSArray 型になっていますが、CLGeocoderのクラスリファレンスによると

Contains an array of CLPlacemark objects. For most geocoding requests, this array should contain only one entry. However, forward-geocoding requests may return multiple placemark objects in situations where the specified address could not be resolved to a single location.

とあり、逆ジオコーディングのときは基本的に1つしかオブジェクトが入ってこないと思ってよさそうです。(正ジオコーディングのときはアドレス→緯度経度なので、1つとは限らないため、NSArrayになっている)



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