Issue 1:
System information (version)

OpenCV => 3.4 branch ( 0101fa7 )

Operating System / Platform => Windows 10 64bit

Compiler => Visual Studio 2015

CUDA => 10.0

Summarized description

The opencv_test_imgproc passes, but when I ran it from target RUN_TESTS, it says Segfault

Start 9: opencv_test_imgproc
1/1 Test #9: opencv_test_imgproc ..............***Exception: SegFault137.81 sec

I ran opencv_test_imgproc separately, but all the test passes (!)

To reproduce what gtest was seeing, I need to ran it in Debug mode

When running opencv_test_imgproc with "Start debug" on Visual Studio 2015, the test passed but at the end, it did cause an Segfault at ocl.cpp

opencv/modules/core/src/ocl.cpp

Lines 4322 to 4329
in
0101fa7

void _releaseBufferEntry(const BufferEntry& entry)

{

CV_Assert(entry.capacity_ != 0);

CV_Assert(entry.clBuffer_ != NULL);

LOG_BUFFER_POOL("OpenCL release buffer: %p, %lld (0x%llx) bytes\n",

entry.clBuffer_, (long long)entry.capacity_, (long long)entry.capacity_);

CV_OCL_DBG_CHECK(clReleaseMemObject(entry.clBuffer_));

}

Detailed description

I narrowed down the test case, and the test case was from OCL_ImgProc/CvtColor8u32f

Furthermore, it was related to test of either HSV/Lab/Luv conversion.

Also, although I put a break point at where it causes Segfault, it doesn't reproduce the situation.

I have to exit from the main routine call and it was happening after that exit call. Mysterious...

After watching the source code, I realized that some of the static UMat was used in a wrong scope, such like here

opencv/modules/imgproc/src/color_hsv.cpp

Lines 1483 to 1486
in
0101fa7

{

static UMat sdiv_data;

static UMat hdiv_data180;

static UMat hdiv_data256;

These UMat were passed as a parameter of the OpenCL kernel but the scope was closed before it was actually used

opencv/modules/imgproc/src/color_hsv.cpp

Lines 1516 to 1521
in
0101fa7

h.setArg(ocl::KernelArg::PtrReadOnly(sdiv_data));

h.setArg(hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :

ocl::KernelArg::PtrReadOnly(hdiv_data180));

}

return h.run();

Looking back the history, it seems that color convert was splitted in early 2018, and before the split, the scope was aligned with the actual use.

I moved the UMat declarations and also, I removed the static

Now the test passed without Segfault

Steps to reproduce

Build under environment explained above.

Run with CUDA 10.0 and run the OpenCL kernel on dGPU

OPENCV_OPENCL_DEVICE=:dgpu opencv_test_imgproc --gtest_filter=OCL_ImgProc/CvtColor8u32f*

Also, there I'm not sure why this doesn't happen on CPU and igpu on my laptop.

Still, the scope difference seems bad, so I think it has meaning to fix the scope.

Issue 2:
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).