opencv / opencv_contrib

Repository for OpenCV's extra modules
Apache License 2.0
9.39k stars 5.75k forks source link

Linemod ColorGradientPyramid Algorithm Issue #2843

Open GerardMaggiolino opened 3 years ago

GerardMaggiolino commented 3 years ago
System information (version)

N/A

This is a correction to the existing algorithm which is currently slightly incorrect.

Not sure if anyone cares as this is a fairly old algorithm.

Detailed description

The hysteresisGradient function in the Linemod algorithm looks in a 3x3 patch around a location to compute its quantized orientation. The location itself must be over a magnitude threshold, yet the neighboring points are not tested for their magnitude and recorded regardless.

Ideally, the neighboring points should only be considered in the voting process if their magnitude is also greater than the threshold.

Steps to reproduce

N/A

Issue submission checklist

A fast solution to check all points in the neighboring region against the threshold that does NOT add any noticeable computation time is as follows:

Here:

  // Mask 16 buckets into 8 quantized orientations
  for (int r = 1; r < angle.rows - 1; ++r)
  {
    uchar* quant_r = quantized_unfiltered.ptr<uchar>(r);
    float* mag_row = magnitude.ptr<float>(r); // THIS IS ADDED
    for (int c = 1; c < angle.cols - 1; ++c)
    {
      quant_r[c] &= 7;
       // If magnitude is less than the threshold, project past 8
      quant_r[c] |= (mag[c] <= threshold) << 3; // THIS IS ADDED
    }
  }

and here:

      if (mag_r[c] > threshold)
      {
        // Compute histogram of quantized bins in 3x3 patch around pixel
        int histogram[15] = {0}; // THIS IS CHANGED

The locations in the quantized orientation array that do not have sufficient magnitude will be placed past index 8, and thus ignored in the bottom loop. This has been tested on select images and results in less false positives due to higher quality information being used in the voting scheme.

There is no noticeable slowdown as this approach requires zero extra computation in the inner loop. The first block introduces no branching and only a few extra bit operations and caching of the second array.

alalek commented 3 years ago

Hi!

Do you have a test case (data) to show this problem?

Feel free to prepare Pull Request with changes. At least build CI will run existed tests on related code.