OSX El Capitan 上で OpenCV2 + Perl Cv をインストールする手順

超絶久しぶりのインストール・ノウハウ関連のエントリです。最近 perl はほぼ全くと言っていいほど触っていなくて、excel や word や powerpoint や Java を触る日々が相変わらず続いています。IDE がないともはや生きていけない体になりつつあります。

さて、ブログ読者の方から Perl から OpenCV2 を扱いたいという質問を受けました。休日を利用して OSX 上でちょっと試しているのですが、これが予想以上に面で苦労しました。
ちなみに、苦労したうちの半分は僕の OSX 環境に依存する問題で、Macports, Fink, Homebrew と3つものパッケージ管理ツールが同居していて、インストールされているライブラリ関連が超面倒なことになっていたため、HomeBrew に一本化するところから始まったのがあります。その件に関しては別エントリにてまとめます。

やっと HomeBrew に一本化されたところで、OpenCV2 をインストールが完了したものの、そもそもデフォルトでは Perl バインディングが存在しません。今回は物体認識をしたいわけではないため Image::ObjectDetect では不十分です。いろいろ記憶を思い返してみたら Cv ってのを思い出したので、cpanm ですんなり入るとおもいきや、入らなかったので備忘録メモとして残しておきます。

img003.jpg

- スポンサーリンク -

OSX El Capitan 上で OpenCV2 + Perl Cv をインストールする方法

python をインストールする

$ brew tap homebrew/science
$ brew install python
$ pip install numpy

OpenCV2 をインストールする

$ brew install cmake automake faac fdk-aac git lame libass libtool libvorbis libvpx libvo-aacenc opencore-amr openjpeg opus sdl schroedinger shtool speex texi2html theora wget x264 xvid yasm
$ brew install ffmpeg --with-fdk-aac --with-libvo-aacenc --with-libvorbis --with-libvpx --with-openjpeg --with-theora --with-opencore-amr
$ brew install eigen
$ brew install jasper
$ brew install tbb
$ brew install qt
$ brew install opencv --with-eigen --with-jasper --with-libtiff --with-qt --with-tbb --with-ffmpeg

cpanm で Cv をインストールする

Cv に必要な依存関係にあるモジュール類を cpanm を使ってインストールする。cpanm is 何?という方は、perldoc.jp の cpanm 項を見ると良いでしょう。

$ cpanm Cv

上記は残念ながら必ず失敗します。.cpanm の work ディレクトリへ移動し、最新の work ディレクトリへ移動します。この例では 1458222649.37317 と仮定します。

$ cd ~/.cpanm/work/
$ cd 1458222649.37317
$ ls -la

ディレクトリ構成を確認します。Cv モジュールのソースは Cv-0.29 配下となります。

$ ls -la
total 7952
drwxr-xr-x   7 root  staff      238  3 17 22:50 .
drwxr-xr-x  17 drk   staff      578  3 19 13:45 ..
drwxr-xr-x  38 1006  513       1292  3 19 12:45 Cv-0.29
-rw-r--r--   1 root  staff  4053837  6  2  2013 Cv-0.29.tar.gz
drwxr-xr-x  18 1000  staff      612  3 17 22:50 ExtUtils-PkgConfig-1.15
-rw-r--r--   1 root  staff     9877  9 30  2013 ExtUtils-PkgConfig-1.15.tar.gz
-rw-r--r--   1 root  staff     2443  3 17 22:50 build.log

Cv-0.29 ディレクトリへ移動して手動ビルドしてエラーの原因を特定します。

$ perl Makefile.PL 
Can't link/include C library 'opencv_core', aborting.

README に従って pkg-config を使って opencv のライブラリパスなどを取得します。間違いなく opencv2 がインストールできていることは確認できました。
LIBPATH が /usr/local/Cellar/opencv/2.4.12_2/lib
LICPATH が /usr/local/Cellar/opencv/2.4.12_2/include/opencv であることが確認でしました。

