c++ - How to find euclidean distance between keypoints of a single image in opencv -
c++ - How to find euclidean distance between keypoints of a single image in opencv -
i want distance vector d each key point in image. distance vector should consist of distances keypoint other keypoints in image. note: keypoints found using sift.
im pretty new opencv. there library function in c++ can create task easy?
if aren't interested int position-distance descriptor-distance can utilize 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; } } homecoming selfdistances; }
which give n x n matrix (n = number of keypoints) mat_i,j = euclidean distance between keypoint , j.
with input:
i these outputs:
image keypoints marked have distance of less 0.05 image corresponds matrix. white pixels dist < 0.05.remark: can optimize many things in computation of matrix, since distances symmetric!
update:
here way it:
from chat know need 13gb memory hold distance info 41381 keypoints (which tried). if want instead n best matches, seek code:
// take double here if worried 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 , types same both! // clear vector // plenty space 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 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); // -1 = "no match found" // find 3 best matches 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 improve k+1-th best //todo: simple memcpy faster guess. tmpcurrentdist = tmpd2; tmpcurrentindex =tmpi2; } } } } }
it computes n best matches each keypoint of first descriptors sec descriptors. if want same keypoints you'll set descriptors1 = descriptors2
ion phone call shown below. remember: function doesnt know both descriptor sets identical, first best match (or @ to the lowest degree one) keypoint distance 0 always! maintain in mind if using results!
here's sample code generate image similar 1 above:
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 n best matches between descriptors , themselves. // remind: 1 best match keypoint in 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); homecoming 0; }
c++ opencv
Comments
Post a Comment