How to find the Euclidean distance between the key points of the same image in opencv

I want to get a distance vector d for each key point in the image. The distance vector should consist of the distances from this key point to all other key points in this image. Note. Key points found using SIFT.

Im pretty new for opencv. Is there a library function in C ++ that can make my task easier?

+2
source share
3 answers

If you are not interested in int position-distance, but distance is a descriptor, you can use this:

cv::Mat SelfDescriptorDistances(cv::Mat descr)
{
    cv::Mat selfDistances = cv::Mat::zeros(descr.rows,descr.rows, CV_64FC1);
    for(int keyptNr = 0; keyptNr < descr.rows; ++keyptNr)
    {
        for(int keyptNr2 = 0; keyptNr2 < descr.rows; ++keyptNr2)
        {
            double euclideanDistance = 0;
            for(int descrDim = 0; descrDim < descr.cols; ++descrDim)
            {
                double tmp = descr.at<float>(keyptNr,descrDim) - descr.at<float>(keyptNr2, descrDim);
                euclideanDistance += tmp*tmp;
            }

            euclideanDistance = sqrt(euclideanDistance);
            selfDistances.at<double>(keyptNr, keyptNr2) = euclideanDistance;
        }

    }
    return selfDistances;
}

which will give you the matrix N x N (N = the number of key points), where Mat_i, j = the Euclidean distance between the key points i and j.

with this input:

enter image description here

:

  • , 0,05

enter image description here

  1. , . dist < 0.05.

enter image description here

: , !

UPDATE:

:

, 13 41381 ( ). N , :

// choose double here if you are worried about precision!
#define intermediatePrecision float
//#define intermediatePrecision double
// 
void NBestMatches(cv::Mat descriptors1, cv::Mat descriptors2, unsigned int n, std::vector<std::vector<float> > & distances, std::vector<std::vector<int> > & indices)
{
    // TODO: check whether descriptor dimensions and types are the same for both!

    // clear vector
    // get enough space to create n best matches
    distances.clear();
    distances.resize(descriptors1.rows);
    indices.clear();
    indices.resize(descriptors1.rows);

    for(int i=0; i<descriptors1.rows; ++i)
    {
        // references to current elements:
        std::vector<float> & cDistances = distances.at(i);
        std::vector<int>  & cIndices = indices.at(i);
        // initialize:
        cDistances.resize(n,FLT_MAX);
        cIndices.resize(n,-1);  // for -1 = "no match found"

        // now find the 3 best matches for descriptor i:
        for(int j=0; j<descriptors2.rows; ++j)
        {
            intermediatePrecision euclideanDistance = 0;
            for( int dim = 0; dim < descriptors1.cols; ++dim)
            {
                intermediatePrecision tmp = descriptors1.at<float>(i,dim) - descriptors2.at<float>(j, dim);
                euclideanDistance += tmp*tmp;
            }
            euclideanDistance = sqrt(euclideanDistance);

            float tmpCurrentDist = euclideanDistance;
            int tmpCurrentIndex = j;

            // update current best n matches:
            for(unsigned int k=0; k<n; ++k)
            {
                if(tmpCurrentDist < cDistances.at(k))
                {
                    int tmpI2 = cIndices.at(k);
                    float tmpD2 = cDistances.at(k);

                    // update current k-th best match
                    cDistances.at(k) = tmpCurrentDist;
                    cIndices.at(k) = tmpCurrentIndex;

                    // previous k-th best should be better than k+1-th best //TODO: a simple memcpy would be faster I guess.
                    tmpCurrentDist = tmpD2;
                    tmpCurrentIndex =tmpI2;
                }
            }


        }
    }

}

N . , , descriptors1 = descriptors2 , . : , , ( ) 0 ! , !

, :

int main()
{
    cv::Mat input = cv::imread("../inputData/MultiLena.png");

    cv::Mat gray;
    cv::cvtColor(input, gray, CV_BGR2GRAY);

    cv::SiftFeatureDetector detector( 7500 );
    cv::SiftDescriptorExtractor describer;

    std::vector<cv::KeyPoint> keypoints;

    detector.detect( gray, keypoints );

    // draw keypoints
    cv::drawKeypoints(input,keypoints,input);



    cv::Mat descriptors;
    describer.compute(gray, keypoints, descriptors);

    int n = 4;
    std::vector<std::vector<float> > dists;
    std::vector<std::vector<int> > indices;

    // compute the N best matches between the descriptors and themselves.
    // REMIND: ONE best match will always be the keypoint itself in this setting!
    NBestMatches(descriptors, descriptors, n, dists, indices);

    for(unsigned int i=0; i<dists.size(); ++i)
    {
        for(unsigned int j=0; j<dists.at(i).size(); ++j)
        {
            if(dists.at(i).at(j) < 0.05)
                cv::line(input, keypoints[i].pt, keypoints[indices.at(i).at(j)].pt, cv::Scalar(255,255,255) );
        }
    }

    cv::imshow("input", input);
    cv::waitKey(0);

    return 0;
}
+9

keypoint , pt, , , x y [ (x, y) ] .

kp1 kp2, :

Point diff = kp1.pt - kp2.pt;
float dist = std::sqrt( diff.x * diff.x + diff.y * diff.y )

, .

+2
  • 2D- ( NXN) โ†’ std::vector< std::vector< float > > item;
  • 2 , (N)
  • , a-Jays

    Point diff = kp1.pt - kp2.pt; float dist = std::sqrt( diff.x * diff.x + diff.y * diff.y );

  • , push_back โ†’ N .

+2

Source: https://habr.com/ru/post/1620334/


All Articles