$ pkg-config opencv --libs
-L/usr/local/Cellar/opencv/2.4.12_2/lib -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_nonfree -lopencv_objdetect -lopencv_ocl -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab -llibtbb.dylib

$ pkg-config opencv --cflags
-I/usr/local/Cellar/opencv/2.4.12_2/include/opencv -I/usr/local/Cellar/opencv/2.4.12_2/include

homebrew でインストールしたからか?LIBPATH, INCPATH が正常に引き継がれないため、Makefile.PL を下記の参考例のように直接修正します。赤文字の部分は上記コマンドで取得した値を入れます。

$ vi Makefile.PL

以下のように編集
#my $cv2 = check_lib(lib => 'opencv_core');      # OpenCV-2.x
my $cv2 = check_lib(libpath=>'/usr/local/Cellar/opencv/2.4.12_2/lib', incpath=>'/usr/local/Cellar/opencv/2.4.12_2/include/opencv', lib => 'opencv_core');

いよいよ make を行いますが、次は下記のようなエラーが発生します。

$ perl Makefile.PL
$ make

・・・中略・・・

cp lib/Cv/BGCodeBookModel.pm ../blib/lib/Cv/BGCodeBookModel.pm
/usr/bin/perl /System/Library/Perl/5.18/ExtUtils/xsubpp  -C++ -hiertype -typemap /System/Library/Perl/5.18/ExtUtils/typemap -typemap /private/tmp/Cv-0.29/lib/Cv/typemap  BGCodeBookModel.xs > BGCodeBookModel.xsc && mv BGCodeBookModel.xsc BGCodeBookModel.c
Please specify prototyping behavior for BGCodeBookModel.xs (see perlxs manual)
c++ -c  -I. -I.. -I/private/tmp/Cv-0.29/lib/Cv -I/usr/local/Cellar/opencv/2.4.12_2/include/ -I/usr/local/Cellar//2.4.12_2/include -Os   -DVERSION=\"0.29\" -DXS_VERSION=\"0.29\"  "-I/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE"   BGCodeBookModel.c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
In file included from BGCodeBookModel.xs:3:
In file included from /private/tmp/Cv-0.29/lib/Cv/Cv.inc:27:
In file included from /usr/local/Cellar/opencv/2.4.12_2/include/opencv/cv.h:64:
/usr/local/Cellar/opencv/2.4.12_2/include/opencv2/core/core.hpp:2086:15: error: too many arguments provided to function-like macro invocation
    void seed(unsigned s);
              ^
/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/embed.h:538:9: note: macro 'seed' defined here
#define seed()                  Perl_seed(aTHX)
        ^
In file included from BGCodeBookModel.xs:3:
In file included from /private/tmp/Cv-0.29/lib/Cv/Cv.inc:27:
In file included from /usr/local/Cellar/opencv/2.4.12_2/include/opencv/cv.h:64:
/usr/local/Cellar/opencv/2.4.12_2/include/opencv2/core/core.hpp:2086:10: error: field has incomplete type 'void'
    void seed(unsigned s);
         ^
BGCodeBookModel.c:669:1: warning: duplicate 'extern' declaration specifier [-Wduplicate-decl-specifier]
XS_EXTERNAL(boot_Cv__BGCodeBookModel); /* prototype to pass -Wmissing-prototypes */
^
/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/XSUB.h:145:33: note: expanded from macro 'XS_EXTERNAL'
#      define XS_EXTERNAL(name) extern "C" XSPROTO(name)
                                ^
1 warning and 2 errors generated.
make[1]: *** [BGCodeBookModel.o] Error 1
make: *** [subdirs] Error 2

/usr/local/Cellar/opencv/2.4.12_2/include/opencv2/core/core.hpp 内に定義されている void seed(unsigned s) と /System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/embed.h 内に定義されている #define seed() が競合していてコンパイルができないというエラーが発生しています。WARNING はこの際無視します。仕方がないので、/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/embed.h 側の seed() は opencv2 側からは全く参照されていない定義なので、下記のようにして一時ファイルに対して変更を加えて無視させます。

