7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OpenCVAdvent Calendar 2021

Day 9

メッセージから逆引きしてエラーの原因を特定する記事

Last updated at Posted at 2021-12-08

#はじめに

  • 本記事はOpenCV Advent Calendar 2021 の9日目の記事です
    • 昨日はsuo-takefumiさんの100行で作るARでした。
    • 凹みや穴を重畳するのは良いデモでしたね
  • 本日の記事はOpenCV使用時やビルド時に出てくるエラーメッセージについてです。
    • OpenCVは、意味不明なエラーに遭遇することがあります。
  • 公式のGithubのissueを眺めていると、明後日な投稿が多数あるのですが、そのうち「一目で原因がわかる」メッセージ達を集めてみました。

#ビルド編

c++: internal compiler error: Segmentation fault (program cc1plus)

  • 原因:ビルドマシンのメモリ量が足りない
  • 対策:もっとメモリを積むか、-j 1 を明示的につける
  • x86マシンだと潤沢にメモリを詰めるが、Raspberry Pi/Jetsonなどの組み込みボードだとメモリが枯渇することがたまに起きる。
  • 「メッセージの通りコンパイラのバグだ!」「OpenCVのバグだ!」と騒ぐ人をたくさん見てきたけれど、メッセージの意図をちゃんと読む必要がある
    • 通常、コンパイル時間を短くするために並列ビルドを行い、-j 4などして4コアで並列してビルドすることがある
    • このとき、メモリ使用量は並列処理数分だけ多く利用することになる
    • また、OpenCV内の一部のソースコードたちも、マクロを多用していたりすると、単体のコンパイルでもメモリ使用量が跳ね上がったりする。
    • メモリの使用量が逼迫している場合、GCC内でSegmentation faultが起きたり、カーネルにプロセスをkillされたりする
  • という訳で、前述の対策に行き着く。
  • また、ccacheを使うのも、並列ビルドを可能にしながらもメモリ使用量を抑える良い手段(その代わりストレージが必要になる)

Duplicated modules NAMES has been found

  • メッセージ文中のNAMESには特定のモジュールの名前が入る
  • 原因:contrib付きでビルドする際に、本体側が3.4系列、contrib側がmasterだと発生する
  • 対策:本体側、contrib側で同じブランチをチェックアウトする
  • opencv_contribは、いわばOpenCVの2軍とも言うべき存在でまだ荒削りなmoduleだったり使用頻度の低いmoduleがcontribに格納される
  • ときに、contribから本体は「昇格」があったり、逆の「降格」があったりする。その際、本体側とcontrib側でbranchの整合性が取れてないと、同じ名前のmoduleが両方に存在してしまう
  • 結果、前述のエラーメッセージが以下のように発生する
core
> cudaarithm
> cudabgsegm
> cudacodec
 : (以下続く)
  • 3.4系列まではCUDA関連のモジュールは本体側にあったが、4系列でcontribに送られた。
  • このため、このエラーで目にするモジュール名はCUDA関連のモジュールであろう。
  • ただし、エラーが特徴的なので、すぐに見抜けるはず

fatal error: boostdesc_bgm.i: No such file or directory

  • make時に発生する
  • 原因:https通信に問題あり
  • xfeatures2d モジュールのcmake時に、バックグラウンドでソースコード(分類器)のダウンロードが行われる
  • このとき、CMake内製の通信モジュールでhttps通信が行われる
  • https通信に失敗しうる原因は主に2つ
    • 1つはビルド時の環境がproxyなどを利用しており、一部のhttpsサイトを遮断している場合
    • もう1つは、ソースコードからcmakeをビルドして、その際cmakeのbootstrapオプションに--system-curlをつけ忘れた場合
    • いずれの場合もhttps通信に失敗し、ファイルがダウンロードされない。
    • そしてダウンロードされてないファイルを参照するため、前述のエラーが発生する
  • OpenCVのバグではないので、自身のネットワーク環境を調べよう
  • なんでこういう仕組みになってるのかはわからないけれど、もしかしたらライセンス関係でこうなってるのやもしれぬ(未調査)

nvcc fatal Unsupported gpu architecture compute_xx

  • 末尾のxxには数字が入る
  • 原因:CUDAのバージョンが希望のCCをサポートしていない
  • 対策:新しいGPUを使いたいなら新しいCUDAにする。

Error generating /xxx/modules/core/CMakeFiles/cuda_compile_1.dir/src/cuda/./cuda_compile_1_generated_gpu_mat.cu.o

  • 原因:ディスク容量不足
  • 対処方法:/tmp/パーティションが載ってるディスクの容量を空ける
  • CUDA関連のコードは/tmp/以下に一時的なファイルを生成する
  • このファイルはときにGBオーダーのサイズになることがある
  • Jetson Nanoを始めとして、SDカードの容量をケチったりしてると、/tmp/ のパーティションがいっぱいになることも多々見かける。

