howardMatcher.cpp
Go to the documentation of this file.
00001 /*
00002  * howardMatcher.cpp
00003  *
00004  *  Created on: May 31, 2011
00005  *      Author: Alexander Shishkov
00006  */
00007 #include <posest/howardMatcher.h>
00008 #include <iostream>
00009 
00010 using namespace std;
00011 using namespace cv;
00012 using namespace pe;
00013 
00014 HowardDescriptorExtractor::HowardDescriptorExtractor(int _neighborhoodSize): neighborhoodSize(_neighborhoodSize)
00015 {
00016   CV_Assert(neighborhoodSize/2 != 0);
00017 }
00018 
00019 void HowardDescriptorExtractor::read(const FileNode &fn)
00020 {
00021   neighborhoodSize = fn["neighborhoodSize"];
00022 }
00023 
00024 void HowardDescriptorExtractor::write(FileStorage &fs) const
00025 {
00026   fs << "neighborhoodSize" << neighborhoodSize;
00027 }
00028 
00029 int HowardDescriptorExtractor::descriptorSize() const
00030 {
00031   return neighborhoodSize*neighborhoodSize - 1;
00032 }
00033 
00034 int HowardDescriptorExtractor::descriptorType() const
00035 {
00036   return CV_8UC1;
00037 }
00038 
00039 void HowardDescriptorExtractor::computeImpl(const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors) const
00040 {
00041   Mat im;
00042   if (image.channels() > 1)
00043   {
00044     cvtColor(image, im, CV_BGR2GRAY);
00045   }
00046   else
00047     im = image;
00048   int borderSize = neighborhoodSize/2;
00049   //temporary removed. I need that keypoints count doesn't change.
00050   //removeBorderKeypoints(keypoints, im.size(), borderSize);
00051   descriptors.create(keypoints.size(), descriptorSize(), descriptorType());
00052   descriptors.setTo(Scalar(0));
00053 
00054   for (size_t keypointInd = 0; keypointInd < keypoints.size(); keypointInd++)
00055   {
00056     int index = 0;
00057     for(int y = keypoints[keypointInd].pt.y - borderSize; y < keypoints[keypointInd].pt.y + borderSize; y++)
00058     {
00059       for(int x = keypoints[keypointInd].pt.x - borderSize; x < keypoints[keypointInd].pt.x + borderSize; x++)
00060       {
00061         if (x == keypoints[keypointInd].pt.x && y == keypoints[keypointInd].pt.y)
00062         {
00063           continue;
00064         }
00065         if (x < 0 || x >= image.cols || y < 0 || y >= image.rows)
00066           continue;
00067         descriptors.at<unsigned char>(keypointInd, index++) = im.at<unsigned char>(y, x);
00068       }
00069     }
00070   }
00071 }
00072 
00073 HowardStereoMatcher::HowardStereoMatcher(float thresh, int descriptorSize):
00074     threshold(thresh), descriptorSize(descriptorSize)
00075 {
00076   extractor = new HowardDescriptorExtractor(descriptorSize);
00077 }
00078 
00079 void HowardStereoMatcher::match(const frame_common::Frame& prevFrame, const frame_common::Frame& frame,
00080              vector<DMatch>& matches, vector<int>& filteredIndices, const Mat& mask)
00081 {
00082   if (mask.empty())
00083   {
00084     windowedMask = Mat(prevFrame.kpts.size(), frame.kpts.size(), CV_8UC1, Scalar::all(1));
00085   }
00086   else
00087   {
00088     mask.copyTo(windowedMask);
00089   }
00090 
00091   extractor->compute(prevFrame.img, const_cast<vector<KeyPoint>&>(prevFrame.kpts), prevFrameDtors);
00092   filterKpts(prevFrame.img, prevFrame.kpts, true);
00093   extractor->compute(frame.img, const_cast<vector<KeyPoint>&>(frame.kpts), frameDtors);
00094   filterKpts(frame.img, frame.kpts, false);
00095 
00096   Mat scoreMatrix;
00097   calculateScoreMatrix(scoreMatrix);
00098   calculateCrossCheckMatches(scoreMatrix, matches);
00099 
00100   cout << "After crosscheck = " << matches.size() << endl;
00101   if (matches.size())
00102   {
00103     Mat consistMatrix;
00104     calculateConsistMatrix(matches, prevFrame, frame, consistMatrix);
00105     filterMatches(consistMatrix, filteredIndices);
00106   }
00107   cout << "After filtering = " << filteredIndices.size() << endl;
00108 }
00109 
00110 void HowardStereoMatcher::filterKpts(const Mat& img, const vector<KeyPoint>& kpts, bool orientation)
00111 {
00112   int border = descriptorSize/2;
00113   for (size_t ind = 0; ind < kpts.size(); ind++)
00114   {
00115     const Point& kpt = kpts[ind].pt;
00116     if (kpt.x < border || kpt.x >= img.cols - border || kpt.y < border || kpt.y >= img.rows - border)
00117     {
00118       if (orientation)
00119         windowedMask.row(ind).setTo(Scalar::all(0));
00120       else
00121         windowedMask.col(ind).setTo(Scalar::all(0));
00122     }
00123   }
00124 }
00125 
00126 void HowardStereoMatcher::calculateScoreMatrix(Mat& scoreMatrix)
00127 {
00128   scoreMatrix.create(prevFrameDtors.rows, frameDtors.rows, CV_32S);
00129   scoreMatrix.setTo(-1);
00130 
00131   for (int row = 0; row < prevFrameDtors.rows; row++)
00132     for (int col = 0; col < frameDtors.rows; col++)
00133     {
00134       if (windowedMask.at<unsigned char>(row, col))
00135       {
00136         //calculate SAD between row descriptor from first image and col descriptor from second image
00137         scoreMatrix.at<int>(row, col) = sum(abs((prevFrameDtors.row(row) - frameDtors.row(col))))[0];
00138       }
00139     }
00140 }
00141 
00142 void HowardStereoMatcher::calculateCrossCheckMatches(const Mat& scoreMatrix, vector<DMatch>& matches)
00143 {
00144   Point minIndex;
00145   vector<int> matches1to2(scoreMatrix.rows);
00146   for (int row = 0; row < scoreMatrix.rows; row++)
00147   {
00148     minMaxLoc(scoreMatrix.row(row), 0, 0, &minIndex, 0, windowedMask.row(row));
00149     matches1to2[row] = minIndex.x;
00150   }
00151   vector<int> matches2to1(scoreMatrix.cols);
00152   for (int col = 0; col < scoreMatrix.cols; col++)
00153   {
00154     minMaxLoc(scoreMatrix.col(col), 0, 0, &minIndex, 0, windowedMask.col(col));
00155     matches2to1[col] = minIndex.y;
00156   }
00157 #if 0
00158   for (size_t mIndex = 0; mIndex < matches1to2.size(); mIndex++)
00159   {
00160     if (matches2to1[matches1to2[mIndex]] == (int)mIndex)
00161     {
00162       matches.push_back(DMatch(mIndex, matches1to2[mIndex], 0.f));
00163     }
00164   }
00165 #endif
00166 
00167   for (size_t mIndex = 0; mIndex < matches1to2.size(); mIndex++)
00168   {
00169     matches.push_back(DMatch(mIndex, matches1to2[mIndex], 0.f));
00170   }
00171 
00172   for (size_t mIndex = 0; mIndex < matches2to1.size(); mIndex++)
00173   {
00174     if (matches1to2[matches2to1[mIndex]] != (int)mIndex)
00175       matches.push_back(DMatch(matches2to1[mIndex], mIndex, 0.f));
00176   }
00177 }
00178 
00179 double HowardStereoMatcher::calcDeltaL(const Point3f& p11, const Point3f& p21, double t, double f, double threshold)
00180 {
00181   double A = pow( (p11.x - p21.x)*(t - p11.x) - (p11.y - p21.y)*p11.y - (p11.z - p21.z)*p11.z, 2);
00182   double B = pow( (p11.x - p21.x)*p11.x - (p11.y - p21.y)*p11.y - (p11.z - p21.z)*p11.z, 2);
00183   double C = 0.5*pow(t* (p11.y - p21.y), 2);
00184   double D = pow( (p11.x - p21.x)*(t - p21.x) - (p11.y - p21.y)*p21.y - (p11.z - p21.z)*p21.z, 2);
00185   double E = pow( (p11.x - p21.x)*p21.x - (p11.y - p21.y)*p21.y - (p11.z - p21.z)*p21.z, 2);
00186   double F = C;
00187   Point3f diff = p11 - p21;
00188   double L = norm(diff);
00189   return threshold*sqrt(p11.z*p11.z*(A+B+C) + p21.z*p21.z*(D+E+F)) / (L*f);
00190 }
00191 
00192 void HowardStereoMatcher::calculateConsistMatrix(const vector<DMatch>& matches, const frame_common::Frame& prevFrame,
00193                               const frame_common::Frame& frame, Mat& consistMatrix)
00194 {
00195   consistMatrix.create(matches.size(), matches.size(), CV_8UC1);
00196   for (int row = 0; row < consistMatrix.rows; row++)
00197   {
00198     if (!prevFrame.goodPts[matches[row].queryIdx])
00199     {
00200       consistMatrix.row(row).setTo(Scalar(0));
00201       consistMatrix.col(row).setTo(Scalar(0));
00202     }
00203     else
00204     {
00205       for (int col = 0; col < row; col++)
00206       {
00207         unsigned char consistent = 0;
00208         if (frame.goodPts[matches[col].trainIdx])
00209         {
00210           Eigen::Vector4d vec = prevFrame.pts[matches[row].queryIdx];
00211           Point3f p11(vec(0), vec(1), vec(2));
00212           vec = prevFrame.pts[matches[col].queryIdx];
00213           Point3f p21(vec(0), vec(1), vec(2));
00214 
00215           vec = frame.pts[matches[row].trainIdx];
00216           Point3f p12(vec(0), vec(1), vec(2));
00217           vec = frame.pts[matches[col].trainIdx];
00218           Point3f p22(vec(0), vec(1), vec(2));
00219 
00220           Point3f diff1 = p11 - p21;
00221           Point3f diff2 = p12 - p22;
00222           if (abs(norm(diff1) - norm(diff2)) < threshold)
00223             consistent = 1;
00224 #if 0
00225           double L1 = norm(diff1), L2 = norm(diff2);
00226           double dL1 = calcDeltaL(p11, p21, prevFrame.cam.tx, prevFrame.cam.fx, threshold);
00227           double dL2 = calcDeltaL(p12, p22, frame.cam.tx, frame.cam.fx, threshold);
00228           if (fabs(L1 - L2) < 3*sqrt(dL1*dL1+dL2*dL2))
00229             consistent = 1;
00230 #endif
00231 
00232         }
00233         consistMatrix.at<unsigned char>(row, col) = consistMatrix.at<unsigned char>(col, row) = consistent;
00234       }
00235     }
00236     consistMatrix.at<unsigned char>(row, row) = 1;
00237   }
00238 }
00239 
00240 void HowardStereoMatcher::filterMatches(const Mat& consistMatrix, vector<int>& filteredIndices)
00241 {
00242   std::vector<int> indices;
00243   //initialize clique
00244   Mat sums(1, consistMatrix.rows, CV_32S);
00245   for (int row = 0; row < consistMatrix.rows; row++)
00246     sums.at<int>(0, row) = sum(consistMatrix.row(row))[0];
00247   Point maxIndex;
00248   minMaxLoc(sums, 0, 0, 0, &maxIndex, Mat());
00249   indices.push_back(maxIndex.x);
00250 
00251   int lastAddedIndex = maxIndex.x;
00252 
00253   //initialize compatible matches
00254   vector<int> compatibleMatches, sizes;
00255   for (int mIndex = 0; mIndex < consistMatrix.cols; mIndex++)
00256   {
00257     if (consistMatrix.at<unsigned char>(lastAddedIndex, mIndex))
00258     {
00259       compatibleMatches.push_back(mIndex);
00260       sizes.push_back(sum(consistMatrix.row(mIndex))[0]);
00261     }
00262   }
00263 
00264   while(true)
00265   {
00266     vector<int>::iterator cmIter, sizeIter;
00267     if (lastAddedIndex != maxIndex.x)
00268     {
00269       for (cmIter = compatibleMatches.begin(), sizeIter = sizes.begin();
00270            cmIter != compatibleMatches.end(), sizeIter != sizes.end();)
00271       {
00272         if (consistMatrix.at<unsigned char>(lastAddedIndex, *cmIter))
00273         {
00274           cmIter++;
00275           sizeIter++;
00276         }
00277         else
00278         {
00279           cmIter = compatibleMatches.erase(cmIter);
00280           sizeIter = sizes.erase(sizeIter);
00281         }
00282       }
00283     }
00284     if (!compatibleMatches.size())
00285       break;
00286     vector<int>::iterator maxIter = compatibleMatches.end(), maxSizeIter = sizes.end();
00287     int maxSize = 0;
00288     for (cmIter = compatibleMatches.begin(), sizeIter = sizes.begin();
00289                cmIter != compatibleMatches.end(), sizeIter != sizes.end(); cmIter++, sizeIter++)
00290     {
00291       if (*sizeIter > maxSize)
00292       {
00293         maxSize = *sizeIter;
00294         maxSizeIter = sizeIter;
00295         maxIter = cmIter;
00296       }
00297     }
00298     indices.push_back(*maxIter);
00299     lastAddedIndex = *maxIter;
00300     compatibleMatches.erase(maxIter);
00301     sizes.erase(maxSizeIter);
00302   }
00303 
00304   filteredIndices = indices;
00305 }
00306 


posest
Author(s): Kurt Konolige
autogenerated on Thu Jan 2 2014 12:12:17