$ cp /System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/embed.h embed.h 
$ vi embed.h

下記のように #define seed() をコメントする
#define screaminstr(a,b,c,d,e,f)        Perl_screaminstr(aTHX_ a,b,c,d,e,f)
//#define seed()                        Perl_seed(aTHX)
#define set_context             Perl_set_context


$ vi Makefile

下記のように $(PERL_INC)/ をコメントする

        $(PERL_INC)/dosish.h            \
#        $(PERL_INC)/embed.h            \
        $(PERL_INC)/embedvar.h            \

これでやっと正常に make が通る通るようになりました。テストケースの中で inlineC を使ってるものがありますが、そちらの中身までは修正していないので同上のエラーが発生しますが、これは無視してもよいものです。(もちろん同じような手順を踏めばこのエラーも消せます。)

$ make
$ make test

PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/1config.t ................... 1/? # cxx: 
t/1config.t ................... ok    
t/1const-old.t ................ 1/? Undefined subroutine &main::CV_CAP_PROP_WHITE_BALANCE_BLUE_U called at t/1const-old.t line 456.


#   Failed test 'CV_CAP_PROP_WHITE_BALANCE_BLUE_U'
#   at t/1const-old.t line 458.
Undefined subroutine &main::CV_CAP_PROP_WHITE_BALANCE_RED_V called at t/1const-old.t line 456.


