Archive for the 技術情報 Category

Using OpenCV on iOS 6.0

OpenCVをビルドして、iOSで使用するまでのステップをまとめます。
環境は以下の通りです。

  • xcode 4.5.1 (iOS 6対応)
  • OpenCV 2.4.2
  • iPhone 5

1. OpenCVをダウンロードする
まずはOpenCVをダウンロードします。
これを書いている時点での最新バージョンは 2.4.2です。
OpenCV-2.4.2.tar.bz2
ファイルを解凍し、適当なディレクトリーにコピーして下さい。

2. OpenCVをビルドする
OpenCVのディレクトリ名を”opencv”に変更し、pythonのスクリプトを実行します。

$ mv OpenCV-2.4.2 opencv
$ python opencv/ios/build_framework.py ios

時間は少々かかりますが、先ほどのopencvディレクトリと同じ階層に”ios”というディレクトリが作成され、必要なものはそこにまとめられます。

3. xcodeでプロジェクトを作成
プロジェクトのタイプは何でも良いと思います。
作成したプロジェクトの $(PROJECT_NAME)-Prefix.pch を開き下記の部分を追加して下さい。

#import

#ifndef __IPHONE_3_0
#warning “This project uses features only available in iOS SDK 3.0 and later.”
#endif

#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#endif

4. opencv.frameworkの追加
先ほどビルドしたiosディレクトリをプロジェクトのディレクトリにコピーし、
opencv.framework (ios/opencv.framework )ディレクトリをプロジェクトに追加します。ドラッグ&ドロップでOKです。

4. テストプログラムのビルド
とりあえずメインのViewControllerだけ新規作成します。Super Classは何でも構いません。一番簡単なUIViewControllerのサブクラスをひな形だけ作ります。
ファイルを作成したら、拡張子を”.mm”に変更します。こうする事でxcode標準(?)のObjective-CとC++を混在させる事が出来ます。
ちなみにiOS版のOpenCVはC++とで出来ています。

ロジックは何も書いていませんが、この状態でビルドが出来る事になります。
試しにビルドしてみると #include <ext/atomicity.h>  が見つからないとエラーが出ると思います。

不思議な事にエミュレータでビルドすると大丈夫なのですが、実機でビルドをするとエラーが出てきます。
正直な所、ここでかなりハマりました。
ext/atomicity.h なるヘッダファイルはxcodeのディレクトリの下に実際に存在します。またこのエラーはプリコンパイルヘッダを clung がC++用にコンパイルする時に出て来ます。

たどり着いたのはコンパイラの設定です。

問題があるのは “C++ Language Dialect” と “C++ Standard Library” のようです。

下記の様に設定し直します。

この状態でコンパイルは出来る様になったはずです。
しかしリンクに失敗する場合があります。「場合があると」というのは実機にiPhone 5を使用したときです。iPhone 5は新しい armv7s を搭載しています。xcode 4.5も armv7s 用のコードを出力します。しかし OpenCV がまだ armv7s に対応していないようで、Python のスクリプトでビルドしたライブラリには armv7s 用のコードが含まれていないようです。そのため実機用のコードも armv7 用のコードで統一しなければいけないようです。

これも設定で回避できます。

 

“Valid Architectures” からarmv7s を削除し、Build Archive Architecture Only を “NO” にします。

以上です。

iOS 5.xのデバイスはいつまで続くか?

現時点ではまだ始まっていないようですが、本日中にiOSのアップデートが始まります。iOS5.xがインストールされている対応デバイスならば自動的に(?)OTAでアップデートが知らされるはず。だとすると多くの人(iPhone3G, iPhone4, iPhone4S, iPad2 , iPad(3rd gen), iPod Touch 4)はあまり遠くない時期にはiOS6に移行してくれそうだ。

iOS5.xのままで残っているのは iPhone 3G, iPad (1st gen), iPod touch (3rd gen)という事になる。もっと古い機種はiOS4.xのままという事になる。かなり古い機種で、現役で使っている人はどれくらいいるのだろうか?

 

アプリのiOS 6対応

他の開発者の方々も同じでしょうが、先週iOS6に対応したxcode 4.5(GM)がリリースされてその対応に大わらわ(?)ではないかと思います。

