OpenCV野良ビルド時にCMakeが指定したPythonのライブラリをうまく見つけてくれない時は

OpenCVをPythonサポート込みでビルドしたいことがあります。
Python側へインタフェースを露出するためのヘッダなどが必要なので、いくつかのPython関連パッケージを入れれば、あとはシンプルにCMakeを実行すればよいことがほとんどです。
(そのやり方はネットにたくさんまとまっているので他をご参照ください)

% sudo apt-get install python2.7-dev python3.4-dev #などなど。
% cd /path/to/opencv/source/root
% mkdir build; cd build
% cmake -DBUILD_opencv_python2=ON -DBUILD_opencv_python3=ON ..

一方で、rootがないなどの状況でpython2.7-devなどのパッケージがシステムにない場合は、例えばpyenvを使って一時的にpythonをユーザ環境に入れそのパスを参照させることで、Python対応こみでビルドすることが可能です。
(ビルドがおわったら一時的に入れたPython環境は消してOKです)

% pyenv install miniconda2-latest
% pyenv install miniconda3-latest
% cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$HOME \
        -DBUILD_opencv_python2=ON \
        -DPYTHON2_EXECUTABLE=`pyenv local miniconda2-latest; pyenv which python` \
        -DPYTHON2_INCLUDE_DIR=`pyenv local miniconda2-latest; python -c 'from distutils.sysconfig import get_python_inc; print(get_python_inc())'` \
        -DPYTHON2_NUMPY_INCLUDE_DIRS=`pyenv local miniconda2-latest; python -c 'import numpy; print(numpy.get_include())'` \
        -DPYTHON2_LIBRARIES=`find $PYENV_ROOT/versions/miniconda2-latest/lib -name 'libpython*.so'` \
        -DBUILD_opencv_python3=ON \
        -DPYTHON3_EXECUTABLE=`pyenv local miniconda3-latest; pyenv which python` \
        -DPYTHON3_INCLUDE_DIR=`pyenv local miniconda3-latest; python -c 'from distutils.sysconfig import get_python_inc; print(get_python_inc())'` \
        -DPYTHON3_NUMPY_INCLUDE_DIRS=`pyenv local miniconda3-latest; python -c 'import numpy; print(numpy.get_include())'` \
        -DPYTHON3_LIBRARIES=`find $PYENV_ROOT/versions/miniconda3-latest/lib -name 'libpython*.so'` \
        ..

このとき、CMakeを走らせたときの序盤にこんなメッセージが出たり(PythonLibsを見つけられてなかったり、意図したのと違うものを見つけに行ってる)、

 -- Found PythonInterp: /home/xxxx/.pyenv/versions/miniconda2-latest/bin/python (found suitable version "2.7.14", minimum required is "2.7")
 -- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython2.7.so (found suitable exact version "2.7.14")
 -- Found PythonInterp: /home/xxxx/.pyenv/versions/miniconda3-latest/bin/python (found suitable version "3.6.3", minimum required is "3.4")
 -- Could NOT find PythonLibs (missing:  PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS) (found suitable exact version "3.6.3")

CMakeの最後の結果表示のときにこんなメッセージが出たり(LibrariesがNO)、

 --   Python 2:
 --     Interpreter:                 /home/xxxx/.pyenv/versions/miniconda2-latest/bin/python (ver 2.7.14)
 --     Libraries:                   NO
 --     numpy:                       /home/xxxx/.pyenv/versions/miniconda2-latest/lib/python2.7/site-packages/numpy/core/include (ver 1.14.0)
 --     packages path:               lib/python2.7/site-packages
 --
 --   Python 3:
 --     Interpreter:                 /home/xxxx/.pyenv/versions/miniconda3-latest/bin/python (ver 3.6.3)
 --     Libraries:                   NO
 --     numpy:                       /home/xxxx/.pyenv/versions/miniconda3-latest/lib/python3.6/site-packages/numpy/core/include (ver 1.14.0)
 --     packages path:               lib/python3.6/site-packages

正しく指定したはずのライブラリのパスをCMakeがどうも認識してくれない様子のときは、CMakeのバージョンを疑ってみてください

% cmake --version
cmake version 2.8.12.2

2.8系では、うまくPythonのライブラリをみつけてくることができないようです。
OpenCVの提供するCMakeLists.txtのcmake_minimum_requiredは(Linuxであれば)2.8になっているので、特に怒られることなく進んでしまう、というのが罠でした(今回取り上げたかなり限定的なシチュエーション以外ではそれで問題なく動くためです)。

特にUbuntu14.04をまだ使っていたりした場合は、標準でapt-getしたものは2.8までになります。
野良ビルドするなり、PPAにするなり、新しいUbuntuに乗り換えるなりするといいです。

自分用メモ。

tmuxのセッション作成時に名前付けを強制するzshrc

魚を飼う時、繁殖をさせやすいのはグッピーやアカヒレなどだそうです。数匹のつがいがいればすぐに数百匹まで増えてしまうんだとか。

さて、tmuxヘビーユーザーなんですがセッションが乱立しがちで、外からsshして既存セッションをattachするときにどれがどれかわからないことが個人的にはよくあります。
セッション内の任意のウィンドウもしくはペインでtmux rename-sessionをすることでセッション全体に名前をつけることができ、attachするときこの名前で参照することができて便利です。
これを、セッション作成時に自動で聞くようにしてみました。

やりたいこと

  • tmuxでセッションを作ったあと最初のウィンドウが開かれる時、そのセッションに名前をつけるのを強制したい
  • 何も入力しないことも許容する。その場合は名前付けしない

やりたくないこと

  • 名前付けしなかった場合、セッション内で新たなウィンドウやペインを開く度にまた聞かれたくない

やってることは単純で、zshが起動した時それがtmuxセッション内でかつセッション名がデフォルト(数字のみ)のままである場合、名前の入力を求めtmux rename-sessionコマンドを呼ぶだけです。
何も入力しない場合はセッション名はデフォルトのまま放置しますが、そのままだとセッション内で新たなshellを開く度にプロンプトが出て鬱陶しいので、それが出ないようtmuxのsession-wideな環境変数を使いマークしています。シェル環境変数にマークした場合引き継がれないのでうまくいきません。

tmux 2.2(Mac)と2.1(Ubuntu)で確認しています。

てきとうに書いたのでもっとCOOLなやり方もあると思いますが、ひとまずこんなかんじで。

UbuntuでOpenCVをlibjpeg-turboつきでビルドする

都道府県別の一人あたり魚介類消費量では、青森県がトップで、以下秋田、鳥取、新潟、富山と日本海側の県が続きます。島国・沖縄が意外にも最下位です。

さて、OpenCVで画像をロードするのを速くしたくて、JPEGについてはlibjpeg-turboというのが使えることを知りました。
libjpeg-turboはlibjpegをSIMDなどによって高速化したものでAPIレベルの互換性を保っています。
条件が良ければデコードが数倍速くなるということで、これをOpenCVに組み込んでビルドする方法をメモ。

Continue reading

MacからLinuxにssh X11Forwardingする

スズキは出世魚ということで有名ですが、結局何種類の呼び方があるかご存知でしょうか?地方によるようですがなんと4〜5種類。上には上がいて、ボラは6種類。おぼえきれんわ!

さて、MacからLinuxなPCにX転送でsshしたいときの設定、ググればすぐわかるのですが自分の備忘録がてらにメモ。

前提として、普通にLinux同士でのSSH XForwardingまではできてると想定します。
(入り先のsshd_configのX11Forwardingをyesに)

Mac用X端末XQuartzの導入

MacではXが動いてないので、導入する必要があります。
brewでは入れられない模様。

XQuartz download

ダウンロードしてインストールしてください。

これでOK!

% ssh -X foobar@hoge.jp
$ DISPLAY=localhost:10.0 chrominum-browser

高速化Tips

Macに限ったことではないですがX転送を快適にする設定。

.ssh/configを編集して、

Host *
  Compression yes
  CompressionLevel 9
  Ciphers arcfour256

なる設定を追加すると、結構速くなります。
上2つの項目は説明不要でしょう。Ciphersは暗号化方式で、
How to speed up X11 forwarding in SSH – Xmodulo
等に記述がある通り、arcfour256でかなり高速になります。

イマドキなCUDA 6.5のインストール手順@Ubuntu

現在確認されている深海魚として最も深いところでは8,000メートルを超えるところで見つかったヨミノアシロという種だそうです。8,000メートルって。800気圧って。

さて、CUDAの開発環境の構築は昔から少々面倒で、多少のLinuxの知識と折れない心と英語力が必要です。
自分もこのたびわりと久しぶりに自宅PCにCUDA環境を構築したら、やり方も変わっていて躓いたので備忘録としてメモ。

Continue reading

zsh(やshやbash)でパス系環境変数の重複を除去する

魚へんのつく漢字は非常にたくさんあって、よく雑学問題とかになるんですが、実際のところいくつあるんでしょう。Unicodeの文字表で調べてみたところ、魚へんのつく漢字は394種類ありました。実際はもっとあるんでしょうが、すごいですね。

さて、tmuxを使っていたり、シェル設定を書き換えてsourceしたりなど、PATHやLD_LIBRARY_PATHなどのパス系環境変数の記述が重複してしまうことがよくあります。
これを解決するためのメモ。
参考はこちら。というか完全にそのまま。
zsh で環境変数 LD_LIBRARY_PATH、INCLUDE などの重複パスを除去する – キーボードをたたくとき

zshrcやzshenvに下記のような記述をすればOKです。

typeset -T LD_LIBRARY_PATH ld_library_path; typeset -U ld_library_path
typeset -T LIBRARY_PATH library_path; typeset -U library_path
typeset -T CPATH cpath; typeset -U cpath

どういう意味かは参考サイトの通りです。

また、特にPATHなどに関しては以下の記述で重複除去ができます。

typeset -U path cdpath fpath manpath

ところで、パス記述の重複ってパフォーマンスには影響するのかな。
つまり、実際のパス探索の段階で、すでに見たところをまた見に行ったりするんでしょうか。
だとすると重複除去は絶対必要ですねー。

あと、bashで同じことをしたい場合はどうすればいいんでしょう。
こんなかんじで重複除去自体はできなくはないですが、

$ PATH=c:b:c:a:b:a
$ PATH=`echo $PATH | sed "s/:/\n/g" | sort -u | paste -sd ":"`
$ echo $PATH
a:b:c

記述順が変化してしまい、実際のパス探索の順序が変わってしまい、イケてないかんじです。
力技でできないことはないけど・・・スマートにできないものか。

追記。bashやshでの重複除去を力づくでやってみたので、興味があれば続きを参照。

Continue reading

Linux上のAndroid開発で実機実行する際のudev/adb設定

お久しぶりです.今年度から名古屋のお魚さんかわって東京のお魚さんになったお魚さんです.

魚類の中で最小の種は,Paedocypris progeneticaと言い,成魚で体長7.9〜10mm程度なんだそうですね.
最小の魚類であるばかりか,最小の脊椎動物とのことです.

さて,Linux PC上でAndroidアプリ開発するとき,Android端末をPCに認識させるために設定が必要です.
ググれば出る情報ですがよく忘れるのでメモ.

やることは単純です.
(1)端末のベンダIDをudevのルールに追加
(2)adbを再起動
ついでに,アプリを端末上で実行するところまで説明します.

udev設定

Android端末をUSBでLinux PCとつなぎます.

% lsusb
...
Bus 002 Device 018: ID 0fce:619e Sony Ericsson Mobile Communications AB
...
Bus 002 Device 021: ID 0bb4:0ff9 HTC (High Tech Computer Corp.)
...

こんなかんじで,SONY EricssonのベンダIDは0fce,HTCのベンダIDは0bb4,…というかんじで見ることができます.

ベンダIDを調べたら,

