まんぼう日記

takataka's diary

Mac + OpenCV 3.1 の VideoCapture が 100 秒で落ちる件

ツクツクボウシが鳴く時節になりました.あのひとたちの鳴き声を聴くとどうしても「天空の城ラピュタ」に出てくる飛行船を思い出してまうたかたかです.

 

6月末に標記のような問題を見つけて7月はじめに自分の周りのんについては対処したんですが,「そのうちパッチが反映されたんが(たかたかが使ってる)MacPorts でインストールできるようになるやろ」と放置してたら,いまだに未対応なので,記事に書いとくことにしました.ほんまは,MacPortsのメンテナさんに連絡して対応してもらうとかするのがええんでしょうが….

 

件の問題が発生する環境は,こんなんです:

  • OS X Yosemite な MacBook Air/Pro で内蔵カメラを使用
  • OpenCV は,MacPorts でいれた 3.1
$ port installed opencv
  opencv @3.1.0_3+eigen+opencl+python27+tbb (active)

この環境で,python で cv2.VideoCapture(3.1でのpython版のドキュメントが見つからないので,3.0の旧版にリンクしてます)使ったプログラム書いて動かすと,最初は問題なく動作しますが,100秒後

libc++abi.dylib: terminating with uncaught exception of type NSException

というエラーを吐いてプログラムが異常終了します.

 

 

で,いろいろ探しまわった結果,対応策はこちらで見つけました:

MacOSX / QTKit capture: trying to fix invalid timer call · opencv/opencv@a2bda99 · GitHub

cap_qtkit.mmにパッチを当てればよい,と.2月に master に merge されてるので,開発版をおっかけてる人は反映されてるんでしょう.リリース版使ってる人は,次の版のリリースを待ちましょう…というわけにもいかへんので,手動でパッチあてることにしました.

 

まず,OpenCV をいったんアンインストールします.

$ sudo port uninstall opencv@3.1.0_3+eigen+opencl+python27+tbb

そして,ソースアーカイブを集めてきて(fetch),展開し(extract),(MacPortsで用意してる)パッチを当てます(patch)

$ sudo port fetch opencv +eigen+opencl+python27+tbb
$ sudo port extract opencv +eigen+opencl+python27+tbb
$ sudo port patch opencv +eigen+opencl+python27+tbb

ちなみに,portコマンドが依存関係を自動で解消するので,port patch だけ実行すれば上2つを勝手に先に実行してくれます.

 

展開されたソースファイルたちの中から目的のものを探してパッチを当てます.目的のファイルmodules/videoio/src/cap_qtkit.mmは,次のどちらかから下っていった所にあると思います(7月に作業したときは前者だったけど,さきほど試したら後者でした.この話がなんか関係あるのかな? [MacPorts-announce] New build system).

/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/graphics/opencv
/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_graphics_opencv/opencv/work

上記のディレクトリは,それぞれport dirおよびport workの出力です.

では,パッチを当てましょう.こんなん.

--- modules/videoio/src/cap_qtkit.mm	2015-12-19 00:02:16.000000000 +0900
+++ modules/videoio/src/cap_qtkit.mm	2016-07-13 14:19:35.000000000 +0900
@@ -93,6 +93,8 @@ didDropVideoFrameWithSampleBuffer:(QTSam
 - (int)updateImage;
 - (IplImage*)getOutput;
 
+- (void)doFireTimer:(NSTimer *)timer;
+
 @end
 
 /*****************************************************************************
@@ -622,6 +624,11 @@ didDropVideoFrameWithSampleBuffer:(QTSam
     return 1;
 }
 
+- (void)doFireTimer:(NSTimer *)timer {
+    (void)timer;
+    // dummy
+}
+
 @end

上記の内容を ~/patch.txt というファイルとして保存してたとすると,次のようにしてパッチを当てることができます.

$ cd `port work`
$ cd opencv-3.1.0/modules/videoio/src
$ sudo patch < ~/patch.txt

 

仕上げは,パッチを当てたソースからのビルドとインストール.

$ sudo port build opencv +eigen+opencl+python27+tbb
$ sudo port -s install opencv +eigen+opencl+python27+tbb

install の際に -s を忘れると,せっかくのソースを無視してバイナリパッケージをインストールしてくれちゃう(当然パッチは反映されない)ので気をつけましょう.

 

後は,VideoCapture 使ったプログラムで動作確認.100秒経っても落ちなければおけ.