MSYS2/MinGW64環境でのruby-opencv

OpenCVをRubyより使いたく色々探していると,「ruby-opencv」というGemがあることを発見しました.

ruby-opencv/ruby-opencv · GitHub
https://github.com/ruby-opencv/ruby-opencv

ここにも書かれている通り,Mac環境であれば,HomebrewかMacPortであらかじめOpenCVのバイナリパッケージをインストールしておいて,gemコマンドで直接インストールする場合は,仮にOpenCVのライブラリの場所が/opt/opencv/lib,インクルードファイルの場所が/opt/opencv/include だったとすると,

$ gem install ruby-opencv -- --with-opencv-dir=/opt/opencv

で,Bundlerでbundle installする場合は,

$ bundle config build.ruby-opencv --with-opencv-dir=/opt/opencv
$ bundle install

のようにすればすぐに利用可能です.MacやLinux(X Window)環境だと何の問題もありません.

Window環境であれば,Windows用のOpenCVのバイナリパッケージ(数百MBもある)を取ってきて,PATHを設定し,すでにVisual Studio(Visual C/C++)の環境があれば,gem install するだけで使える(らしい,試してないので分からないけど...)

では,Windows環境で,Visual Studio等がなくVCのコンパイラ(CL.EXE)が利用できない場合どうするか.

ということで,手前のMSYS2/MinGW64 の環境下でruby-opencvが利用できるかどうかTRYしてみました.

MSYS2/MinGW64のインストールについては,「MSYS2+VagrantによるWindowsでのUNIX環境」を参照ください.

まずは,MSYS2 Shell(32bit,msys-2.0.dll環境下)でシェル(mintty)を立ち上げて,MinGW-w64(64bit版)のOpenCVのパッケージをインストールします.当然のごとくMSYS2版のOpenCVはありません.

$ pacman -S mingw-w64-x86_64-opencv

そして,とりあえず,

$ gem install ruby-opencv -V

としてみます.「-V」をつけることで,ビルドの詳細を確認することができます.(別につけなくてもいいです)

Building native extensions. This could take a while...
/usr/bin/ruby.exe extconf.rb
>> Check the required libraries...
checking for main() in -lstdc++... *** extconf.rb failed ***

はい,失敗しました.Makefileさえ作成できません.

mkmf.logを見てみると,

"gcc -o conftest.exe -I/usr/include/ruby-2.1.0/x86_64-msys -I/usr/include/ruby-
2.1.0/ruby/backward -I/usr/include/ruby-2.1.0 -I. -I/usr/include -I/usr/local/i
nclude -D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fno-strict-a
liasing conftest.c -L. -L/usr/lib -L/usr/lib -L/usr/local/lib -L. -pipe -fstack
-protector -lruby210 -lpthread -lgmp -ldl -lcrypt "
/usr/lib/gcc/x86_64-pc-msys/4.9.2/../../../../x86_64-pc-msys/bin/ld: -lgmp が見つ
かりません
collect2: エラー: ld はステータス 1 で終了しました

ライブラリの場所として「/usr/lib」,「/usr/local/lib」しか見に行っていません.

MinGW64(64bit版)のOpenCVは,「/mingw64/lib」に置いてあるので,そこを指定しなければなりません.ということで,別にlibxml2ライブラリの場所も同じように指定して,

$ gem install ruby-opencv -V -- --with-opencv-dir=/mingw64 --with-libxml2-dir=/mingw64

とやってみると,Makefileは作成できました.コンパイルも上手く行っています.しかし,最後の opencv.so 生成の際のリンク作業中に...

algorithm.o:algorithm.cpp:(.text+0x502): `cv::fastMalloc(unsigned long)' に対する
定義されていない参照です
algorithm.o:algorithm.cpp:(.text+0x502): 再配置がオーバーフローしないように切り詰められ
ました: R_X86_64_PC32 (未定義シンボル `cv::fastMalloc(unsigned long)' に対して)
collect2: エラー: ld はステータス 1 で終了しました
Makefile:232: ターゲット 'opencv.so' のレシピで失敗しました
make: *** [opencv.so] エラー 1
ERROR: Error installing ruby-opencv:
ERROR: Failed to build gem native extension.

というエラー発生.「R_X86_64_PC32」が未定義? なんだこれ,ということでググってみても良くわからず...

恐らく,Win64ネイティブなバイナリをMSYS2環境でリンクさせるのはダメなんでしょう.

そこで,今度は,MinGW64-w64 Win64 Shell(Win64環境下)でシェル(mintty)を起動して,