#   Failed test 'CV_CAP_PROP_WHITE_BALANCE_RED_V'
#   at t/1const-old.t line 458.
# Looks like you failed 2 tests of 418.
t/1const-old.t ................ Dubious, test returned 2 (wstat 512, 0x200)
Failed 2/418 subtests 
t/1const.t .................... ok     
t/1CvBox2D.t .................. ok   
t/1CvConnectedComp.t .......... ok     
t/1CvPoint.t .................. ok   
t/1CvPoint2D32f.t ............. ok   
t/1CvPoint2D32fPtr.t .......... ok     
t/1CvPoint2D64f.t ............. ok   
t/1CvPoint2D64fPtr.t .......... ok     
t/1CvPoint3D32f.t ............. ok   
t/1CvPoint3D32fPtr.t .......... ok     
t/1CvPoint3D64f.t ............. ok   
t/1CvPoint3D64fPtr.t .......... ok     
t/1CvPointPtr.t ............... ok     
t/1CvRect.t ................... ok     
t/1CvScalar.t ................. ok     
t/1CvSize.t ................... ok   
t/1CvSize2D32f.t .............. ok   
t/1CvTermCriteria.t ........... ok     
t/1doublePtr.t ................ ok   
t/1floatPtr.t ................. ok   
t/1intPtr.t ................... ok   
t/1more-test.t ................ ok   
t/1sizeof.t ................... ok   
t/1version.t .................. 1/? 
#   Failed test 'use Cv::Qt;'
#   at t/1version.t line 8.
#     Tried to use 'Cv::Qt'.
#     Error:  Can't locate Cv/Qt.pm in @INC (you may need to install the Cv::Qt module) (@INC contains: /Users/drk/.cpanm/work/1458222649.37317/Cv-0.29/blib/lib /Users/drk/.cpanm/work/1458222649.37317/Cv-0.29/blib/arch /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2/darwin-thread-multi-2level /Library/Perl/Updates/5.18.2 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at t/1version.t line 8.
# BEGIN failed--compilation aborted at t/1version.t line 8.
# Looks like you failed 1 test of 23.
t/1version.t .................. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/23 subtests 
t/2absDiff.t .................. ok     
t/2add.t ...................... ok     
t/2addWeighted.t .............. 2/3 init done 
t/2addWeighted.t .............. ok   
t/2alias.t .................... ok     
t/2and.t ...................... ok     
t/2autoload.t ................. ok     
t/2boxPoints.t ................ ok   
t/2cmp.t ...................... ok   
t/2copy.t ..................... ok   
t/2corner.t ................... 1/12 init done 
t/2corner.t ................... ok     
t/2croak.t .................... ok   
t/2crossProduct.t ............. ok   
t/2CvArr.t .................... ok       
t/2CvFileStorage.t ............ 2/25 init done 
t/2CvFileStorage.t ............ ok     
t/2CvImage.t .................. ok     
t/2CvMat-CvImage.t ............ ok   
t/2CvMat.t .................... ok       
t/2CvMatND.t .................. ok       
t/2CvRNG.t .................... 2/11 init done 
t/2CvRNG.t .................... ok     
t/2CvSeq.t .................... ok     
t/2CvSparseMat.t .............. ok     
t/2CvSTORAGE.t ................ ok   
t/2CvString.t ................. ok     
t/2cvtColor.t ................. 2/31 init done 
t/2cvtColor.t ................. ok     
t/2cvtScale.t ................. ok   
t/2cvtScaleAbs.t .............. ok     
t/2cvtSeqToArray.t ............ ok     
t/2dct.t ...................... 1/3 init done 
t/2dct.t ...................... ok   
t/2det.t ...................... ok   
t/2dft.t ...................... 1/3 init done 
t/2dft.t ...................... ok   
t/2div.t ...................... ok   
t/2dst.t ...................... ok       
t/2encode.t ................... 2/236 init done 
t/2encode.t ................... ok       
t/2error.t .................... ok     
t/2exp.t ...................... ok   
t/2flip.t ..................... ok     
t/2font.t ..................... 2/3 init done 
t/2font.t ..................... ok   
t/2gemm.t ..................... ok     
t/2getAffineTransform.t ....... 1/10 init done 
t/2getAffineTransform.t ....... ok     
t/2getCols.t .................. ok     
t/2getDims.t .................. ok     
t/2getPerspectiveTransform.t .. 1/10 init done 
t/2getPerspectiveTransform.t .. ok     
t/2getRawData.t ............... ok    
t/2getReal.t .................. ok     
t/2getRotationMatrix2D.t ...... ok     
t/2getRows.t .................. ok     
t/2getSize.t .................. ok     
t/2getSubRect.t ............... 2/7 init done 
t/2getSubRect.t ............... ok   
t/2getTextSize.t .............. 2/20 init done 
t/2getTextSize.t .............. ok     
t/2histogram.t ................ 14/31 init done 
t/2histogram.t ................ ok     
t/2initSystem.t ............... 1/2 init done 
t/2initSystem.t ............... ok   
t/2inRange.t .................. 1/13 init done 
t/2inRange.t .................. ok     
t/2inv.t ...................... ok   
t/2loadImage.t ................ 2/13 init done 
t/2loadImage.t ................ ok     
t/2log.t ...................... ok   
t/2lut.t ...................... 1/6 init done 
t/2lut.t ...................... ok   
t/2matchTemplate.t ............ ok   
t/2max.t ...................... ok     
t/2merge.t .................... ok       
t/2min.t ...................... ok     
t/2minMaxLoc.t ................ ok     
t/2misc.t ..................... ok     
t/2mixChannels.t .............. ok   
t/2morphologyEx.t ............. ok     
t/2mouse.t .................... 1/? init done 
t/2mouse.t .................... ok   
t/2mul.t ...................... ok   
t/2or.t ....................... ok     
t/2polyLine.t ................. 1/2 init done 
t/2polyLine.t ................. ok   
t/2pow.t ...................... ok   
t/2ptr.t ...................... ok     
t/2refcount.t ................. ok     
t/2resize.t ................... ok     
t/2saveImage.t ................ ok   
t/2scaleAdd.t ................. ok   
t/2setZero.t .................. 2/12 init done 
t/2setZero.t .................. ok     
t/2solve.t .................... ok   
t/2solveCubic.t ............... ok   
t/2split.t .................... ok     
t/2stereoSGBM.t ............... ok   
t/2sub.t ...................... ok     
t/2subRS.t .................... ok   
t/2sum.t ...................... ok   
t/2surf.t ..................... 2/13 init done 
t/2surf.t ..................... ok     
t/2threshold.t ................ 2/7 init done 
t/2threshold.t ................ ok   
t/2trackbar.t ................. 1/? init done 
t/2trackbar.t ................. ok   
t/2useCv-bgcode.t ............. ok   
t/2useCv-default.t ............ ok   
t/2useCv-nocv.t ............... ok   
t/2useCv-nohist.t ............. ok   
t/2useCv-qt.t ................. skipped: Cv::Qt required for testing
t/2useCv-subdiv.t ............. ok   
t/2xor.t ...................... ok     
t/4boundingRect.t ............. 1/2 init done 
t/4boundingRect.t ............. ok   
t/4contour.t .................. 1/5 init done 
t/4contour.t .................. ok   
t/4contourArea.t .............. 2/3 init done 
t/4contourArea.t .............. ok   
t/4CvMat-More.t ............... ok     
t/4CvMatND-More.t ............. ok     
t/4CvMore.t ................... ok   
t/4CvSeq-Circle.t ............. ok     
t/4CvSeq-Point.t .............. ok     
t/4CvSeq-Point2.t ............. 2/3 init done 
t/4CvSeq-Point2.t ............. ok   
t/4CvSeq-Rect.t ............... ok     
t/4CvSeq-SURFPoint.t .......... ok     
t/4CvVideoWriter.t ............ ok   
t/4fitEllipse.t ............... 2/16 init done 
t/4fitEllipse.t ............... ok     
t/4fitLine.t .................. ok     
t/4getBuildInformation.t ...... 1/4 # OpenCV modules: python, legacy, imgproc, gpu, core, nonfree, contrib, ocl, features2d, flann, ts, stitching, photo, superres, videostab, ml, highgui, objdetect, video, calib3d
t/4getBuildInformation.t ...... ok   
t/4houghCircle.t .............. 2/9 init done 
t/4houghCircle.t .............. ok   
t/4m_get.t .................... ok     
t/4makeSeqHeaderForArray.t .... ok     
t/4minAreaRect.t .............. 2/3 init done 
t/4minAreaRect.t .............. ok   
t/4minEnclosingCircle.t ....... 2/12 init done 
t/4minEnclosingCircle.t ....... ok     
t/4moments.t .................. 1/1 init done 
t/4moments.t .................. ok   
t/4namedParameters.t .......... ok    
t/4overload.t ................. ok     
t/4pointSeqFromMat.t .......... 2/5 init done 
t/4pointSeqFromMat.t .......... ok   
t/4projectPoints2.t ........... 1/1 init done 
t/4projectPoints2.t ........... ok   
t/4s_new.t .................... ok   
t/4toArray-seq.t .............. ok     
t/4toArray.t .................. ok     
t/4transform.t ................ 1/39 init done 
t/4transform.t ................ ok     
t/9flipbook.t ................. 1/? init done 
t/9flipbook.t ................. ok   
t/9inlineC.t .................. 1/6 /usr/bin/perl /System/Library/Perl/5.18/ExtUtils/xsubpp  -typemap "/System/Library/Perl/5.18/ExtUtils/typemap" -typemap "/Users/drk/.cpanm/work/1458222649.37317/Cv-0.29/blib/lib/Cv/typemap"   _9inlineC_t_f254.xs > _9inlineC_t_f254.xsc && mv _9inlineC_t_f254.xsc _9inlineC_t_f254.c
c++ -c  -I"/Users/drk/.cpanm/work/1458222649.37317/Cv-0.29/t" -I/Users/drk/.cpanm/work/1458222649.37317/Cv-0.29/blib/lib/Cv -I/usr/local/Cellar/opencv/2.4.12_2/include/ -I/usr/local/Cellar//2.4.12_2/include -Os   -DVERSION=\"0.00\" -DXS_VERSION=\"0.00\"  "-I/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE"   _9inlineC_t_f254.c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
In file included from _9inlineC_t_f254.xs:7:
In file included from /usr/local/Cellar/opencv/2.4.12_2/include/opencv/cv.h:64:
/usr/local/Cellar/opencv/2.4.12_2/include/opencv2/core/core.hpp:2086:15: error: too many arguments provided to function-like macro invocation
    void seed(unsigned s);
              ^