ただ、このxcodeを使ってしまうとiPhone 5にも完全対応しなくてはいけないようで少々面倒ですね。何が面倒って画面のレイアウトです。それまでのxcodeでとりあえずのiOS6対応をしている分には長くなった縦の両端が黒くなるだけでしたが(Portlraitの場合)、GM版でビルドすると今までの画角と両方に対応しなければいけません。

また今までのxcodeを使っていればiOSのAPIの互換性もあまり気にする必要はありませんでしたが、GM版を使うとそれもそうもいかないようです。これで噂されているiPad miniなんて出たら面倒だなぁと思ったりしています。iPhone 5の場合には UIUserInterfaceIdiom  = UIUserInterfaceIdiomPhone の場合だけで、画面が大きくなる分には表示項目を削る必要はありませんでした。しかしもしiPad miniUIUserInterfaceIdiomUIUserInterfaceIdiomPadだったりするとかなり面倒になる気がします。

 

リリースしているアプリについては既にiOS 6に対応しています。

 

備忘録:NSLayoutConstraint を無効にする

遅めの夏休みをとっているうちにiOS6やiPhone5のリリースが発表になりました。旅行の前から予想されていたのですが、意外とリリース日が早い事に驚いています。
前々から気になっていたのがiOS6対応のxcodeではInterface BuilderでUIViewに何かを追加すると、必ずNSLayoutConstraintが埋め込まれ、iOS5.0などのエミュレータで実行するとExceptionが発生してしまう事でした。

2012-09-16 07:13:14.395 iOS6Test05[2178:c07] *** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named NSLayoutConstraint'
*** First throw call stack:
(0x176c052 0x116cd0a 0x1714a78 0x17149e9 0x3307d7 0x3309af 0x3306b7 0x23136d 0xd8e2c 0xd93a9 0xd95cb 0x39a73 0x39ce2 0x39ea8 0x40d9a 0x289b 0x119d6 0x128a6 0x21743 0x221f8 0x15aa9 0x1656fa9 0x17401c5 0x16a5022 0x16a390a 0x16a2db4 0x16a2ccb 0x122a7 0x13a9b 0x26f2 0x2625)
terminate called throwing an exception(lldb)

これを何とかしないと新たに作るプロジェクトで古いiOSに対応出来なくなってしまうと思ったのですが、やはり解決策がありました。忘れないうちに備忘録として残しておきます。

File InspectorでStory Boardを開き、”Interface Builder Document”セクションの”Use Autolayout”をオフにすれば終わりです。

 

さてiOS6βGM用のxcodeβGMもリリースされて、4inch iPhoneのシミュレータも付いて来ました。正式に新しい画角のiOSデバイスが出るわけですが、WWDCのセッションやxcodeのβシードを見ているとNSLayoutConstraint なるものが出て来ていましたので十分予想は出来たわけです。

で、xcodeのβで気になっていたのモノの一つがこのNSLayoutConstraint。これによって今後も新しい画角のiOSデバイスが出て来ても、あるていど柔軟にアプリが対応出来るようになったわけですね。

 

CLGeocoderで正ジオコーディング

iOS 5.0がリリースされてからかなり経ちますが、いつの間にかiOSでも正ジオコーディングがサポートされていたんですね。気付きませんでした。

逆ジオコーディングも同じCLGeocoderで簡単に行う事が出来ます。

 

