この記事はOpenCV Advent Calendar 2015の3日目の記事です.
はじめに
OpenCVは,エラー内容に応じたエラーコードを定義しているだけでなく,エラーメッセージ表示機能,例外処理機能を提供しています.
この記事では,
- OpenCVで定義されるエラーコードの意味を理解することで**「開発者がエラーメッセージからソースコードのどの箇所でどのような問題が起きているかを把握できるようになる」**
だけでなく,
- OpenCVが提供するエラーメッセージ表示機能,例外処理機能の使い方を理解することで**「開発者が適切なエラーメッセージを表示したり,例外処理の実装を行えるようにする」**
ことを目的としています.
エラーコード一覧表
以下の表にOpenCVが定義するエラーコードとその意味をまとめています.
ソースコード上ではcore/include/opencv2/core/base.hpp
で定義されているため,興味のある方は読んでみるとよいでしょう.
エラーコード | 意味 |
---|---|
StsOk0 | 正常 |
StsBackTrace | BackTraceのための疑似的なエラー |
StsError | 不明なエラー |
StsInternal | 内部エラー |
StsNoMem | メモリ不足 |
StsBadArg | 不正な引数/パラメータ |
StsBadFunc | 非サポートの関数/機能 |
StsNoConv | 収束しない場合のエラー |
StsAutoTrace | AutoTraceの呼び出し |
HeaderIsNull | イメージヘッダーがNULL |
BadImageSize | 不正なイメージサイズ |
BadOffset | 不正なオフセット値 |
BadDataPtr | 不正なDataPtr |
BadStep | 不正なステップ値 |
BadModelOrChSeq | 不正なモデル/シーケンス |
BadNumChannels | 無効なチャンネル数 |
BadNumChannel1U | 無効なチャンネル数 (1U:1チャンネル符号なし) |
BadDepth | 不正なdepth値 |
BadAlphaChannel | 無効なアルファチャンネル |
BadOrder | 不正なOrder指定 |
BadOrigin | 不正なOrigin指定 |
BadAlign | 不正なアライメント |
BadCallBack | 不正なコールバック |
BadTileSize | 不正なタイルサイズ |
BadCOI | 不正なCOI(Channel of Interest)指定 |
BadROISize | 不正なROI(Region of Interest)指定 |
MaskIsTiled | マスクがタイル配列 |
StsNullPtr | ヌルポインタが渡ってくるべきでない 箇所でヌルポインタが渡された |
StsVecLengthErr | vector配列の長さが適切でない |
StsFilterStructContentErr | 不正なフィルター構造 |
StsKernelStructContentErr | 不正なカーネル構造 |
StsFilterOffsetErr | 不正なフィルターのオフセット値 |
StsBadSize | 不正なサイズ |
StsDivByZero | ゼロ除算の発生 |
StsInplaceNotSupported | in-place操作が非サポート |
StsObjectNotFound | オブジェクトが見付からない |
StsUnmatchedFormats | アンマッチなフォーマット指定 |
StsBadFlag | 不正なフラグ指定 |
StsBadPoint | 不正な座標値指定 |
StsBadMask | 不正なマスク |
StsUnmatchedSizes | アンマッチなサイズ指定 |
StsUnsupportedFormat | 非サポートのフォーマット指定 |
StsOutOfRange | パラメータが範囲外の値 |
StsParseError | パースエラー |
StsNotImplemented | 未実装の関数/機能 |
StsBadMemBlock | メモリブロック破壊 |
StsAssert | アサーションエラー |
GpuNotSupported | CUDA機能を無効にしたOpenCVライブラリで CUDA機能を使用した場合のエラー |
GpuApiCallError | CUDA API呼び出し時のエラー |
OpenGlNotSupported | OpenGL機能を無効にしたOpenCVライブラリで OpenGL機能を使用した場合のエラー |
OpenGlApiCallError | OpenGL API呼び出し時のエラー |
OpenCLApiCallError | OpenCL API呼び出し時のエラー |
OpenCLDoubleNotSupported | OpenCLデバイスが倍精度浮動小数点数 (double型)を非サポート |
OpenCLInitError | OpenCL初期化時のエラー |
OpenCLNoAMDBlasFft | OpenCL AMD BLAS機能が利用できない |
エラーメッセージ表示
CV_Errorマクロを使う方法
OpenCVで提供されるCV_Error
マクロを用いることでエラーメッセージ表示を容易に記述することができます.このマクロの第一引数はエラーコード,第二引数はエラーメッセージの文字列です。
詳細は公式ドキュメントを参照ください.
以下にCV_Error
マクロの使用例を記述します.
CV_Error(cv::Error::BadNumChannels, "Unsupported channels count");
この例ではエラーコードとしてBadNumChannels
を指定しており,以下のようなエラーメッセージが表示されます.
OpenCV Error: Bad number of channels (Unsupported channels count) in hoge, file fuga.cpp, line 12
このエラーメッセージは以下のような意味を表しています.
メッセージ | 意味 |
---|---|
Bad number of channels |
エラーコードに対応した文字列. この例ではBadNumChannelsに対応した文字列. |
(Unsupported channels count) |
CV_Error マクロの第二引数に指定した文字列 |
in hoge |
エラー発生関数. この例ではhoge関数内でエラーが発生したことを表す. |
file fuga.cpp, line 12 |
エラー発生したファイル名と行番号. この例ではfuga.cppの12行目でエラーが発生したことを表す. |
また,Bad number of channels
という文字列はBadNumChannels
というエラーコードに対応した文字列です.他のエラーコードにも同様に各エラーコードに対応した文字列が用意されています.ソースコード上ではmodules/core/src/system.cpp
のcvErrorStr関数で定義されているため,興味のある方は読んでみるとよいでしょう.
CV_Error_マクロ
CV_Error
マクロではあらかじめ決まった書式でエラーメッセージの表示が行われます.
書式指定を用いたエラーメッセージを出力を行いたい場合はCV_Error_マクロにより実現できます.
CV_Assertマクロを使う方法
CV_Assert
マクロを用いることで指定した条件式を満たさない場合にエラーメッセージを表示させることができます.詳細は公式ドキュメントを参照ください.
以下にCV_Assert
マクロの使用例を記述します.
int i = -1;
CV_Assert(i >= 0);
この例ではCV_Assert
呼び出し時にi >= 0
という条件を満たさないので
CV_Assert
マクロ内でcv::error
関数が呼ばれ,以下のようなエラーメッセージが表示されます.
OpenCV Error: Assertion failed (i >= 0) in hoge, file fuga.cpp, line 8
このエラーメッセージは以下のような意味を表しています.
メッセージ | 意味 |
---|---|
Assertion failed |
エラーコードに対応した文字列. この例ではアサーションエラー発生(StsAssert)に対応した文字列. |
(i >= 0) |
エラーとなった理由. この例では(i >= 0)という条件式を満たしていないため. |
in hoge |
エラー発生関数. この例ではhoge関数内でエラーが発生したことを表す. |
file fuga.cpp, line 8 |
エラー発生したファイル名と行番号. この例ではfuga.cppの8行目でエラーが発生したことを表す. |
CV_Assertマクロを使う方法の注意点
CV_Error
マクロを使ったエラーメッセージ表示では開発者がエラーコードを指定することができますが,CV_Assert
マクロでは内部的にエラーコードがcv::Error::StsAssert
となります.
(アサーションが発生するので当然と言えば当然ですが)
例外処理
OpenCVで提供されるcv::Exception
を用いることで例外処理を容易に記述することができます.
この関数の第一引数はエラーコード,第二引数はエラーメッセージの文字列,
第三引数は関数名,第四引数はファイル名,第五引数は行数です.詳細は公式ドキュメントを参照ください.
サンプルコード
サンプルコード(CV_Errorマクロ)
CV_Error
マクロに対してエラー内容に応じたエラーコードを指定し,
エラーメッセージ表示を行うサンプルコードです.
#include <opencv2/core.hpp> // coreモジュールにて定義
#include <iostream>
// 1チャンネルの画像しか受け付けない関数
void testFunc(cv::InputArray src_)
{
cv::Mat src = src_.getMat();
// 入力画像のチャンネル数が1以外の場合にエラーとする
// ここではエラーコードとしてcv::Error::BadNumChannelsを指定
if (src.channels() != 1)
CV_Error(cv::Error::BadNumChannels, "Unsupported channels count");
}
int main(int argc, const char* argv[])
{
// 3チャンネルの画像データを生成する
cv::Mat img(cv::Size(512, 512), CV_8UC3, cv::Scalar(0, 0, 255));
// testFunc関数を実行する
testFunc(img);
return 0;
}
このサンプルでは,1チャンネルの画像しか受け付けないtestFunc関数に対して
3チャンネルの画像を入力(=無効なチャンネル数を指定)した例のため,
CV_Error
マクロの第一引数(エラーコード)にcv::Error::BadNumChannels
を指定しています.
また,このサンプルを実行すると以下のようなエラーメッセージが表示されます.
このとき,エラーメッセージにはエラー内容だけでなくエラーが起きた関数名,ファイル名,行番号も表示されます.
OpenCV Error: Bad number of channels (Unsupported channels count) in testFunc, file error_test.cpp, line 12
サンプルコード(cv::Exception)
cv::Exception
にエラーコード,エラーメッセージ,関数名,ファイル名,行番号を指定し,
例外をキャッチした際にエラーメッセージ表示を行うサンプルコードです.
#include <opencv2/core.hpp> // coreモジュールにて定義
#include <iostream>
// 常にExceptionを投げる関数
void testFunc2(void)
{
// エラーコード,エラーメッセージ,関数名,
// ファイル名,行番号を指定してExceptionを投げる
throw cv::Exception(cv::Error::StsError,
"Unspecified error", CV_Func, __FILE__, __LINE__);
}
int main(int argc, const char* argv[])
{
try
{
// testFunc2関数を実行する
testFunc2();
}
catch (cv::Exception& e)
{
// 例外をキャッチしたらエラーメッセージを表示
std::cerr << e.what() << std::endl;
return -1;
}
return 0;
}
このサンプルを実行すると以下のようなエラーメッセージが表示されます.
このとき,エラーメッセージにはcv::Exceptionに指定したエラーメッセージ,
関数名,ファイル名,行番号が表示されます.
exception_test.cpp:10: error: (-2) Unspecified error in function testFunc2
おわりに
- OpenCVが定義するエラーコード,エラーメッセージの意味を理解してデバッグに活用しましょう
- OpenCVが提供する
CV_Error
マクロ,cv::Exception
を活用して適切なエラー処理,例外処理を実装しましょう
備考
筆者は以下の環境で動作確認しました.
- OpenCV 3.0.0
- Windows 8.1 Pro(64bit)
- Visual Studio 2013 Update5