SUBSYSTEM=="usb", ATTRS{idVendor}=="ここにベンダIDを入れる", MODE="0666", GROUP="plugdev"

という文字列を,以下ファイルに追記します.端末を複数お持ちならベンダごとに記述してください.
/etc/udev/rules.d/51-android.rules

終わったら,念のためにudevに設定をリロードさせます.で,adb (android debug bridge)を再起動します.

% sudo udevadm control --reload-rules
% adb kill-server
% adb start-server

ちなみにadbは,Android SDKのルートディレクトリ下のplatform-toolsにあります.
ここまでで設定は完了です.

アプリ動かすまで

ここで一旦Android端末をUSBから引っこ抜いて,また接続します.
これをしないとudevが端末を認識してくれないので.

では,実際にアプリを動かしてみましょう.
開発環境(Eclipse+SDK+ADTPlugin)については導入済みということにして,またAndroid端末のUSBデバッグモードも有効にしておいてください.

プロジェクトもすでに作ってあるとします.
EclipseのRun asボタンをクリックして,

eclipse_click_run_as

端末を選択して,
eclipse_choose_real_device

OKをクリックすると端末で動きます!
execution_result_htcj

Androidに限らず,もっとみんなLinux PCで開発すればいいのに!(マサカリ覚悟)

参考

ssh XForwardingを速くする設定

おさかなさんも先日,24歳を迎えました.もう若くはないです.
しかしキャビアで有名なチョウザメは寿命が150年〜200年にも達するそうです.

手元の環境でssh XForwardingするとき速度が遅くて困っていたのですが,ちょっと調べると高速化Tipsがあり,効果覿面でしたのでメモがてらに.
How to speed up X11 forwarding in SSH – Linux FAQ

~/.ssh/configに

Host *
    Compression yes
    CompressionLevel 9
    TCPKeepAlive yes
    Ciphers blowfish-cbc,arcfou

こんな感じの記述を追加します.

ふつう

% ssh -YC hogehoge@fugafuga

とするとX転送とCompressionが有効な状態になりますが,暗号化処理が結構重たく遅くなるようです.そこでこの設定をすると暗号化処理が軽くなりトータルでも速くなるという理屈のようです.

個人的な印象ですが,WWWブラウザとか画像ビューア(geeqie)まるごとX転送して遠隔操作するぶんには,今まで話にならなかったのがこの設定によってまぁ問題ないぐらいまで速くなった気がします.

こちらも読んでておもしろい.
OpenSSH ciphers performance benchmark | /contrib/famzah

sshのXForwardingを速くする設定と題した記事ですが,ssh全般的に速くなる設定ですねこれは.

OpenCVビルド時のCUDAのccbinの指定方法

リンネの生物階級分類において,「スズキ目」というのは脊椎動物中で最大の規模を誇る「目」なんだそうです.
スズキ目スズキ科スズキはまさに全生物中における最大勢力を束ねる王者と言えましょう.だから何.

さかな前線 » CMakeでCUDAの-ccbinの正しい指定方法の姉妹記事です.

さて,Linux上でOpenCVでCUDAサポートをONにしてビルドするとき,GCCのバージョンを指定したいことがあります.
基本的にはデフォルトGCCなんですが,4.8系などは現在のCUDAのnvccではサポートされていませんので,CUDAビルド時に限りGCC4.4や4.6を使うという設定です.

具体的には,CMakeのときに以下のように書きます

$ pwd
/home/hogehogehogehogeho/opencv-2.4.6.1/build

$ cmake -DWITH_CUDA=ON -DCUDA_HOST_COMPILER=/usr/bin/g++-4.4 ..

$ make -j40 -s; sudo make install

WITH_CUDAとともにCUDA_HOST_COMPILERを正しく設定すればいいのですが,CUDA_HOST_COMPILERに指定するgccはPATHが通っていても絶対パスで指定する必要があるようです.
CUDA_HOST_COMPILER=g++-4.4と書くと,ないよ>< って言われます.

以上です.