CLGeocoder *geocoder;
    geocoder = [CLGeocoder alloc]; 
    geocoder = [geocoder init];
    [geocoder geocodeAddressString:text completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error) {
            NSLog(@"Geocode failed with error: %@", error); return;
        }
        CLPlacemark* placemark; 
        for(placemark in placemarks) {
            NSLog(@"name : %@", placemark.name); 
            NSLog(@"ocean : %@", placemark.ocean); 
            NSLog(@"postalCode : %@", placemark.postalCode); 
            NSLog(@"subAdministrativeArea : %@", placemark.subAdministrativeArea); 
            NSLog(@"subLocality : %@", placemark.subLocality); 
            NSLog(@"subThoroughfare : %@", placemark.subThoroughfare); 
            NSLog(@"thoroughfare : %@", placemark.thoroughfare); 
            NSLog(@"administrativeArea : %@", placemark.administrativeArea); 
            NSLog(@"inlandWater : %@", placemark.inlandWater); 
            NSLog(@"ISOcountryCode : %@", placemark.ISOcountryCode); 
            NSLog(@"locality : %@", placemark.locality); 
            NSLog(@"addressDictionary CountryCode : %@", [placemark.addressDictionary objectForKey:@"CountryCode"]); 
            NSLog(@"addressDictionary Country : %@", [placemark.addressDictionary objectForKey:@"Country"]); 
            NSLog(@"addressDictionary ZIP : %@", [placemark.addressDictionary objectForKey:@"ZIP"]); 
            NSLog(@"addressDictionary State : %@", [placemark.addressDictionary objectForKey:@"State"]); 
            NSLog(@"addressDictionary SubLocality : %@", [placemark.addressDictionary objectForKey:@"SubLocality"]); 

            NSString* name; 
            name = ABCreateStringWithAddressDictionary(placemark.addressDictionary, YES); 
            NSLog(@"%@", name); 
        } 
    }];

 

使い方は簡単。上記のgeocodeAddressStringに地名や住所を渡して挙げるだけです。

結果はplacemarksCLPlacemarkのアレイとして返って来ます。

アレイになって返ってくるのは、例えば地名として「新宿駅」を検索すると複数の住所が返ってくるからです。

CLPlacemarkのリファレンスにも あるように、このクラスは様々な住所に関するメンバーを持っています。

しかし正ジオコーディングにおいては殆ど使い物になりません。

値がセットされていたり、されていなかったり。

多分、これをまた逆ジオコーディングしてやると色々セットされてくるのじゃないかと思いますが、それは試していません。

使えるかな?と思ったのはaddressDictionaryです。

 

 NSDictionary *addressDictionary

 

これをABCreateStringWithAddressDictionary()に渡してあげれば住所として読めるようなNSStringに変換してくれます。

 

    NSString* name; name = ABCreateStringWithAddressDictionary(placemark.addressDictionary, YES); NSLog(@"%@", name);

 

 

 

 

Android 4.0を使ってみる

妻がauのhtc Jを購入した事で少し触ってみました。

この機種を選んだのは大きく2つの理由がありました。

  1. おさいふケイタイ機能がある。
  2. ディザリング機能がある。

これらを中心に評価してみます。

 

1. おさいふ携帯機能

外で働いていて、客先等への移動が発生する妻にとって「おさいふ携帯」は必須です。

いかんせん、iPhoneは対応していません。昨年のiPhone4Sが出たときも、実は妻用のiPhone4Sも予約していたんです。しかしSuicaが使えない事を知ると、とたんに拒絶。キャンセルすることになってしまいました。

 

その後もiPhoneでのサポートは噂レベルですし、iPhone5がいつ出るのかも分からない状態でしたのでGW頃からAndroidの購入を考えていました。いくつかのAndroid携帯ではサポートしている機種もありましたが、逆に次ぎに挙げているディザリングに対応していなかったり、両方サポートしていてもデザインがイマイチだったりと今回のhtc Jまで待つ事になってしまいました。

 

さてhtc Jのおさいふ携帯ですが、すでにネット上の色々な所にも書かれていますが、最初のハードルは少々高かったです。今までのガラケーから電話帳等を移行し、あらかた設定が終わった後におさいふ携帯の設定をしようとすると、ダメなのです。

ダメというのは

 

 

 

 

 

 

 

2. ディザリング機能

 

 

3G回線からパケットを逃がしたい携帯キャリア

ドコモが昨年末にトラブルを起こした事で顕在化した3G回線を始めとする携帯の回線の飽和状態はどこのキャリアでも否めない問題だと思います。

私が携帯(iPhone)で使っているauの回線もやはり同じです。携帯電話各社はそれぞれにWi-Fiスポットを設けて極力通話以外のパケット通信を他へ逃がしたいようです。

あまりTVを真面目に見ていない私は「巨人の星」の星飛雄馬を起用したCMも「へ〜」という程度で流してみていました。ふと気付くと我が家のインターネット接続や固定電話で使用しているJCOMとの併用で毎月基本料金が1480円も割引になると!

勇んで近くのau shopに申し込みに行って来ました。月額基本料金が割安になるだけではなく、自宅固定電話とau携帯の通話が無料になってしまうという事を聞き、またお得感。

iPhone 4Sのリリースとともにナンバーポータビリティーでキャリアも変えた時には、au光の回線ならば通話料が無料になると聞いていたのですが、いつのまにか(?)JCOMもauの傘下に入っていたのか、同様に無料になっていました。

2月頃でしょうかauから案内書が来て、今なら無線LANルータがタダでレンタル出来ると…

auのHPでも紹介している「HOT SPOT Cube 無料レンタルキャンペーン」です。

その時はあまり興味を引きませんでした。既に家では無線LANルータは導入していましたから。

しかし前述のJCOMと併用時の割引キャンペーンのためにau shopを訪れた際に紹介された「auスマートバリュー(ルータ割引)」のキャンペーンです。au傘下のUQ Wi-Maxが提供するWi-Fi Walker Data08Wが利用の無い月は基本料金0円で使えるというサービス。元々外出の機会が少ない私ですが、「いざ!」という時には使いたいと思うときもあります。おまけにパケットの制限も無く最大で4410円です。

良い話だけではありません。もちろんauの主回線やJCOMの回線を含めた2年縛りはあります。その部分ではちょっと考えてしまいました。

しかしこのData08Wの別売ドックを買うと、通常時は802.11nまで使える家庭用Wi-Fiルータとしても使える事が分かりました。もちろん家庭内で使っている場合には家に引き込んでいるLAN回線(私の場合にはJCOMのInternet回線)を使用するのでWiMaxの接続料金はかかりません。

 

別にauの宣伝をしている訳ではありません。

しかし携帯各社、程度の差はあれどこも回線は逼迫しているようです。

出来れば3G回線(一部ではLTEや4G)から別の回線(Wi-Fi等)にパケットを逃がしたい事情があるようです。

 

auと幾つかの固定電話の回線と併用した場合の月額基本料金割引の話は出ているのですが、残念な事にUQ Wi-Maxの端末が割引になっているという話は全面には出て来ていません(auのHPでも何故か奥まった所にしかありません)。
そろそろiPhone 5の噂も出ている昨今。あまりキャリアに縛られたくない私ですが、なんとなく割安感で申し込んでしまいました。

ちなみに 「HOT SPOT Cube 無料レンタルキャンペーン」も申し込んでしまいました。

