void cvMatch2MyMatch(const DMatchVec& cvMatch , Matching& myMatch) { int numMatch = cvMatch.size(); myMatch.reserve(numMatch); for (int i = 0; i < numMatch; i++) { myMatch.add(cvMatch[i].queryIdx, cvMatch[i].trainIdx, cvMatch[i].distance); } }
void matchSurf(int dimDesc, std::vector<float>& desc0, std::vector<float>& desc1, Matching& matches, float ratio, float maxDist) { int len0 = (int) desc0.size(); int len1 = (int) desc1.size(); assert(len0 % dimDesc == 0 && len1 %dimDesc == 0); int npts0 = len0 / dimDesc; int npts1 = len1 / dimDesc; matches.clear(); matches.reserve(npts0 > npts1 ? npts0 : npts1); float dist, d1, d2; for (int i = 0; i < npts0; i++) { d1 = d2 = FLT_MAX; int jMin = -1; for (int j = 0; j < npts1; j++) { dist = computeSurfDescDist(&desc0[0] + i * dimDesc, &desc1[0] + j * dimDesc, dimDesc); if (dist < d1) { d2 = d1; d1 = dist; jMin = j; } else if (dist < d2) d2 = dist; } if (d1 < maxDist && d1 / d2 < ratio) { matches.add(i, jMin, d1); } } }
void matchSurf(const Mat_f& kdesc0, const Mat_f& kdesc1, Matching& matches, float ratio) { assert(kdesc0.rows > 0); assert(kdesc0.cols == kdesc1.cols); int dimDesc = kdesc0.cols; matches.clear(); matches.reserve(std::max(kdesc0.rows, kdesc1.rows)); float dist, d1, d2; for (int i = 0; i < kdesc0.rows; i++) { d1 = d2 = FLT_MAX; int jMin = -1; for (int j = 0; j < kdesc1.rows; j++) { dist = computeSurfDescDist(kdesc0.data + i * dimDesc, kdesc1.data + j * dimDesc, dimDesc); if (dist < d1) // if this feature matches better than current best { d2 = d1; d1 = dist; jMin = j; } else if (dist < d2) // this feature matches better than second best { d2 = dist; } } // If match has a d1:d2 ratio < 0.65 ipoints are a match if (d1 / d2 < ratio) { matches.add(i, jMin, d1); } } }
int refineMatchedPoints(const Mat_d& pts1, const Mat_d& pts2, Matching& matches, Matching& newMatches, double ratio) { double ud[2] = { 0, 0 }; Mat_d d(matches.num, 2); int num = matches.num; for (int i = 0; i < num; i++) { int idx1 = matches[i].idx1; int idx2 = matches[i].idx2; d.data[2 * i] = pts2.data[2 * idx2] - pts1.data[2 * idx1]; d.data[2 * i + 1] = pts2.data[2 * idx2 + 1] - pts1.data[2 * idx1 + 1]; ud[0] += d.data[2 * i]; ud[1] += d.data[2 * i + 1]; } ud[0] /= num; ud[1] /= num; double cov[4] = { 0, 0, 0, 0 }; for (int i = 0; i < num; i++) { double dx = d.data[2 * i] - ud[0]; double dy = d.data[2 * i + 1] - ud[1]; cov[0] += dx * dx; cov[1] += dx * dy; cov[3] += dy * dy; } double s = ratio * ratio; cov[0] /= num / s; cov[1] /= num / s; cov[3] /= num / s; cov[2] = cov[1]; double icov[4]; mat22Inv(cov, icov); newMatches.clear(); newMatches.reserve(num); for (int i = 0; i < num; i++) { double dx = d.data[2 * i] - ud[0]; double dy = d.data[2 * i + 1] - ud[1]; double dist = dx * dx * icov[0] + 2 * dx * dy * icov[1] + dy * dy * icov[2]; if (dist < 1.0) { newMatches.add(matches[i].idx1, matches[i].idx2, 0); } } return newMatches.num; }
void drawMatching(const ImgG& img1, const Mat_d& keyPts1, const ImgG& img2, const Mat_d& keyPts2, ImgRGB& outImg, double scale, unsigned char* flag) { int numPts = keyPts1.rows; Matching matches; matches.reserve(numPts); cv::RNG rng; for (int i = 0; i < numPts; i++) { matches.add(i, i, 0); } drawMatching(img1, keyPts1, img2, keyPts2, matches, outImg, scale, flag); }
/** match SURF feature points between two views*/ int NewMapPtsSURF::matchBetween(int iCam, int jCam, Matching& matches) { std::vector<float>& desc1 = surfDescs[iCam]; std::vector<float>& desc2 = surfDescs[jCam]; int dim = m_descDim; std::vector<cv::DMatch> matches1, matches2; cv::Mat matDesc1(desc1.size() / dim, dim, CV_32F, &desc1[0]); cv::Mat matDesc2(desc2.size() / dim, dim, CV_32F, &desc2[0]); cv::BruteForceMatcher<cv::L2<float> > matcher; matcher.match(matDesc1, matDesc2, matches1); matcher.match(matDesc2, matDesc1, matches2); //test cv::Mat img1(m_img[iCam].rows, m_img[iCam].cols, CV_8UC1, m_img[iCam].data); cv::Mat img2(m_img[jCam].rows, m_img[jCam].cols, CV_8UC1, m_img[jCam].data); cv::Mat outImg; cv::drawMatches(img1, surfPoints[iCam], img2, surfPoints[jCam], matches1, outImg); cv::imwrite("/home/tsou/test.bmp", outImg); //cross validation std::vector<int> ind1; ind1.assign(surfPoints[iCam].size(), -1); for (size_t j = 0; j < matches1.size(); j++) { int idx1 = matches1[j].queryIdx; int idx2 = matches1[j].trainIdx; ind1[idx1] = idx2; } matches.clear(); matches.reserve(matches2.size()); for (size_t j = 0; j < matches2.size(); j++) { int idx2 = matches2[j].queryIdx; int idx1 = matches2[j].trainIdx; if (ind1[idx1] == idx2) { matches.add(idx1, idx2, matches2[j].distance); } } return matches.num; }