参考:OpenCV – Bug #2844: build with CUDA 5.0 on macosx – OpenCV DevZone

CMakeでCUDAの-ccbinの正しい指定方法

半年ぶりの更新です.
半年の間に,しらすの春の旬と秋の旬をまたぐことになりました.
っていうか,寒いよ!夏がいいよ!!><

さて,Linux上のCMakeでCUDAを使っているんですが,CUDAではたいてい最新のGCCはサポートされません.
ということで,nvccの-ccbinオプションによってCUDA関連のコンパイルのみを古いGCCにすることができます.
普段のC++コードは最新のGCCで,CUDA関連のみはサポートされたGCCでご利用いただけます.

CMakeにおいてこれを行うときは少しクセがあり,だいぶ格闘したのでメモ.

-ccbinの例

例えば次のソースを用意します.

// prog.cu
int main()
{
}

GCCの4.8.1を使ってnvccでコンパイルしてみると.

$ g++ --version
g++ (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ nvcc prog.cu
In file included from /usr/local/cuda/bin/../include/cuda_runtime.h:59:0,
                 from <command-line>:0:
/usr/local/cuda/bin/../include/host_config.h:82:2: error: #error -- unsupported GNU version! gcc 4.7 and up are not supported!
 #error -- unsupported GNU version! gcc 4.7 and up are not supported!
  ^

$ nvcc prog.cu -ccbin g++-4.4
$ ./a.out
(うごいた)

こうなります.
ちなみに今回はCUDA 4.2の環境.

CUDAソースによる小さいサンプル

本題.

CMakeだとnvccは自動的に実行されるので,nvccに与えるオプションはちゃんと与える必要があります.

ということで,CMakeLists.txtの最小の例.
上のprog.cuと同じディレクトリに置きます.

#A tiny example of CMakeLists.txt

cmake_minimum_required(VERSION 2.8)                     # おまじない
project(osakanacuda)                                    # プロジェクト名

set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -ccbin g++-4.4)  # GCCへのパス.PATHが通っていればこのように名前のみの指定でもOK
#list(APPEND CUDA_NVCC_FLAGS -ccbin g++-4.4)            # これでもOK

#以下はどちらもダメ.違いがわかりますか?
#set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -ccbin=g++-4.4)
#list(APPEND CUDA_NVCC_FLAGS=-ccbin g++-4.4)

find_package(CUDA)                                      # CUDA環境を見つけてくれる.やらないとダメ
cuda_add_executable(prog prog.cu)                       # progっていう実行ファイルをビルドしてくれる設定になる

こんな配置だとすると,

.
├── CMakeLists.txt
├── prog.cu
└── build/

次のようにしてビルドします.

$ ls
CMakeLists.txt prog.cu build/

$ cd build
$ cmake ..
$ make

ダメって書いてある方の指定をすると,

nvcc fatal   : redefinition of argument 'compiler-bindir'
CMake Error at prog_generated_prog.cu.o.cmake:206 (message):
  Error generating
  /hogehogehogehogheohgoehgoehoge/build/CMakeFiles/prog.dir//./prog_generated_prog.cu.o

っていう内容を含んだエラーが出ます.

理由

正しい指定と誤った指定の違いは見ての通り,”-ccbin=hogehoge”か”-ccbin hogehoge”の違いなんですが,CMakeのFindCUDAにあるrun_nvcc.cmakeを読んでみると,
“-ccbin”という文節があった場合にその指定を優先するようになっており,
ない場合はCMakeの中でのデフォルトの指定をすることになっています.

なので,”-ccbin=hogehoge”をCUDA_NVCC_FLAGSに指定すると,nvccが呼び出されるときは

nvcc ... -ccbin=hogehoge -ccbin fugafuga ...

となり,「多重指定はダメだっちゃ」と怒られます.

なんちゅー仕様.誰か修正してくださ・・・

なお今回の環境は,

  • Debian 6.0
  • CMake version 2.8.11.1
  • CUDA 4.2
  • GCC 4.8.1/4.4.5

です.