• P
    Merge pull request #22947 from chacha21:hasNonZero · 60b806f9
    Pierre Chatelier 提交于
    Added cv::hasNonZero() #22947 
    
    `cv::hasNonZero()` is semantically equivalent to (`cv::countNonZero()>0`) but stops parsing the image when a non-zero value is found, for a performance gain
    
    - [X] I agree to contribute to the project under Apache 2 License.
    - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
    - [X] The PR is proposed to the proper branch
    - [ ] There is a reference to the original bug report and related work
    - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
          Patch to opencv_extra has the same branch name.
    - [ ] The feature is well documented and sample code can be built with the project CMake
    
    This pull request might be refused, but I submit it to know if further work is needed or if I just stop working on it.
    The idea is only a performance gain vs `countNonZero()>0` at the cost of more code.
    
    Reasons why it might be refused :
    
    - this is just more code
    - the execution time is "unfair"/"unpredictable" since it depends on the position of the first non-zero value
    - the user must be aware that default search is from first row/col to last row/col and has no way to customize that, even if his use case lets him know where a non zero could be found
    - the PR in its current state is using, for the ocl implementation, a mere `countNonZero()>0` ; there is not much sense in trying to break early the ocl kernel call when non-zero is encountered. So the ocl implementation does not bring any improvement.
    - there is no IPP function that can help (`countNonZero()` is based in `ippCountInRange`)
    - the PR in its current state might be slower than a call to `countNonZero()>0` in some cases (see "challenges" below)
    
    Reasons why it might be accepted :
    
    - the performance gain is huge on average, if we consider that "on average" means "non zero in the middle of the image"
    - the "missing" IPP implementation is replaced by an "Open-CV universal intrinsics" implementation
    - the PR in its current state is almost always faster than a call to `countNonZero()>0`, is only slightly slower in the worst cases, and not even for all matrices
    
    **Challenges**
    The worst case is either an all-zero matrix, or a non-zero at the very last position.  In such a case, the `hasNonZero()` implementation will parse the whole matrix like `countNonZero()` would do. But we expect the performance to be the same in this case. And `ippCountInRange` is hard to beat !
    There is also the case of very small matrices (<=32x32...) in 8b, where the SIMD can be hard to feed.
    
    For all cases but the worse, my custom `hasNonZero()` performs better than `ippCountInRange()`
    For the worst case, my custom `hasNonZero()` performs better than `ippCountInRange()` *except for large matrices of type CV_32S or CV_64F* (but surprisingly, not CV_32F).
    The difference is small, but it exists (and I don't understand why).
    For very small CV_8U matrices `ippCountInRange()` seems unbeatable.
    
    Here is the code that I use to check timings
    
    ```
    
      //test cv::hasNonZero() vs (cv::countNonZero()>0) for different matrices sizes, types, strides...
      {
        cv::setRNGSeed(1234);
        const std::vector<cv::Size> sizes = {{32, 32}, {64, 64}, {128, 128}, {320, 240}, {512, 512}, {640, 480}, {1024, 768}, {2048, 2048}, {1031, 1000}};
        const std::vector<int> types = {CV_8U, CV_16U, CV_32S, CV_32F, CV_64F};
        const size_t iterations = 1000;
        for(const cv::Size& size : sizes)
        {
          for(const int type : types)
          {
            for(int c = 0 ; c<2 ; ++c)
            {
              const bool continuous = !c;
              for(int i = 0 ; i<4 ; ++i)
              {
                cv::Mat m = continuous ? cv::Mat::zeros(size, type) : cv::Mat(cv::Mat::zeros(cv::Size(2*size.width, size.height), type), cv::Rect(cv::Point(0, 0), size));
                const bool nz = (i <= 2);
                const unsigned int nzOffsetRange = 10;
                const unsigned int nzOffset = cv::randu<unsigned int>()%nzOffsetRange;
                const cv::Point pos = 
                  (i == 0) ? cv::Point(nzOffset, 0) :
                  (i == 1) ? cv::Point(size.width/2-nzOffsetRange/2+nzOffset, size.height/2) :
                  (i == 2) ? cv::Point(size.width-1-nzOffset, size.height-1) :
                  cv::Point(0, 0);
                std::cout << "============================================================" << std::endl;
                std::cout << "size:" << size << "  type:" << type << "  continuous = " << (continuous ? "true" : "false") << "  iterations:" << iterations << "  nz=" << (nz ? "true" : "false");
                std::cout << "  pos=" << ((i == 0) ? "begin" : (i == 1) ? "middle" : (i == 2) ? "end" : "none");
                std::cout << std::endl;
                cv::Mat mask = cv::Mat::zeros(size, CV_8UC1);
                mask.at<unsigned char>(pos) = 0xFF;
                m.setTo(cv::Scalar::all(0));
                m.setTo(cv::Scalar::all(nz ? 1 : 0), mask);
                std::vector<bool> results;
                std::vector<double> timings;
    
                {
                  bool res = false;
                  auto ref = cv::getTickCount();
                  for(size_t k = 0 ; k<iterations ; ++k)
                    res = cv::hasNonZero(m);
                  auto now = cv::getTickCount();
                  const bool error = (res != nz);
                  if (error)
                    printf("!!ERROR!!\r\n");
                  results.push_back(res);
                  timings.push_back(1000.*(now-ref)/cv::getTickFrequency());
                }
                {
                  bool res = false;
                  auto ref = cv::getTickCount();
                  for(size_t k = 0 ; k<iterations ; ++k)
                    res = (cv::countNonZero(m)>0);
                  auto now = cv::getTickCount();
                  const bool error = (res != nz);
                  if (error)
                    printf("!!ERROR!!\r\n");
                  results.push_back(res);
                  timings.push_back(1000.*(now-ref)/cv::getTickFrequency());
                }
    
                const size_t bestTimingIndex = (std::min_element(timings.begin(), timings.end())-timings.begin());
                if ((bestTimingIndex != 0) || (std::find_if_not(results.begin(), results.end(), [&](bool r) {return (r == nz);}) != results.end()))
                {
                  std::cout << "cv::hasNonZero\t\t=>" << results[0] << ((results[0] != nz) ? "  ERROR" : "") << "   perf:" << timings[0] << "ms => " << (iterations/timings[0]*1000) << " im/s" << ((bestTimingIndex == 0) ? " * " : "") << std::endl;
                  std::cout << "cv::countNonZero\t=>" << results[1] << ((results[1] != nz) ? "  ERROR" : "") << "   perf:" << timings[1] << "ms => " << (iterations/timings[1]*1000) << " im/s" << ((bestTimingIndex == 1) ? " * " : "") << std::endl;
                }
              }
            }
          }
        }
      }
    
    ```
    
    Here is a report of this benchmark (it only reports timings when `cv::countNonZero()` is faster)
    My CPU is an Intel Core I7 4790 @ 3.60Ghz
    
    ```
    
    ============================================================
    size:[32 x 32]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    cv::hasNonZero          =>1   perf:0.353764ms => 2.82674e+06 im/s
    cv::countNonZero        =>1   perf:0.282044ms => 3.54555e+06 im/s *
    ============================================================
    size:[32 x 32]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    cv::hasNonZero          =>1   perf:0.610478ms => 1.63806e+06 im/s
    cv::countNonZero        =>1   perf:0.283182ms => 3.5313e+06 im/s *
    ============================================================
    size:[32 x 32]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    cv::hasNonZero          =>0   perf:0.630115ms => 1.58701e+06 im/s
    cv::countNonZero        =>0   perf:0.282044ms => 3.54555e+06 im/s *
    ============================================================
    size:[32 x 32]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    cv::hasNonZero          =>1   perf:0.607347ms => 1.64651e+06 im/s
    cv::countNonZero        =>1   perf:0.467037ms => 2.14116e+06 im/s *
    ============================================================
    size:[32 x 32]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    cv::hasNonZero          =>0   perf:0.618162ms => 1.6177e+06 im/s
    cv::countNonZero        =>0   perf:0.468175ms => 2.13595e+06 im/s *
    ============================================================
    size:[32 x 32]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[32 x 32]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[32 x 32]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[32 x 32]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[32 x 32]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[64 x 64]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[64 x 64]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[64 x 64]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[64 x 64]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[128 x 128]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[128 x 128]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[128 x 128]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[128 x 128]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[320 x 240]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[320 x 240]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[320 x 240]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[320 x 240]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[512 x 512]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[512 x 512]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[512 x 512]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[512 x 512]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[640 x 480]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[640 x 480]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[640 x 480]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[640 x 480]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1024 x 768]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1024 x 768]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1024 x 768]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1024 x 768]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    cv::hasNonZero          =>1   perf:895.381ms => 1116.84 im/s
    cv::countNonZero        =>1   perf:882.569ms => 1133.06 im/s *
    ============================================================
    size:[2048 x 2048]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    cv::hasNonZero          =>0   perf:899.53ms => 1111.69 im/s
    cv::countNonZero        =>0   perf:870.894ms => 1148.24 im/s *
    ============================================================
    size:[2048 x 2048]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[2048 x 2048]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    cv::hasNonZero          =>1   perf:2018.92ms => 495.313 im/s
    cv::countNonZero        =>1   perf:1966.37ms => 508.552 im/s *
    ============================================================
    size:[2048 x 2048]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    cv::hasNonZero          =>0   perf:2005.87ms => 498.537 im/s
    cv::countNonZero        =>0   perf:1992.78ms => 501.812 im/s *
    ============================================================
    size:[2048 x 2048]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[2048 x 2048]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[2048 x 2048]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[2048 x 2048]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:0  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:0  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:0  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:0  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:0  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:0  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:0  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:0  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:2  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:2  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:2  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:2  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:2  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:2  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:2  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:2  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:4  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:4  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:4  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:4  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:4  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:4  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:4  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:4  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:5  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:5  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:5  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:5  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:5  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:5  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:5  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:5  continuous = false  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:6  continuous = true  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:6  continuous = true  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:6  continuous = true  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:6  continuous = true  iterations:1000  nz=false  pos=none
    ============================================================
    size:[1031 x 1000]  type:6  continuous = false  iterations:1000  nz=true  pos=begin
    ============================================================
    size:[1031 x 1000]  type:6  continuous = false  iterations:1000  nz=true  pos=middle
    ============================================================
    size:[1031 x 1000]  type:6  continuous = false  iterations:1000  nz=true  pos=end
    ============================================================
    size:[1031 x 1000]  type:6  continuous = false  iterations:1000  nz=false  pos=none
    done
    
    ```
    60b806f9
core.hpp 151.1 KB