Archive for the OpenCV Category

opencv-2.4.6 on iOS 7.0.3 (64 bit)

iOS7と同時にリリースされたiPhone5sは64bitのCPUを搭載しています。
今までのアプリもそのままで動作し、高速ではあるのですが、やはり64bitのネイティブアプリを試してみたくなります。
一つのプロジェクトで構成されていれば簡単に出来てしまいますが、外部のフレームワークやライブラリなどを使っている場合にはそれらが64bit対応していなければなりません。

そこでまずOpenCVの64bit対応を試してみました。

定量的な測定はまだしていませんが、iPhone5sでは32bit版アプリでもかなり高速ですが、64bitアプリにすると更に高速になっている感じがあります。
つい先日発表されたiPad airやRetina版のiPad miniも64bit CPUを登載しているようですので、今後は64 bitアプリも多く出てくるのではないかと思います。

 

●環境

xcode 5.0.1
Darwin Kernel Version 13.0.0 (Mervericks)

platforms/ios/build_framework.py

def build_framework(srcroot, dstroot):
    "main function to do all the work"

    targets = ["iPhoneOS", "iPhoneOS", "iPhoneSimulator"]
    archs = ["armv7", "armv7s", "i386"]
    for i in range(len(targets)):
        build_opencv(srcroot, os.path.join(dstroot, "build"), targets[i], archs[i])
    put_framework_together(srcroot, dstroot)

112,113行目に以下のように編集し、ターゲットとアーキティクチャを追加する。

    targets = ["iPhoneOS", "iPhoneOS", "iPhoneOS", "iPhoneSimulator",  "iPhoneSimulator"]
    archs = ["arm64", "armv7", "armv7s", "i386", "x86_64"]

platforms/ios/cmake/Modules/Platform/iOS.cmake

# Hidden visibilty is required for cxx on iOS
set (CMAKE_C_FLAGS "")
set (CMAKE_CXX_FLAGS "-stdlib=libc++ -headerpad_max_install_names -fvisibility=hidden -fvisibility-inlines-hidden")

set (CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -fomit-frame-pointer -ffast-math")

if (HAVE_FLAG_SEARCH_PATHS_FIRST)
    set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
    set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
endif (HAVE_FLAG_SEARCH_PATHS_FIRST)

45行目を以下のように編集し、最適化オプションを変更する。

    set (CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -Os -fomit-frame-pointer -ffast-math")

modules/legacy/src/dpstereo.cpp

#define CV_IMAX3(a,b,c) ((temp3 = (a) >= (b) ? (a) : (b)),(temp3 >= (c) ? temp3 : (c)))
#define CV_IMIN3(a,b,c) ((temp3 = (a) <= (b) ? (a) : (b)),(temp3 <= (c) ? temp3 : (c)))

このままではマクロでエラーになるため下記のように修正する。

 
#define CV_IMAX3(a,b,c) (temp3 = (a >= b ? (a >= c ? a : (b >= c ? b : c)) : (b >= c ? b : c)))
#define CV_IMIN3(a,b,c) (temp3 = (a <= b ? (a <= c ? a : (b <= c ? b : c)) : (b <= c ? b : c)))

最後に以下のコマンドでフレームワークを作成します。

python ../opencv/platforms/ios/build_framework.py ios

Build OpenCV for armv7s

現在のOpenCVは正式な環境では armv7s 対応のライブラリを作ってくれません。
そのため、アプリをビルドする場合にはプロジェクトから armv7s を外さなければなりません。
これからアプリを出そうという際には最新のアーキティクチャを使えないのはとうも納得が行きません。
そこでいろいろ調べてみました。
私はcmakeに関しては全くの素人で、これから知識を深めたいというわけでもありませんので、「とりあえずビルドできる」を目標にしています。

結論から言うと
opencv/ios/cmake/Toolchains/Toolchain-iPhoneOS_Xcode.cmake を編集してやります。

essage (STATUS “Setting up iPhoneOS toolchain”)
set (IPHONEOS TRUE)

# Standard settings
set (CMAKE_SYSTEM_NAME iOS)
# Include extra modules for the iOS platform files
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} “${CMAKE_CURRENT_SOURCE_DIR}/ios/cmake/Modules”)

# Force the compilers to gcc for iOS
include (CMakeForceCompiler)
CMAKE_FORCE_C_COMPILER (gcc gcc)
CMAKE_FORCE_CXX_COMPILER (g++ g++)

set (CMAKE_C_SIZEOF_DATA_PTR 4)
set (CMAKE_C_HAS_ISYSROOT 1)
set (CMAKE_C_COMPILER_ABI ELF)
set (CMAKE_CXX_SIZEOF_DATA_PTR 4)
set (CMAKE_CXX_HAS_ISYSROOT 1)
set (CMAKE_CXX_COMPILER_ABI ELF)

SET (CMAKE_OSX_ARCHITECTURES “armv7” “armv7s”)

# Skip the platform compiler checks for cross compiling
set (CMAKE_CXX_COMPILER_WORKS TRUE)
set (CMAKE_C_COMPILER_WORKS TRUE)

赤で色分けされた行を追加してやるだけです。
とりあえずテストプロジェクトでは iPhone 5用にビルドしても問題なく armv7s でコンパイルされており、リンカーでもエラーは出ません。

 

ただもう一つ問題が…

結論から言うと、armv7でもarmv7sでもパフォーマンスはあまり変わりませんでした(処理にも依存すると思うのですが)。

で、OpenCVをビルドした時のログを見てみると全くオプティマイズされていないようなのです。

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xct oolchain/usr/bin/clang -x c -arch armv7s -fmessage-length=0 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototy pes -Wno-return-type -Wformat -Wno-missing-braces -Wparentheses -Wswitch – Wno-unused-function

 

これは多分armv7でビルドした際も同じだと思います。OpenCVのソース内までデバッガーで追って行くつもりは無いのでやはり “-Os” でコンパイルしたいです。
またOpenCVのcmakeと格闘です。
今回の事で少しだけcmakeも理解(?)出来た気もしますので時間のある時に試してみます。

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” にします。

以上です。