確認した環境
- OpenCV4.1.1
- Windows10
- Visual Studio Community 2019 Version 16.3.7
はじめに
OpenCV には汎用的な幾何変換を行う cv::remap 関数があります。
この関数では変換情報を表す cv::Mat 型のマップ情報を使用します。
マップ情報は大きく分けて浮動小数点マップと固定小数点マップの2種類があります。
cv::remap のドキュメントを読むと
浮動小数点マップより固定小数点マップの方が処理速度が速いとの記述があります。
しかし固定小数点マップは気になる部分がありました。
それが補間係数テーブルです。
cv::remap のドキュメントを引用します。
map1 contains pairs (cvFloor(x), cvFloor(y)) and map2 contains indices in a table of interpolation coefficients.
map2 が補間係数テーブルのインデックスを表すとありますが、 補間係数テーブルは一体どこにあるのでしょうか。 この関数を使う分には知らなくても問題ないことなのかもしれませんが、 ライブラリ上のどこかに既に存在する固定の値なのか、それともマップや入力画像によって変わるために毎回生成される値なのか、 どういう仕組みか気になったので調べました。
結論
先に結論を載せます。
- 補間係数テーブルはマップや入力画像によって変わる値ではない。
- 補間係数テーブルは補間方法によって異なる。
- 一部の補間方法では補間係数テーブルがあらかじめ(プログラム開始時に?)作成される。
- その補間方法は INTER_LINEAR, INTER_CUBIC, INTER_LANCZOS4 の3種類。
- 他の補間方法での補間係数テーブル作成タイミングは、その補間方法による cv::remap の初回実行時だと思われる。
私が調べた限りではこのようだと判断したのですが、間違っていたら申し訳ございません。 教えていただけると助かります。
調べた方法
調べ方は OpenCV のソースコードを読みました。
cv::remap の中身が書いてある imgwarp.cpp を読みますが、
ただ読むのも辛いので OpenCV に含まれるサンプルコード Remap_Demo.cpp を Visual Studio でデバッグビルドしてステップ実行しながら追いました。
そのような方法で処理を追っていくとremap関数内で initInterTab2D という関数を呼び出すことが分かります。
initInterTab2D 関数内で補間係数テーブルを作成しているようですが、
static bool inittab[INTER_MAX+1]
というスタティック変数によって作成済みかどうかを管理しています。
そしてこの initInterTab2D 関数のすぐ下には以下のコードがありました。
引用します。
#ifndef __MINGW32__ static bool initAllInterTab2D() { return initInterTab2D( INTER_LINEAR, false ) && initInterTab2D( INTER_LINEAR, true ) && initInterTab2D( INTER_CUBIC, false ) && initInterTab2D( INTER_CUBIC, true ) && initInterTab2D( INTER_LANCZOS4, false ) && initInterTab2D( INTER_LANCZOS4, true ); } static volatile bool doInitAllInterTab2D = initAllInterTab2D(); #endif
これによって、INTER_LINEAR, INTER_CUBIC, INTER_LANCZOS4 の3種類の補間係数テーブルは cv::remap を呼び出す前に作成されるようです。 試しに initAllInterTab2D 関数と main 関数の一行目にブレークポイントを付けてデバッグ開始したところ、initAllInterTab2D 関数のブレークポイントが先に引っかかりました。
課題
補間係数テーブルの在り処と生成タイミングについて書きましたが、 補間係数テーブルが具体的にどういうデータなのかというのまでは触れませんでしたので、 そのことについて書きたいです。