11
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 21

GaussianBlur関数でほぼ空っぽの画像が生成されるバグ

Last updated at Posted at 2021-12-20

#TL;DR
オーバーフロー

#はじめに

テストFAIL時のログ
[  FAILED  ] 73 tests, listed below:
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/388, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(9x9), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/393, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(11x11), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/396, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(11x11), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/397, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(11x11), BORDER_CONSTANT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/413, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(15x15), BORDER_CONSTANT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/417, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(17x17), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/434, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(21x21), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/446, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(23x23), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/453, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(25x25), BORDER_CONSTANT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/456, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(27x27), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/458, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(27x27), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/476, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(31x31), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/505, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(9x9), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/511, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(9x9), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/537, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(17x17), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/538, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(17x17), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/566, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(23x23), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/569, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(25x25), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/575, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(25x25), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/591, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(29x29), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/593, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(31x31), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/594, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(3), KSize(31x31), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/639, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(11x11), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/648, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(15x15), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/649, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(15x15), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/652, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(15x15), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/658, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(17x17), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/664, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(19x19), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/667, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(19x19), BORDER_REPLICATE, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/703, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(4), KSize(27x27), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1817, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(7x7), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1819, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(7x7), BORDER_REPLICATE, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1826, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(9x9), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1827, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(9x9), BORDER_REPLICATE, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1837, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(11x11), BORDER_CONSTANT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1843, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(13x13), BORDER_REPLICATE, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1864, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(19x19), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1872, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(21x21), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1874, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(21x21), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1878, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(21x21), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1884, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(23x23), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1892, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(25x25), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1898, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(27x27), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1902, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(27x27), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1905, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(29x29), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1916, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(1), KSize(31x31), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1945, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(9x9), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1952, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(11x11), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1957, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(11x11), BORDER_CONSTANT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1960, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(13x13), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1965, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(13x13), BORDER_CONSTANT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1969, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(15x15), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1977, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(17x17), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1978, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(17x17), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/1982, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(17x17), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2008, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(25x25), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2023, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(27x27), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2024, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(29x29), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2032, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(31x31), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2038, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(3), KSize(31x31), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2073, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(11x11), BORDER_REFLECT101, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2086, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(13x13), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2088, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(15x15), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2096, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(17x17), BORDER_REFLECT101, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2108, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(19x19), BORDER_CONSTANT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2111, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(19x19), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2114, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(21x21), BORDER_REPLICATE, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2118, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(21x21), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2123, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(23x23), BORDER_REPLICATE, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2131, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(25x25), BORDER_REPLICATE, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2135, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(25x25), BORDER_REFLECT, sub matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2142, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(27x27), BORDER_REFLECT, whole matrix)
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/2153, where GetParam() = (NVIDIA Tegra X1, 113x113, CV_16U, Channels(4), KSize(31x31), BORDER_REFLECT101, sub matrix)
73 FAILED TESTS
  • テストはopencv_test_cudafiltersでしたが、後述の通り、imgprocモジュールが引き金です

#再現性
コードに飛び込む前に状況を整理してみましょう
##CV_16Uに限る

  • テストのメッセージを見るに、CV_16Uというパラメータが見えます
  • GaussianBlur関数に渡す画像の要素がCV_8UCV_32Fの場合はテストはPASSするのですが、CV_16UのときだけFAILします
[  FAILED  ] CUDA_Filters/GaussianBlur.Accuracy/388, where GetParam() = (NVIDIA Tegra X1, 128x128, CV_16U, Channels(1), KSize(9x9), BORDER_CONSTANT, whole matrix)
テスト名の後ろ、GetParamがついている場合は同じ関数を複数のパラメータでチェックする。ここにCV_16U__________^^^^^^
他のパラメータは変化するが、このCV_16Uだけ変化しない

##deterministicな再現性

  • 同じテストを何回実行しても決まって同じテストがコケます
$ for i in `seq 1 3 ` ; do ./bin/opencv_test_cudafilters --gtest_filter=*Gaussian* --gtest_param_filter=*CV_16U* | grep "FAILED TESTS" ; done
67 FAILED TESTS
67 FAILED TESTS
67 FAILED TESTS
  • 一方で、--gtest_repeat=3オプションを利用すると、テストがFAILする数が変わる
$ ./bin/opencv_test_cudafilters --gtest_filter=*Gaussian* --gtest_param_filter=*CV_16U* --gtest_repeat=3 | grep "FAILED TESTS"
67 FAILED TESTS
64 FAILED TESTS
77 FAILED TESTS
  • このコケ方が変化することの意味は
    • bashfor文で複数回実行した場合は固定のシードで実行されるので、deterministicな結果が得られる
    • 一方で、gtest_repeatオプションをつけた場合、シードの初期化が1度だけ行われたあと同じ乱数系列が引き続き使われる
    • そのため、生成される乱数は微妙に違ってくる
  • つまり、微妙なパラメータの違いでテストがコケることを意味している

#画像
##入力画像
src_emphasized[1].png
##出力画像GPU版
dst_gpu_emphasized[1].png
##出力画像CPU版
dst_cpu_emphasized[1].png

  • というわけでテストはcudafiltersモジュールのテストがコケてるのですが、当該テストは
    • CUDA版のガウシアンフィルタの結果と
    • CPU版のガウシアンフィルタの結果を
    • それぞれ比較し、結果が一致しなければFAIL
    • という仕組みです
  • 今回のFAILは、どうやらCPU版が予期せぬ結果を返したためにFAILとなっている模様です。
  • CPU版の実装はimgprocモジュール内にあります

