Skip to content

imgproc: calcHist generates miss counts pixel in release mode #15597

@tomoaki0705

Description

@tomoaki0705
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

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

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).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions