Test ExposureCompensate.SimilarityThreshold fails on Windows 10 in master branch

System information (version)
  • OpenCV => 4.5.1-pre (git 46e275d )
  • Operating System / Platform => Windows 10 x64
  • Compiler => Visual Studio 2019 Community Editon x64, Ninja
Detailed description
C:\Slave\workspace\nightly-master\windows10\opencv\modules\stitching\test\test_exposure_compensate.cpp:66
Expected: (psnr_similarity_mask) > (300), actual: 38.0114 vs 300
Issue submission checklist
  • I report the issue, it’s not a question
  • I checked the problem with documentation, FAQ, open issues,
    answers.opencv.org, Stack Overflow, etc and have not found solution

  • I updated to latest OpenCV version and the issue is still there
  • There is reproducer code and related data files: videos, images, onnx, etc

3 thoughts on “Test ExposureCompensate.SimilarityThreshold fails on Windows 10 in master branch

  1. I faced this issues on following platforms

    • Failed
      • firefly-rk3399 (Mali-T860 OpenCL 1.2)
      • odroid-c4 (Mali-G31 OpenCL 2.0)
      • odroid-n2-plus (Mali-G52 OpenCL 2.0)
      • odroid-xu4 (Mali-T628 OpenCL 1.2)
      • tinkerboard (Mali-T760 OpenCL 1.2)
      • rock-pi-4c (Mali-T860 OpenCL 1.2)
    • Passes
      • jetson-nano
      • jetson-tx1
      • jetson-tx2
      • jetson-xavier
      • jetson-xavier-nx
      • le-potato
      • raspberry-pi-3
      • raspberry-pi-4
    • The platform that failed has an Arm Mali as a GPU and has an OpenCL capability.
    • The platform that passed doesn’t have an OpenCL capability, so CPU version implementation will be kicked. (Jetsons have nice GPUs, but they don’t have OpenCL capability)
    • Also, on the failed platforms, if I set environmental variable OPENCV_OPENCL_DEVICES=disabled, then CPU version is kicked and the test passes.
    • Now, I narrowed down the behavior of the test, and the difference comes from here.
    bitwise_and(intersect, similarity, intersect);
    • This bitwise_and function does nothing when OpenCL is enabled.
    • In another way, if I temporarily disable OpenCL just for this bitwise_and function, the test passes
    +bool flag = cv::ocl::useOpenCL();
    +cv::ocl::setUseOpenCL(false);
     bitwise_and(intersect, similarity, intersect);
    +cv::ocl::setUseOpenCL(flag);
    
    • Test result
    [       OK ] ExposureCompensate.SimilarityThreshold (93847 ms)
    [----------] 1 test from ExposureCompensate (93848 ms total)
    
    [----------] Global test environment tear-down
    [==========] 1 test from 1 test case ran. (93849 ms total)
    [  PASSED  ] 1 test.
    
    • This passed similarity is UMat and intersect is Mat_<uchar> with size of 32×32 and they contain either 0 or 0xff
    • Though similarity sometime has 0, the and operation does nothing, and 0xff is kept. That’s where the behavior differs.
    • Additionally, I tried the same test in opencv_test_core by kicking OCL_Arithm/Bitwise_and.Mat/0 (8UC1) and fixing the size as 32×32, but the test passed. So, there’s something under the hood which triggers this bitwise_and to do nothing.
  2. Also, this temporally fix putting in here worked.

    - bitwise_and(intersect, similarity, intersect);
    + bitwise_and(intersect.clone(), similarity, intersect);
    

    The combination is still not determined yet, but in this case, this binary operation takes Mat, UMat and written back to Mat.
    The Mat are processed in-place and that seems one of the cause.
    Now, making a copy every time here is kind of a dirty fix, and may be something should be fixed in memory management side.

  3. @tomoaki0705 Thank you for investigation!

    bitwise_and(intersect, similarity, intersect);

    OpenCL kernels for operations with “in-place” src/dst buffers should be implemented with another kernels code. This is a bug to be fixed in core module.


    Workaround without .clone() (reduced performance impact):

    Mat_<uchar> intersect_updated;
    bitwise_and(intersect, similarity, intersect_updated);
    std::swap(intersect, intersect_updated);
    

    or

    bitwise_and(intersect, similarity.getMat(ACCESS_READ), intersect);