/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/embed.h:538:9: note: macro 'seed' defined here
#define seed()                  Perl_seed(aTHX)
        ^
In file included from _9inlineC_t_f254.xs:7:
In file included from /usr/local/Cellar/opencv/2.4.12_2/include/opencv/cv.h:64:
/usr/local/Cellar/opencv/2.4.12_2/include/opencv2/core/core.hpp:2086:10: error: field has incomplete type 'void'
    void seed(unsigned s);
         ^
_9inlineC_t_f254.c:193:1: warning: duplicate 'extern' declaration specifier [-Wduplicate-decl-specifier]
XS_EXTERNAL(boot__9inlineC_t_f254); /* prototype to pass -Wmissing-prototypes */
^
/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE/XSUB.h:145:33: note: expanded from macro 'XS_EXTERNAL'
#      define XS_EXTERNAL(name) extern "C" XSPROTO(name)
                                ^
1 warning and 2 errors generated.
make[1]: *** [_9inlineC_t_f254.o] Error 1

A problem was encountered while attempting to compile and install your Inline
C code. The command that failed was:
  make > out.make 2>&1

The build directory was:
/Users/drk/.cpanm/work/1458222649.37317/Cv-0.29/_Inline/build/_9inlineC_t_f254

To debug the problem, cd to the build directory, and inspect the output files.

 at t/9inlineC.t line 35.
	...propagated at /System/Library/Perl/Extras/5.18/Inline/C.pm line 772.