Required baseline optimization is not supported: VFPV3

  • 原因:Aarch64上でのビルドで、-DCPU_BASELINE=VFPV3をつけている
  • 対処方法:CPU_BASELINEオプションは空にする
  • CPU_BASELINEオプションはCMake時に渡す
  • Aarch64で使えるオプションは現在(2021/12/1時点, OpenCV 3.4.16, 4.5.3)使えるのはNEONFP16のみ。
    • Armv7 ではVFPV3も使えたが、VFPV3NEONのサブセットとでも言うべき拡張であり、NEONがAarch64 (Armv8)で標準命令セットに含まれた以上、VFPV3だけ個別に指定する意味は無い
    • もっと言えば、FP16命令も標準命令に含まれているので、Aarch64はCPU_BASELINEオプションを使う場面は無い
    • ただ、Apple M1を始め、オイシイ拡張命令がどんどんアクセスできるようになってるので、いずれOpenCVで拡張命令を使った実装がされる可能性が高い。
    • なので、CPU_BASELINEオプションを指定して意味がある日が来るかもしれない。

#実行時編

unresolved external "__declspec(dllimport) bool cv::__termination in DllMain"

  • 筆者の過去記事参照
  • 原因はOpenCV 4.0.0固有の既知のバグ
  • OpenCV 4.0.0だけで起きる。3系列では起きないし、4.0.1ではFIXが含まれている
  • 迂回策として、 cmake -DOPENCV_SKIP_DLLMAIN_GENERATION=ON ... というようにOPENCV_SKIP_DLLMAIN_GENERATIONオプションを使う方法もある
  • このページに書いてある現象のうち、この現象だけはOpenCVのバグである。あとは環境か使い方の問題であることに注意。

OpenCL error CL_OUT_OF_RESOURCES (-5) during call: clEnqueueNDRangeKernel

  • 環境によってはわんさかと遭遇するメッセージ
  • これはerrorという文言を含んでいるが、エラーではない。OpenCLから出てくるメッセージ
  • 具体的には、使用しているOpenCLデバイスに対して、可能な容量以上の計算を投げると、OpenCL側でエラーを挙げる。このときコンソールに表示される画面が前述のメッセージ
  • 一方で、OpenCV内ではOpenCL実行がコケた場合、自動的にCPU実装に切り替える1ので、見た目にはエラーに見えない。

OpenCV Error: Assertion failed (size.width>0 && size.height>0)

  • 原因:ファイルのオープンに失敗している
  • 解説:OpenCVでは、ファイル名を間違えていたり、存在しないファイルをオープンしようとしたり、またはパーミッションでオープンできなかった場合など、正しくファイルを開けなくても、実行時エラーを「投げない」
  • 代わりに、ユーザはファイルが正しくオープンできたかどうか、.empty()メソッドを使って確認することを求められる
  • ファイルのオープンに失敗して、空っぽのMatであることを確認せずにOpenCVのAPIに投げると、前述のような、様々な実行時エラーが投げられます。
  • 直接の起因とエラーメッセージが対応してないのでわかりにくいですが、原因はファイルのオープンです。
  • また、APIによって、Assertionが様々ですので、前述のメッセージ以外のメッセージが出ることがあります。気をつけましょう。

番外編

野良ビルドを多用した場合

  • タイトルと趣旨が反するのですが、「不思議なことが起きたときの原因」の話です。
  • 当時私が突き当たった環境はWindows 7、MSVC2015、OpenCVは3.0かそのあたりの話だったと思います。
  • 現象としてはアクセス違反、確保した領域外にアクセスしていました。
    • が、状況をよくよく調べると、「画像をopenしてロードする際、コンストラクタを通らずにいきなりallocateされてないメモリ領域に書き込もうとしてアクセス違反」という意味不明な状況でした。
    • また、imread関数にわたすパラメータに依らずアクセス違反が発生しており、果たして原因は何なのか、途方にくれていました。
  • 紐解けば簡単な話で、ビルド時に使ったlibファイルと、実行時に読み込まれるdllファイルが、違うバージョンだったのです
    • 厳密にはバージョンはマイナーバージョンまで一致していたのですが、微妙なビルドオプションが違いました。
    • 下手にマイナーバージョンが合っていたため、明示的にエラーが発生せず、関数callがへんてこな場所から開始していたためでした。
  • 野良ビルド、気をつけましょう。

さいごに

  • OpenCVのエラーメッセージは残念ながらお世辞にもわかりやすいとは言えません。
  • このページにたどり着いた人が少しでも時間の無駄を減らせれば、と思います
  • 明日は@fukushima1981先生の投稿で、執筆時点でのタイトルは「OpenCVによる特異値分解と最小二乗法」です。楽しみですね!
  1. 唯一rgbdモジュールのKinect Fusion関係のコードは、本エラーを正しくハンドリングしない。ぴえん。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?