pythonc++opencvnormalizationnorm

OpenCV: L1 normalization of descriptor matrix


I'm trying to implement SIFTRoot in C++ following this article.

In particular:

    # apply the Hellinger kernel by first L1-normalizing and taking the
    # square-root
    descs /= (descs.sum(axis=1, keepdims=True) + eps)
    descs = np.sqrt(descs)

My question are:

  1. Is there any built-in C++ function to do this in OpenCV?
  2. Are all the descriptors value positive? Otherwise the L1 norm should use the abs of each element.
  3. The first line means "for each row vector, compute the sum of all its elements, then add eps (in order to avoid to divide by 0) and finally divide each vector element by this sum value".

Solution

  • The SIFT descriptor is basically a histogram, so it shouldn't have negative values. I don't think there exists a single function in OpenCV that does what you want to achieve. But it's not too hard to come up with a few lines that do the job

    // For each row
    for (int i = 0; i < descs.rows; ++i) {
      // Perform L1 normalization
      cv::normalize(descs.row(i), descs.row(i), 1.0, 0.0, cv::NORM_L1);
    }
    // Perform sqrt on the whole descriptor matrix
    cv::sqrt(descs, descs);
    

    I don't know exactly how OpenCV deals with zero sum in L1 normalization. You can replace cv::normalize with descs.rows(i) /= (cv::norm(descs.rows(i), cv::NORM_L1) + eps) if the above code generates NaN.