BEGIN failed--compilation aborted at t/9inlineC.t line 35.
# Looks like you planned 6 tests but ran 2.
# Looks like your test exited with 2 just after 2.
t/9inlineC.t .................. Dubious, test returned 2 (wstat 512, 0x200)
Failed 4/6 subtests 
t/9pod.t ...................... ok     
t/9ref.t ...................... 1/? # no t/ref-2.4.12.pm (make ref)
t/9ref.t ...................... ok   
t/9threads.t .................. 1/? libpng warning: Application built with libpng-1.5.4 but running with 1.6.21
Thread 1 terminated abnormally: Can't bless non-reference value at t/9threads.t line 33.
t/9threads.t .................. 2/? 
#   Failed test at t/9threads.t line 51.
# Looks like you failed 1 test of 2.
t/9threads.t .................. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/2 subtests 

Test Summary Report4 
-------------------
t/1const-old.t              (Wstat: 512 Tests: 418 Failed: 2)
  Failed tests:  417-418
  Non-zero exit status: 2
t/1version.t                (Wstat: 256 Tests: 23 Failed: 1)
  Failed test:  3
  Non-zero exit status: 1
t/9inlineC.t                (Wstat: 512 Tests: 2 Failed: 0)
  Non-zero exit status: 2
  Parse errors: Bad plan.  You planned 6 tests but ran 2.
t/9threads.t                (Wstat: 256 Tests: 2 Failed: 1)
  Failed test:  2
  Non-zero exit status: 1
Files=152, Tests=4972, 323 wallclock secs ( 1.01 usr  0.39 sys + 133.38 cusr 31.62 csys = 166.40 CPU)
Result: FAIL
Failed 4/152 test programs. 4/4972 subtests failed.
make: *** [test_dynamic] Error 1

inlineC 以外のテストケースもほぼ全て pass したので無事インストールして完了です。お疲れ様でした。

$ sudo make install
- スポンサーリンク -