-
-
Notifications
You must be signed in to change notification settings - Fork 56.5k
imgproc: calcHist generates miss counts pixel in release mode #15597
Description
System information (version)
- OpenCV => recent 3.4 ( c209677 )
- Operating System / Platform => Jetson Xavier, Jetson TX1, Jetson TX2, Jetson Nano, Firefly RK3399, ODROID-N2 (All Aarch64)
- Compiler => GCC 7.4.0
Abstract
- Another rounding error causes missing count in histogram
- This leads to test failure in xphoto module
Detailed description
The original issue comes from opencv_test_xphoto which is contrib module.
$ ./build/bin/opencv_test_xphoto --gtest_filter=*float_min_value
CTEST_FULL_OUTPUT
OpenCV version: 3.4.8-pre
OpenCV VCS version: 3.4.7-189-gc209677
Build type: Release
Compiler: /usr/bin/c++ (ver 7.4.0)
Parallel framework: pthreads
CPU features: NEON FP16
OpenCL is disabled
TEST: Skip tests with tags: 'mem_6gb', 'verylong'
Note: Google Test filter = *float_min_value
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from xphoto_simplecolorbalance
[ RUN ] xphoto_simplecolorbalance.float_min_value
/home/nvidia/opencv_contrib/modules/xphoto/test/simple_color_balance.cpp:197: Failure
The difference between minDst and newMin is 65468.87890625, which exceeds 65536*1e-4, where
minDst evaluates to -65468.87890625,
newMin evaluates to 0, and
65536*1e-4 evaluates to 6.5536000000000003.
[ FAILED ] xphoto_simplecolorbalance.float_min_value (1 ms)
[----------] 1 test from xphoto_simplecolorbalance (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (2 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] xphoto_simplecolorbalance.float_min_value
1 FAILED TEST
Not only float_min_value but total 3 tests fail.
[==========] 15 tests from 4 test cases ran. (1171 ms total)
[ PASSED ] 12 tests.
[ FAILED ] 3 tests, listed below:
[ FAILED ] xphoto_simplecolorbalance.float_min_value
[ FAILED ] xphoto_simplecolorbalance.float_p
[ FAILED ] xphoto_simplecolorbalance.float_c3
Steps to reproduce
These tests were added by opencv/opencv_contrib#2263
opencv/opencv_contrib#2263 also modified balanceWhiteSimple to use calcHist
In calcHist, it's computing the bin number here
opencv/modules/imgproc/src/histogram.cpp
Lines 251 to 253 in c209677
| int idx = cvFloor(*p0*a + b); | |
| if( (unsigned)idx < (unsigned)sz ) | |
| ((int*)H)[idx]++; |
In Release mode + Aarch64, this multiply and add operations are tend to be compiled as fmadd instruction
fmadd d0, d2, d0, d1
And this fmadd causes digit loss when the result becomes near to zero.
Following text shows that *p0*a+b is supposed to become 0.
(gdb) p *p0
$22 = 24000
(gdb) p a
$23 = 0.098610877049377668
(gdb) p b
$24 = -2366.6610491850643
(gdb) p *p0*a+b
$25 = 0
when the actual computation result becomes negative, not 0.
(gdb) p value
$20 = -2.2115642650533118e-13
Since we are doing cvFloor on negative value, the result becomes -1 and it won't pass the following if condition
opencv/modules/imgproc/src/histogram.cpp
Lines 252 to 253 in c209677
| if( (unsigned)idx < (unsigned)sz ) | |
| ((int*)H)[idx]++; |
This will lead to missing count of pixel.
The cause is same as #6536 , it's another headache rounding error.
Now, my best solution I can imagine is to apply round-to-zero instead of cvFloor inside calcHist
Another solution is to modify the parameter of xphoto so the test passes.
I just like to know which way to fix this issue, or if there are any already implemented round-to-zero function in OpenCV (AFAIK, there are only cvFloor, cvRuond and cvCeil).