$ gem install ruby-opencv -V -- --with-opencv-dir=/mingw64 --with-libxml2-dir=/mingw64

すると今度はいきなり...

checking for main() in -lmsvcrt... yes
checking for main() in -lopencv_calib3d2411... no
*** extconf.rb failed ***

ライブラリ「libopencv_calib3d2411」がないので,Makefileが作れませんでした,ときた...

/mingw64/lib配下にあるのは「libopencv_calib3d.dll.a」,お尻に「2411」とついているのは,OpenCVのVersion 2.4.11を意味するようです.このようにライブラリファイル名にバージョン番号をくっつけているのは,Windows版のOpenCVライブラリを見に行っているようなのです.

そこで,OpenCV Windows版バイナリ Ver. 2.4.11 をダウンロードして,適当な場所(例として C:¥Applications¥opencv)にインストール.

$ gem install ruby-opencv -V -- --with-opencv-lib=/c/Applications/opencv/build/x64/vc12/lib \
--with-opencv-include=/c/Applications/opencv/build/include

Windows版は,32bit/64bitの別,それとVisual Studioのバージョンも関係してくるので面倒くさいです.

warningとかたくさん出ますが,何とかMakefileはできたものの,やはりコンパイルエラー...型の定義がコンフリクトしているなどと,ダーッとでてきます.OpenCV Windows版は,Visual C++(msvcrt)でビルドしたもの,それをMinGWで利用するのは至極困難というもの...

  • MSYS2 Shell環境だと,MinGW64 OpenCVライブラリは64bitなのでビルド不可
  • MinGW-w64(Win64) Shell環境だと,ビルドの際にWindows版OpenCVライブラリを見に行ってしまう.
  • Windows版OpenCVライブラリをインストールしても,VC++(msvcrt)でビルドしたものなのでビルド不可

では,最終的にどうしたのかといいますと...

MinGW64(Win64)環境下で,ruby-opencvをビルドするときに,Windows版のOpenCVではなく,MinGW64版のOpenCVのライブラリを参照させるようにすれば良いのです.

それには「extconf.rb」に手を加える必要があります.gem installだとGemのダウンロードからビルド,インストールまで一気通貫でやってしまうので,まずruby-opencvパッケージをGitでダウンロードしてその後手動でビルドさせる方法で行います.

$ git clone https://github.com/ruby-opencv/ruby-opencv.git
$ cd ruby-opencv
$ vi ext/opencv/extconf.rb
incdir, libdir = dir_config("opencv", "/usr/local/include", "/usr/local/lib")
dir_config("libxml2", "/usr/include", "/usr/lib")

ここの部分を,

incdir, libdir = dir_config("opencv", "C:/msys64/mingw64/include", "C:/msys64/mingw64/lib")
dir_config("libxml2", "C:/msys64/mingw64/include", "C:/msys64/mingw64/lib")

に書き換えて,以下の様にファイル名に変にバージョン番号を付加させるところをコメントアウトします.

if $mswin or $mingw
suffix = cv_version_suffix(incdir)
# opencv_libraries.map! { |lib| lib + suffix }           # この行をコメントアウト
# opencv_libraries_opt.map! { |lib| lib + suffix }       # この行をコメントアウト
have_library("msvcrt")
:

でもって,次のコマンドでGemファイルをビルドします.

$ gem build ruby-opencv.gemspec -V

Successfully built RubyGem
Name: ruby-opencv
Version: 0.0.14.20150125044335
File: ruby-opencv-0.0.14.20150125044335.gem

するとこんな長い名前のGemファイルが生成されますので,それをgem installします.

$ gem install ruby-opencv-0.0.14.20150125044335.gem -l -V

上手く行きました!

gem listで確認します.

$ gem list
bigdecimal (1.2.6)
:
ruby-opencv (0.0.14.20150125044335)
:

ちゃんとインストールされているようです.

有効かどうかrequireしてみます.

$ irb
>> require 'opencv'
=> true

OKのようです!

それでは何かプログラムを作成してみます.単純に画像ファイルを読み込んで,ウィンドウに表示させるスクリプトです.

require 'opencv'
include OpenCV

if ARGV.size == 0
    puts 'Usage: ruby #{__FILE__} <input image>'
    exit
end

image = nil
begin
    image = CvMat.load(ARGV[0], CV_LOAD_IMAGE_COLOR)
rescue
    puts 'Cannot open or find the image #{ARGV[0]}.'
    exit
end

window = GUI::Window.new('Display window')
window.show(image)
GUI::wait_key

実行してみます.

$ ruby ocview.rb lena.jpg
広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中