おかげで我が家の無線LAN環境はちょっと変な形になっていますが… (^^;

 

Significant-Change Location Service

位置情報をトラッキングする必要のあるアプリを考えていて、CLLocationManagerについて調査しています。

Appleのドキュメントにも書かれている様に通常のstartUpdatingLocationによる維持情報の取得はバッテリーの消費がかなり激しいようで、長時間の使用には向いていません。

またアプリがバックグラウンドに入り、メモリー使用量などの関係で強制終了させられた場合にはユーザが常に意識していなければならない問題があります。

 

その点、Significant-Change Location Serviceを利用すると、バッテリーの消費が抑えられる事と、アプリがいつの間にか終了させられていても位置情報の更新があるとiOSが自動的にアプリを起動してくれるという利点があります。

 

ただ、位置情報を更新してくれるタイミングや精度には当然劣化があります。

またテストの段階で、位置情報の更新があった場合に、確実にアプリを再起動してくれるのか?そのテストをどうするか悩ましい所です。

 

一番面倒なのは、机上でテストが出来ない事。

実際に実機を持って外を歩き回らないと検証が出来ず、またその際にMacを一緒に持ち歩くわけにも行かず、xcodeでモニターしながらというわけに行かないのため通常のアプリに比べて開発効率が落ちてしまいます。

 

Road to OpenGL ES (6)

Cheetah3D再び

次はBlenderの話を書こうと思っていたのですが、再びCheetah3Dに戻って来ました。Cheetah3Dに面白い機能を見つけたからです。

Blenderと同様にCheetah3Dも様々なフォーマットでデータをExportする事が出来るのですが、その中の”.h”へのExportが気になったからです。

試しにExportを実行して見ると、下記のようなヘッダファイルが出力されます。3Dモデルにもよるのですが、かなり巨大なヘッダファイルです。

嬉しいのが、その使い方まで書いてあります。

まずは構成ですがまず、NAME_vertex,NAME_indexの2つの2次元配列。

そしてNAME_vertexcountとNAME_polygoncountがそれぞれの配列の個数。

NAMEの部分はそれぞれメッシュのの名前が自動的に割り当てられます。

 

 

おまけにどのようにしてこの配列を使って描画すれば良いかまで書いてあります。

 

// You can draw the mesh the following way:
//      glEnableClientState(GL_INDEX_ARRAY);
//      glEnableClientState(GL_NORMAL_ARRAY);
//      glEnableClientState(GL_VERTEX_ARRAY);
//      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//      glInterleavedArrays(GL_T2F_N3F_V3F,0,NAME_vertex);
//      glDrawElements(GL_TRIANGLES,NAME_polygoncount*3,GL_UNSIGNED_INT,NAME_index);

 

しかしこれが引っかけ(?)で、このままではiOS上で実行出来ません。
ビルドで弾かれてしまいます。実装されていないAPIがあるからです。
多分、MacOS X のOpenGLなら大丈夫なんでしょうね。
Cheetah3DのサポートHPにもあるように、
http://cheetah3d.de/forum/showthread.php?t=4617
上記APIの代わりに下記のAPIを呼んであげれば無事に描画する事が出来ます。
glVertexPointer(3, GL_FLOAT, sizeof(vertexStruct), &NAME_vertex[0][5]);
glTexCoordPointer(2, GL_FLOAT, sizeof(vertexStruct), &NAME_vertex[0][0]);
glNormalPointer(GL_FLOAT, sizeof(vertexStruct), &NAME_vertex[0][2]);
glDrawElements(GL_TRIANGLES,NAME_polygoncount*3,GL _UNSIGNED_SHORT,NAME_index);

 

 

Road to OpenGL ES (5)

Cheetah3D

Unityにはまだ未練があります。なぜならこの時点でまだ他にソリューションが見つかっていないからです。

その意味で、3Dレンダリングソフトを試してみて相性が良ければ…という気持ちがありました。前回ご紹介したUnityと連携出来る3Dレンダリングソフトですが、やはりAutodesk関連のソフトは高価すぎます。ですので迷い無くCheetah3DとBlenderに絞りました。

まずはCheetah3D。

AppStoreからも購入可能です。

僕は簡単なんでAppStoreから購入してしまいました。購入してしまうと値段が出ないのでカードの請求書を見るしかありませんが、だいたい8千円台だったと思います。

autodeskのソフトから比べると天と地です。(余談ですが、autodeskの日本法人の社長はまだApple Japan出身の志賀さんなのでしょうか?)

日本語化されていますので、メニュー等も全て日本語です。一部を除いてオンラインヘルプも日本語になっています。

Macのソフトらしく、マウス操作で基本的なメッシュからそれを変形しながら様々なオブジェクトを作って行く事も簡単に出来ます。アニメーションやパーティクルにも対応していて成果物をムービーに落とす事も出来るようです。

本格的なプロにとっては物足りないのかもしれませんが、僕にとっては機能豊富なソフトです。

もともとレンダリングソフト上でアニメーションをするつもりがありませんでしたので(これはUnityでも後でご紹介するフレームワークでも極めて重要なのですが)、これで十分でした。

 

しかし…

マイナーなのです。

ググっても、今やりたい事を助けてくれるようなサイトが極めて少ないのでした。

レンダリングソフト初心者の僕にとっては、この部分がかなりハードルが高いものになって来ました。

 

移り気な僕は、8千円の出費は痛いもののフリーソフトのBlenderへと簡単に行く事になりました。

 

時系列で言えばCheetah3DとBlenderは、かなり平行してevaluateしていました。その中で引っかかったのが、両方とも「.fbx」というファイル形式でエクスポート出来ると言う事です。

それはまた別の項でご紹介します。

 

 

追記。

そしてまたCheetah3Dに戻ってくるのですが…