#bit-exactなGaussianBlur

  • 奇しくも2日目の記事でもGaussianBlur関数に触れてますが、ここではもう少しGaussianBlur関数を掘ってみましょう

##関数の仕組み

.cpp
void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType)
  • このように、GaussianBlur関数には
    • 入力画像
    • 出力用バッファ
    • 平滑化カーネルの大きさ
    • 平滑化具合を示すシグマ (x2)
    • 境界線の処理を指定するフラグ
    • を指定します
  • sigma1は横方向への平滑化度合い、sigma2は縦方向への平滑化度合いを指定します
    • sigmaは値が大きい方が平滑化の度合いが強くなり、小さい方が平滑化の効果は小さくなる1
    • 現状テストコードからはsigma2は無罪で、sigma1だけが引き金のようです。
  • 内部では、このsigmaの値をもとに、カーネル(畳み込み積分される係数)が作られます。テストケースでは7x7のフィルタのようです。
    • 縦横独立して計算するため、7つのパラメータが指定されます。
    • また、OpenCVは3.3ぐらいから2 bit-exactなGaussianBlurが実装されました
    • なので、7つのパラメータはfloatではなく、内部では32bit符号なし整数もしくは16bit符号なし整数として表現されます
  • カーネルを作るところを見てみましょう。
.cpp
    Mat kx, ky;
    createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
  • ここではkxが横方向への平滑化を行うカーネルです
  • 出てきたkxの中身を見てみましょう
0.00000000
3.38778060e-21
7.62910940e-06
0.999984741
7.62910940e-06
3.38778060e-21
0.00000000
  • 指数表示なのでわかりにくいですが、小数点を揃えると、こんな感じです。
0.00000000000000000000000000000
0.00000000000000000000338778060
0.00000762910940
0.999984741
0.00000762910940
0.00000000000000000000338778060
0.00000000000000000000000000000
  • 試しに棒グラフでプロットしてみるとこんな感じです。
    coeff.png

  • 何ということでしょう。人生で一番不毛なグラフを描いてしまった気もします。

  • なお、対数スケールで表示すればちゃんと正規分布の形をしてることがかろうじてわかります
    coeff_log.png

  • とは言え、1番目と2番目の係数が100,000倍(10万倍)違います。

    • そして内部的にはCV_16Uで、表せる最小の桁数は1/65536です。
    • 実はこのあたりがバグのキモではないかと薄々このあたりで筆者は思い始めました。
  • この値は、CV_16Uのケースなので、内部的には固定小数点として以下の形式で保持されます

0x00000000
0x00000000
0x00000000
0x00010000
0x00000000
0x00000000
0x00000000
  • 状況から考えるに、CV_16Uのbit幅で0x10000が発生したときにだけエラーになってるのでは?とプンプンにおってきます。

##実際にバグのトリガとなるコード

  • そこから更に進むと、SIMD最適化されたコードに到着します
.cpp
v_mul_expand(vx_load(src + pre_shift * cn), vx_setall_u16((uint16_t) *((uint32_t*)(m + pre_shift))), v_res0, v_res1);
  • ここの内部で使われているvx_setall_u16は前述のパラメータをロードして、ベクトルレジスタの全要素に設定するintrinsicです
  • ここで、この行をよく読み解くと
.cpp
vx_setall_u16((uint16_t) *((uint32_t*)(m + pre_shift)))
//             ^            ^          ^____メモリアドレス
//             |            |_______________32bit符号なし整数としてロード
//             |____________________________16bit符号なし整数に変換(!)
  • という具合に
    1. メモリアドレスを計算
    2. 32bit符号なし整数としてロード
    3. 16bit符号なし整数に変換(←イマココ
    4. ベクトルレジスタの全要素に同じ値を設定
  • ということをしています。
  • ところで32bit符号なし整数、0x10000を16bit符号なし整数に変換すると結果はいくつでしょう?

##原因中の原因

  • というわけで、バグとしては「オーバーフローが発生していた」のが原因です

##sigma2が無罪なわけ

.cpp
v_uint32 v_mul = vx_setall_u32(*((uint32_t*)(m + pre_shift)));
  • 同様に縦方向にガウシアンフィルタをかける実装ではご覧の通り、符号なし32bit整数として処理されております

#まとめ

  • GaussianBlur関数の画像がCV_16U型の場合でsigma1に0.2以下の値3を渡すと、空っぽな画像が生成されます
  • 原因はオーバーフロー

##再現バージョン

  • 3.4系列の一部 (3.4.13-3.4.16まで。次期リリース予定の3.4.17でFIX)
  • 4.5系列の一部 (4.5.1-4.5.4まで。次期リリース予定の4.5.5でFIX)
  1. 初稿ではsigmaの取る範囲は[0:1]と書いたが、誤りだった。1以上の値も取れる。

  2. (うろ覚え)

  3. 厳密には0.2を超えても再現する。0.201ちょっと。計算の結果、floatなら突出したインパルス関数のような形になるのですが、符号なし16bit整数で表されてるため、結果がオーバーフローします

11
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
11
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?