CUDA を無効にして、次のように Jetson TX2 で OpenCV_Extra を使用して OpenCV 3.3.1 をビルドしました。
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_PNG=OFF -DBUILD_TIFF=OFF -DBUILD_TBB=OFF -DBUILD_JPEG=OFF -DBUILD_JASPER=OFF -DBUILD_ZLIB=OFF -DBUILD_EXAMPLES=ON -DBUILD_opencv_java=OFF -DBUILD_opencv_python2=ON -DBUILD_opencv_python3=ON -DENABLE_PRECOMPILED_HEADERS=OFF -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DWITH_OPENMP=OFF -DWITH_FFMPEG=ON -DWITH_GSTREAMER=OFF -DWITH_GSTREAMER_0_10=OFF -DWITH_GTK=ON -DWITH_VTK=OFF -DWITH_TBB=ON -DWITH_1394=OFF -DWITH_OPENEXR=OFF -DINSTALL_C_EXAMPLES=ON -DINSTALL_TESTS=ON -DCPACK_GENERATOR_DEB=ON -DOPENCV_TEST_DATA_PATH=../opencv_extra/testdata ../opencv
OpenCV テスト スクリプトを実行し、次のような「Calib3d_Affine3f.accuracy」と「match_bestOf2Nearest.bestOf2Nearest」テストで 2 つのテスト エラーが見つかりました。
[opencv_test_calib3d] RUN : /usr/bin/opencv_test_calib3d --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:opencv_test_calib3d.xml
[opencv_test_calib3d] CTEST_FULL_OUTPUT
[opencv_test_calib3d] OpenCV version: 3.3.1
[opencv_test_calib3d] OpenCV VCS version: 3.3.1
[opencv_test_calib3d] Build type: release
[opencv_test_calib3d] Parallel framework: tbb
[opencv_test_calib3d] CPU features: neon fp16
[opencv_test_calib3d] [ RUN ] Calib3d_Affine3f.accuracy
[opencv_test_calib3d] /home/nvidia/build-opencv/opencv/modules/calib3d/test/test_affine3.cpp:57: Failure
[opencv_test_calib3d] Expected: 0
[opencv_test_calib3d] To be equal to: cvtest::norm(cv::Mat(affine.matrix, false).colRange(0, 3).rowRange(0, 3) != expected, cv::NORM_L2)
[opencv_test_calib3d] Which is: 441.673
[opencv_test_calib3d] [ FAILED ] Calib3d_Affine3f.accuracy (0 ms)
[opencv_perf_stitching] RUN : /usr/bin/opencv_perf_stitching --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:opencv_perf_stitching.xml
[opencv_perf_stitching] Time compensation is 0
[opencv_perf_stitching] CTEST_FULL_OUTPUT
[opencv_perf_stitching] OpenCV version: 3.3.1
[opencv_perf_stitching] OpenCV VCS version: 3.3.1
[opencv_perf_stitching] Build type: release
[opencv_perf_stitching] Parallel framework: tbb
[opencv_perf_stitching] CPU features: neon fp16
[opencv_perf_stitching] [----------] 1 test from match_bestOf2Nearest
[opencv_perf_stitching] [ RUN ] match_bestOf2Nearest.bestOf2Nearest/0
[opencv_perf_stitching] Expected:
[opencv_perf_stitching] [0.9970975582816909, 0.01136054503288174;
[opencv_perf_stitching] -0.002557125266879237, 1.02781673911756;
[opencv_perf_stitching] 0.0002463026627945361, -1.679576661348132e-05]
[opencv_perf_stitching] Actual:
[opencv_perf_stitching] [0.9986402872172184, -0.01796581492545124;
[opencv_perf_stitching] -0.00230781842425846, 1.031312571169278;
[opencv_perf_stitching] 0.0002375978666932171, 9.189439617496881e-05]
[opencv_perf_stitching] /home/nvidia/build-opencv/opencv/modules/ts/src/ts_perf.cpp:571: Failure
[opencv_perf_stitching] Failed
[opencv_perf_stitching] Difference (=0.029326359958332979) between argument1 "R" and expected value is greater than 0.014999999999999999
[opencv_perf_stitching] params = "orb"
[opencv_perf_stitching] termination reason: reached maximum number of iterations
[opencv_perf_stitching] bytesIn = 96896
[opencv_perf_stitching] bytesOut = 0
[opencv_perf_stitching] samples = 1
[opencv_perf_stitching] outliers = 0
[opencv_perf_stitching] frequency = 1000000000
[opencv_perf_stitching] min = 306334005 = 306.33ms
[opencv_perf_stitching] median = 306334005 = 306.33ms
[opencv_perf_stitching] gmean = 306334005 = 306.33ms
[opencv_perf_stitching] gstddev = 0.00000000 = 0.00ms for 97% dispersion interval
[opencv_perf_stitching] mean = 306334005 = 306.33ms
[opencv_perf_stitching] stddev = 0 = 0.00ms
[opencv_perf_stitching] [ FAILED ] match_bestOf2Nearest.bestOf2Nearest/0, where GetParam() = "orb" (577 ms)
[opencv_perf_stitching] [----------] 1 test from match_bestOf2Nearest (577 ms total)
Ubuntu 16.04 ベースのイメージと Ubuntu 18.04 ベースのイメージの両方を異なる GCC バージョンで試しました。そして、以下は私の発見の要約です:
ツールチェーンが gcc-7 に基づいている場合は常に、「Calib3d_Affine3f.accuracy」での OpenCV テストの失敗が、異なるイメージの異なるプラットフォームで観察されました。また、どのプラットフォームとイメージの組み合わせでも、gcc < 7 (つまり、gcc-6.4.0 のようなバージョン 7 より前) が使用されている場合、このテストは常にパスします。
「match_bestOf2Nearest.bestOf2Nearest」での OpenCV テストの失敗は、使用されているイメージと gcc のバージョンに関係なく、継続的に観察されました。
私の観察によると、「Calib3d_Affine3f.accuracy」テストでの失敗は、テスト スクリプトが期待値と実際の値を等号 (==) で比較するためであり、これは正確な値を比較するためのものであり、浮動小数点の変動を想定していません。 -異なるコンパイラを使用した異なるプラットフォームでのポイント操作。gcc < 7 では浮動小数点比較テストに合格しますが、gcc-7 では 1e-17 のように 2 つの浮動小数点値がわずかに異なるため失敗します。
質問:
- IEEE 浮動小数点仕様は、精度に関してアーキテクチャ全体で義務付けられていますか?
- OpenCV テスト スクリプトの比較方法 (つまり、許容できるマージンと比較するのではなく、正確な値を比較する) は、IEEE 仕様による浮動小数点値の典型的なものでしょうか?
- gcc-7 を使用する場合と gcc < 7 を使用する場合で、浮動小数点精度の動作が異なるのはなぜですか?
- gcc-7 を使用してテストをパスし、さらに進めるにはどうすればよいですか?
「match_bestOf2Nearest.bestOf2Nearest」の 2 番目の失敗ケースは、一部の OpenCV 関数での浮動小数点演算の精度処理にも関連しています。OpenCV 関数が CV_32F と CV_64F の間の値を内部的にキャストすることがあることがわかりました。CV_32F 形式で精度を処理するのに十分であると仮定すると、これは問題になりません。この場合、テスト スクリプトは、期待値と実際の値をイプシロンのような許容範囲で比較します (正確な値の等価性テストの代わりに)。関数で提供されるランダム シードによっては、テストが失敗することが観察されます。これは、定義済みのイプシロンが十分に大きくないか、CPU の浮動小数点演算の変動性が OpenCV テスト スクリプトで想定されているものよりも大きいことを意味します。
質問:
- Jetson-TX2 の CPU アーキテクチャ固有の特性に関連するものはありますか? それは何でしょう?
- この問題を解決するにはどうすればよいですか?
あなたの知恵を私と共有できれば素晴らしいことです!