features.cpp
Go to the documentation of this file.
00001 
00005 #include "features.hpp"
00006 
00007 
00008 double calculateFeatureSpeeds(const vector<cv::Point2f>& pts1, const vector<cv::Point2f>& pts2, vector<cv::Point2f>& velocities, double time1, double time2) {
00009         
00010         if ((pts1.size() != pts2.size()) || (pts1.size() == 0)) {
00011                 printf("%s << ERROR! pts vectors are of sizes (%d, %d)\n", __FUNCTION__, pts1.size(), pts2.size());
00012                 return 0.0;
00013         }
00014         
00015         double avSpeed = 0.0;
00016         
00017         for (unsigned int iii = 0; iii < pts1.size(); iii++) {
00018                 
00019                 float vel_x = (pts2.at(iii).x - pts1.at(iii).x) / (time2 - time1);
00020                 float vel_y = (pts2.at(iii).y - pts1.at(iii).y) / (time2 - time1);
00021                 
00022                 velocities.push_back(cv::Point2f(vel_x, vel_y));
00023                 avSpeed += pow((pow(vel_x, 2.0) + pow(vel_y, 2.0)), 0.5);
00024         }
00025         
00026         avSpeed /= float(pts1.size());
00027         
00028         return avSpeed;
00029         
00030 }
00031 
00032 double generateVirtualPointset(const vector<cv::Point2f>& pts1, const vector<cv::Point2f>& pts2, vector<cv::Point2f>& virtual_pts, double bias_fraction) {
00033         
00034         if (pts1.size() != pts2.size()) {
00035                 return -1.0;
00036         }
00037         
00038         double totalMotion = 0.0;
00039         
00040         for (unsigned int iii = 0; iii < pts1.size(); iii++) {
00041                 cv::Point2f vpt;
00042                 
00043                 totalMotion += pow(pow(pts1.at(iii).x - pts2.at(iii).x, 2.0)+pow(pts1.at(iii).y - pts2.at(iii).y, 2.0),0.5);
00044                 
00045                 vpt.x = (1.0 - bias_fraction)*pts1.at(iii).x + (bias_fraction)*pts2.at(iii).x;
00046                 vpt.y = (1.0 - bias_fraction)*pts1.at(iii).y + (bias_fraction)*pts2.at(iii).y;
00047                 
00048                 virtual_pts.push_back(vpt);
00049                 
00050         }
00051         
00052         totalMotion /= double(pts1.size());
00053         
00054         return totalMotion;
00055         
00056 }
00057 
00058 /*
00059 draws KeyPoints to scale with coloring proportional to feature strength
00060 */
00061 void drawRichKeyPoints(const cv::Mat& src, std::vector<cv::KeyPoint>& kpts, cv::Mat& dst) {
00062         
00063         cv::Mat grayFrame;
00064         cvtColor(src, grayFrame, CV_RGB2GRAY);
00065         
00066         dst = cv::Mat::zeros(src.size(), src.type());
00067         
00068         
00069         if (kpts.size() == 0) {
00070                 return;
00071         }
00072         
00073         std::vector<cv::KeyPoint> kpts_cpy, kpts_sorted;
00074         
00075         kpts_cpy.insert(kpts_cpy.end(), kpts.begin(), kpts.end());
00076         
00077         double maxResponse = kpts_cpy.at(0).response;
00078         double minResponse = kpts_cpy.at(0).response;
00079         
00080         while (kpts_cpy.size() > 0) {
00081                 
00082                 double maxR = 0.0;
00083                 unsigned int idx = 0;
00084                 
00085                 for (unsigned int iii = 0; iii < kpts_cpy.size(); iii++) {
00086                         
00087                         if (kpts_cpy.at(iii).response > maxR) {
00088                                 maxR = kpts_cpy.at(iii).response;
00089                                 idx = iii;
00090                         }
00091                         
00092                         if (kpts_cpy.at(iii).response > maxResponse) {
00093                                 maxResponse = kpts_cpy.at(iii).response;
00094                         }
00095                         
00096                         if (kpts_cpy.at(iii).response < minResponse) {
00097                                 minResponse = kpts_cpy.at(iii).response;
00098                         }
00099                 }
00100                 
00101                 kpts_sorted.push_back(kpts_cpy.at(idx));
00102                 kpts_cpy.erase(kpts_cpy.begin() + idx);
00103                 
00104         }
00105         
00106         int thickness = 1;
00107         cv::Point center;
00108         cv::Scalar colour;
00109         int red = 0, blue = 0, green = 0;
00110         int radius;
00111         double normalizedScore;
00112         
00113         if (minResponse == maxResponse) {
00114                 colour = CV_RGB(255, 0, 0);
00115         }
00116         
00117         for (int iii = kpts_sorted.size()-1; iii >= 0; iii--) {
00118 
00119                 if (minResponse != maxResponse) {
00120                         normalizedScore = pow((kpts_sorted.at(iii).response - minResponse) / (maxResponse - minResponse), 0.25);
00121                         red = int(255.0 * normalizedScore);
00122                         green = int(255.0 - 255.0 * normalizedScore);
00123                         colour = CV_RGB(red, green, blue);
00124                 }
00125                 
00126                 center = kpts_sorted.at(iii).pt;
00127         center.x *= 16.0;
00128         center.y *= 16.0;
00129         
00130         radius = 16.0 * (double(kpts_sorted.at(iii).size)/2.0);
00131         
00132         if (radius > 0) {
00133             circle(dst, center, radius, colour, -1, CV_AA, 4);
00134         }
00135                 
00136         }
00137         
00138         fadeImage(src, dst);
00139         //cvtColor(grayFrame, dst, CV_GRAY2RGB);
00140         
00141         for (int iii = kpts_sorted.size()-1; iii >= 0; iii--) {
00142 
00143                 if (minResponse != maxResponse) {
00144                         normalizedScore = pow((kpts_sorted.at(iii).response - minResponse) / (maxResponse - minResponse), 0.25);
00145                         red = int(255.0 * normalizedScore);
00146                         green = int(255.0 - 255.0 * normalizedScore);
00147                         colour = CV_RGB(red, green, blue);
00148                 }
00149                 
00150                 center = kpts_sorted.at(iii).pt;
00151         center.x *= 16.0;
00152         center.y *= 16.0;
00153         
00154         radius = 16.0 * (double(kpts_sorted.at(iii).size)/2.0);
00155         
00156         if (radius > 0) {
00157             circle(dst, center, radius, colour, thickness, CV_AA, 4);
00158         }
00159                 
00160         }
00161         
00162         
00163         
00164 }
00165 
00166 void fadeImage(const cv::Mat& src, cv::Mat& dst) {
00167         
00168         double frac = 0.65;
00169         
00170         #pragma omp parallel for
00171         for (int iii = 0; iii < src.rows; iii++) {
00172                 for (int jjj = 0; jjj < src.cols; jjj++) {
00173                         
00174                         if ((src.at<cv::Vec3b>(iii,jjj)[0] != 0) && (src.at<cv::Vec3b>(iii,jjj)[1] != 0) && (src.at<cv::Vec3b>(iii,jjj)[2] != 0)) {
00175                                 for (unsigned int kkk = 0; kkk < 3; kkk++) {
00176                                         
00177                                         // check val first
00178                                         dst.at<cv::Vec3b>(iii,jjj)[0] = (unsigned char) ((1-frac) * double(src.at<cv::Vec3b>(iii,jjj)[0]) + frac * double(dst.at<cv::Vec3b>(iii,jjj)[0])) / 1.0;
00179                                         dst.at<cv::Vec3b>(iii,jjj)[1] = (unsigned char) ((1-frac) * double(src.at<cv::Vec3b>(iii,jjj)[1]) + frac * double(dst.at<cv::Vec3b>(iii,jjj)[1])) / 1.0;
00180                                         dst.at<cv::Vec3b>(iii,jjj)[2] = (unsigned char) ((1-frac) * double(src.at<cv::Vec3b>(iii,jjj)[2]) + frac * double(dst.at<cv::Vec3b>(iii,jjj)[2])) / 1.0;
00181                                         
00182                                 }
00183                         } else {
00184                                 dst.at<cv::Vec3b>(iii,jjj)[0] = src.at<cv::Vec3b>(iii,jjj)[0];
00185                                 dst.at<cv::Vec3b>(iii,jjj)[1] = src.at<cv::Vec3b>(iii,jjj)[1];
00186                                 dst.at<cv::Vec3b>(iii,jjj)[2] = src.at<cv::Vec3b>(iii,jjj)[2];
00187                         }
00188                         
00189                         
00190                 }
00191         }
00192         
00193         
00194 }
00195 
00196 /*
00197 Removes surplus features and those with invalid size
00198 */
00199 void filterKeyPoints(std::vector<cv::KeyPoint>& kpts, unsigned int maxSize, unsigned int maxFeatures) {
00200         
00201         if (maxSize == 0) {
00202                 return;
00203         }
00204         
00205         sortKeyPoints(kpts);
00206         
00207         for (unsigned int iii = 0; iii < kpts.size(); iii++) {
00208                 
00209                 if (kpts.at(iii).size > float(maxSize)) { 
00210                         kpts.erase(kpts.begin() + iii);
00211                         iii--;
00212                 }
00213         }
00214         
00215         if ((maxFeatures != 0) && (kpts.size() > maxFeatures)) {
00216         kpts.erase(kpts.begin()+maxFeatures, kpts.end());
00217     }
00218         
00219 }
00220 
00221 void showMatches(const cv::Mat& pim1, vector<cv::Point2f>& pts1, const cv::Mat& pim2, vector<cv::Point2f>& pts2, cv::Mat& drawImg) {
00222 
00223         drawImg = cv::Mat::zeros(pim1.rows, pim1.cols + pim2.cols, CV_8UC3);
00224         
00225         #pragma omp parallel for
00226         for (int iii = 0; iii < pim1.rows; iii++) {
00227                 for (int jjj = 0; jjj < pim1.cols; jjj++) {
00228                         
00229                         drawImg.at<cv::Vec3b>(iii,jjj)[0] = pim1.at<unsigned char>(iii,jjj);
00230                         drawImg.at<cv::Vec3b>(iii,jjj)[1] = pim1.at<unsigned char>(iii,jjj);
00231                         drawImg.at<cv::Vec3b>(iii,jjj)[2] = pim1.at<unsigned char>(iii,jjj);
00232                         
00233                         drawImg.at<cv::Vec3b>(iii,640+jjj)[0] = pim2.at<unsigned char>(iii,jjj);
00234                         drawImg.at<cv::Vec3b>(iii,640+jjj)[1] = pim2.at<unsigned char>(iii,jjj);
00235                         drawImg.at<cv::Vec3b>(iii,640+jjj)[2] = pim2.at<unsigned char>(iii,jjj);
00236                 }
00237         }
00238         
00239         cv::Point pt1, pt2;
00240         int radius = 4;
00241         int thickness = 1;
00242         
00243         radius *= 16.0;
00244         for (unsigned int iii = 0; iii < pts1.size(); iii++) {
00245                 
00246                 pt1.x = 16.0 * pts1.at(iii).x;
00247                 pt1.y = 16.0 * pts1.at(iii).y;
00248                 
00249                 pt2.x = 16.0 * (pts2.at(iii).x + 640.0);
00250                 pt2.y = 16.0 * pts2.at(iii).y;
00251                 
00252                 circle(drawImg, pt1, radius, CV_RGB(255, 0, 0), thickness, CV_AA, 4);
00253                 circle(drawImg, pt2, radius, CV_RGB(255, 0, 0), thickness, CV_AA, 4);
00254                 line(drawImg, pt1, pt2, CV_RGB(0, 0, 255), thickness, CV_AA, 4);
00255         }
00256         
00257 }
00258 
00259 void crossCheckMatching( cv::Ptr<cv::DescriptorMatcher>& descriptorMatcher,
00260                          const cv::Mat& descriptors1, const cv::Mat& descriptors2,
00261                          vector<cv::DMatch>& filteredMatches12, int knn )
00262 {
00263 
00264     //printf("%s << ENTERED.\n", __FUNCTION__);
00265 
00266     filteredMatches12.clear();
00267 
00268     //printf("%s << DEBUG %d.\n", __FUNCTION__, 0);
00269     //vector<vector<cv::DMatch> > matches12, matches21;
00270     vector<vector<cv::DMatch> > matches12, matches21;
00271 
00272 
00273     //printf("%s << DEBUG %d.\n", __FUNCTION__, 1);
00274 
00275     //printf("%s << descriptors1.size() = (%d, %d).\n", __FUNCTION__, descriptors1.rows, descriptors1.cols);
00276     //printf("%s << descriptors2.size() = (%d, %d).\n", __FUNCTION__, descriptors2.rows, descriptors2.cols);
00277 
00278 
00279 
00280     descriptorMatcher->knnMatch( descriptors1, descriptors2, matches12, knn );
00281 
00282 
00283     //printf("%s << DEBUG %d.\n", __FUNCTION__, 2);
00284     descriptorMatcher->knnMatch( descriptors2, descriptors1, matches21, knn );
00285 
00286     //printf("%s << matches12.size() = %d.\n", __FUNCTION__, matches12.size());
00287 
00288     for( size_t m = 0; m < matches12.size(); m++ )
00289     {
00290         bool findCrossCheck = false;
00291 
00292         //printf("%s << matches12[%d].size() = %d.\n", __FUNCTION__, m, matches12[m].size());
00293 
00294         for( size_t fk = 0; fk < matches12[m].size(); fk++ )
00295         {
00296             cv::DMatch forward = matches12[m][fk];
00297 
00298             //printf("%s << matches21[%d].size() = %d.\n", __FUNCTION__, forward.trainIdx, matches21[forward.trainIdx].size());
00299 
00300             for( size_t bk = 0; bk < matches21[forward.trainIdx].size(); bk++ )
00301             {
00302                 cv::DMatch backward = matches21[forward.trainIdx][bk];
00303                 if( backward.trainIdx == forward.queryIdx )
00304                 {
00305                     filteredMatches12.push_back(forward);
00306                     findCrossCheck = true;
00307                     break;
00308                 }
00309             }
00310             if( findCrossCheck ) break;
00311         }
00312     }
00313 
00314 }
00315 
00316 void filterTrackingsByRadialProportion(vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, cv::Mat& K, cv::Mat& newCamMat, cv::Mat& distCoeffs, cv::Size& imSize, double prop) {
00317         //cout << "filterTrackingsByRadialProportion: " << imSize.width << " " << imSize.height << endl;
00318         
00319         vector<cv::Point2f> newPts;
00320         redistortPoints(pts2, newPts, K, distCoeffs, newCamMat);
00321         
00322         cv::Point2f centrePt = cv::Point2f(double(imSize.width)/2.0,double(imSize.height)/2.0);
00323         double maxDist = prop * double(imSize.width)/2.0;
00324         
00325         double dist;
00326         
00327         unsigned int iii = 0;
00328         
00329         while (iii < pts1.size()) {
00330                 
00331                 dist = distBetweenPts2f(pts2.at(iii), centrePt);
00332                 
00333                 if (dist > maxDist) {
00334                         
00335                         pts1.erase(pts1.begin() + iii);
00336                         pts2.erase(pts2.begin() + iii);
00337                         
00338                 } else {
00339                         iii++;
00340                 }
00341                 
00342         }
00343 
00344         
00345 }
00346 
00347 void reduceEdgyFeatures(vector<cv::KeyPoint>& KeyPoints, cameraParameters& camData) {
00348 
00349         vector<cv::Point2f> candidates;
00350 
00351         cv::KeyPoint::convert(KeyPoints, candidates);
00352 
00353         vector<cv::Point2f> redistortedPoints;
00354         float minBorderDist = 2.0;
00355 
00356         redistortPoints(candidates, redistortedPoints, camData.Kx, camData.distCoeffs, camData.expandedCamMat);
00357 
00358         for (int iii = candidates.size()-1; iii >= 0; iii--) {
00359 
00360                 float xDist = min(abs(((float) camData.expandedSize.width) - redistortedPoints.at(iii).x), abs(redistortedPoints.at(iii).x));
00361                 float yDist = min(abs(((float) camData.expandedSize.height) - redistortedPoints.at(iii).y), abs(redistortedPoints.at(iii).y));
00362                 float dist = min(xDist, yDist) - KeyPoints.at(iii).size;
00363 
00364                 if (dist < minBorderDist) {
00365                         KeyPoints.erase(KeyPoints.begin() + iii);
00366                 }
00367 
00368         }
00369 
00370 }
00371 
00372 void reduceEdgyCandidates(vector<cv::Point2f>& candidates, cameraParameters& camData) {
00373 
00374         vector<cv::Point2f> redistortedPoints;
00375         float minBorderDist = 2.0;
00376 
00377         redistortPoints(candidates, redistortedPoints, camData.Kx, camData.distCoeffs, camData.expandedCamMat);
00378 
00379         for (int iii = candidates.size()-1; iii >= 0; iii--) {
00380 
00381                 float xDist = min(abs(((float) camData.expandedSize.width) - redistortedPoints.at(iii).x), abs(redistortedPoints.at(iii).x));
00382                 float yDist = min(abs(((float) camData.expandedSize.height) - redistortedPoints.at(iii).y), abs(redistortedPoints.at(iii).y));
00383                 float dist = min(xDist, yDist);
00384                 if (dist < minBorderDist) {
00385                         candidates.erase(candidates.begin() + iii);
00386                 }
00387 
00388         }
00389 
00390 }
00391 
00392 bool checkRoomForFeature(vector<cv::Point2f>& pts, cv::Point2f& candidate, double dist) {
00393 
00394         double distance;
00395 
00396         for (unsigned int iii = 0; iii < pts.size(); iii++) {
00397 
00398                 distance = distanceBetweenPoints(pts.at(iii), candidate);
00399 
00400                 if (distance < dist) {
00401                         return false;
00402                 }
00403 
00404         }
00405 
00406         return true;
00407 
00408 }
00409 
00410 void reduceUnrefinedCandidates(vector<cv::Point2f>& candidates) {
00411 
00412         if (candidates.size() == 0) {
00413                 return;
00414         }
00415 
00416         for (int iii = candidates.size()-1; iii >= 0; iii--) {
00417 
00418                 if (((candidates.at(iii).x - floor(candidates.at(iii).x)) == 0.0) && ((candidates.at(iii).y - floor(candidates.at(iii).y)) == 0.0)) {
00419                         printf("%s << erasing: (%f, %f)\n", __FUNCTION__, candidates.at(iii).x, candidates.at(iii).y);
00420                         candidates.erase(candidates.begin() + iii);
00421                 }
00422         }
00423 
00424 }
00425 
00426 void reduceProximalCandidates(vector<cv::Point2f>& existing, vector<cv::Point2f>& candidates) {
00427 
00428         for (unsigned int iii = 0; iii < candidates.size(); iii++) {
00429 
00430                 bool isValid = checkRoomForFeature(existing, candidates.at(iii), 3.0);
00431 
00432                 if (!isValid) {
00433                         candidates.erase(candidates.begin() + iii);
00434                         iii--;
00435                 }
00436 
00437         }
00438 
00439 }
00440 
00441 void concatenateWithExistingPoints(vector<cv::Point2f>& pts, vector<cv::Point2f>& kps, int size, double min_sep, bool debug) {
00442 
00443         // Or reverse order?
00444         for (unsigned int iii = 0; iii < kps.size(); iii++) {
00445 
00446                 if (pts.size() >= size) {
00447                         break;
00448                 }
00449                 
00450                 bool isValid = checkRoomForFeature(pts, kps.at(iii), min_sep);
00451 
00452                 if (!isValid) {
00453                         kps.erase(kps.begin()+iii);
00454                         iii--;
00455                 } else {
00456                         if (debug) { printf("%s << a valid point!!!!!!!\n", __FUNCTION__); }
00457                         pts.push_back(kps.at(iii));
00458                 }
00459 
00460                 
00461 
00462         }
00463 
00464 }
00465 
00466 void initializeDrawingColors(cv::Scalar* kColors, cv::Scalar* tColors, int num) {
00467 
00468         for (int iii = 0; iii < num; iii++) {
00469                 switch (iii) {
00470                         case 0:
00471                                 tColors[iii] = CV_RGB(255, 128, 128);
00472                                 kColors[iii] = CV_RGB(255, 0, 0);
00473                                 break;
00474                         case 1:
00475                                 tColors[iii] = CV_RGB(128, 128, 255);
00476                                 kColors[iii] = CV_RGB(0, 0, 255);
00477                                 break;
00478                         case 2:
00479                                 tColors[iii] = CV_RGB(128, 255, 128);
00480                                 kColors[iii] = CV_RGB(0, 255, 0);
00481                                 break;
00482                         case 3:
00483                                 tColors[iii] = CV_RGB(128, 255, 255);
00484                                 kColors[iii] = CV_RGB(0, 255, 255);
00485                                 break;
00486                         case 4:
00487                                 tColors[iii] = CV_RGB(128, 128, 255);
00488                                 kColors[iii] = CV_RGB(255, 0, 255);
00489                                 break;
00490                         case 5:
00491                                 tColors[iii] = CV_RGB(255, 255, 128);
00492                                 kColors[iii] = CV_RGB(255, 255, 0);
00493                                 break;
00494                         default:
00495                                 tColors[iii] = CV_RGB(128, 128, 255);
00496                                 kColors[iii] = CV_RGB(255, 255, 255);
00497                                 break;
00498 
00499                 }
00500         }
00501 
00502 }
00503 
00504 void transformPoints(vector<cv::Point2f>& pts1, cv::Mat& H) {
00505         cv::Mat ptCol(3, 1, CV_64FC1), newPos(3, 1, CV_64FC1);
00506 
00507         //vector<Point2f> tempPoints;
00508         //tempPoints.insert(tempPoints.end(), finishingPoints[kkk].begin(), finishingPoints[kkk].end());
00509 
00510         for (unsigned int mmm = 0; mmm < pts1.size(); mmm++) {
00511 
00512                 ptCol.at<double>(0,0) = pts1.at(mmm).x;
00513                 ptCol.at<double>(1,0) = pts1.at(mmm).y;
00514                 ptCol.at<double>(2,0) = 1.0;
00515 
00516                 newPos = H * ptCol;
00517 
00518                 //printf("%s::%s << Changing point [%d][%d] from (%f, %f) to (%f, %f)\n", __PROGRAM__, __FUNCTION__, kkk, mmm, finishingPoints[kkk].at(mmm).x, finishingPoints[kkk].at(mmm).y, newPos.at<double>(0,0), newPos.at<double>(1,0));
00519 
00520                 pts1.at(mmm).x = ((float) newPos.at<double>(0,0) / newPos.at<double>(2,0));
00521                 pts1.at(mmm).y = ((float) newPos.at<double>(1,0) / newPos.at<double>(2,0));
00522 
00523         }
00524 }
00525 
00526 void reduceWeakFeatures(cv::Mat& im, vector<cv::KeyPoint>& feats, double minResponse) {
00527 
00528         // assignMinimumRadii(feats);
00529 
00530         vector<float> responseLevels;
00531 
00532         for (unsigned int iii = 0; iii < feats.size(); iii++) {
00533 
00534                 if (feats.at(iii).response == 0.0) {
00535                         feats.at(iii).response = estimateSalience(im, feats.at(iii).pt, ((double) feats.at(iii).size / 2.0));
00536                         responseLevels.push_back(feats.at(iii).response);
00537                 }
00538 
00539                 //printf("%s << (%d) (%f, %f, %d)\n", __FUNCTION__, iii, feats.at(iii).size, feats.at(iii).response, feats.at(iii).octave);
00540 
00541         }
00542 
00543         sort(responseLevels.begin(), responseLevels.end());
00544 
00545         //printf("%s << minResponse = %f; maxResponse = %f; medianResponse = %f\n", __FUNCTION__, responseLevels.at(0), responseLevels.at(responseLevels.size()-1), responseLevels.at(responseLevels.size()/2));
00546 
00547         //cin.get();
00548 
00549         for (int iii = feats.size()-1; iii >= 0; iii--) {
00550 
00551                 // responseLevels.at(responseLevels.size()-5)
00552                 if (feats.at(iii).response < minResponse) { // 80.0
00553                         feats.erase(feats.begin() + iii);
00554                 }
00555 
00556 
00557         }
00558 
00559 }
00560 
00561 void trackPoints(const cv::Mat& im1, const cv::Mat& im2, vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, int distanceConstraint, double thresh, vector<unsigned int>& lostIndices, cv::Mat H12, cameraParameters camData) {
00562 
00563         //struct timeval test_timer;
00564         //double testTime;
00565         
00566         vector<cv::Point2f> originalGuides;
00567         
00568         
00569         bool debugFlag = false;
00570         
00571         if (debugFlag) { printf("%s << ENTERED. im1 = (%u, %u); im2 = (%u, %u), pts1 = (%lu), pts2 = (%lu)\n", __FUNCTION__, im1.cols, im1.rows, im2.cols, im2.rows, pts1.size(), pts2.size()); }
00572         
00573         //testTime = timeElapsedMS(test_timer, true);
00574         //printf("%s << ENTERED.\n", __FUNCTION__);
00575 
00576         if (pts1.size() == 0) {
00577                 return;
00578         }
00579 
00580         if ((distanceConstraint % 2) == 0) {
00581                 distanceConstraint++;
00582         }
00583         
00584         //testTime = timeElapsedMS(test_timer, false);
00585         //printf("XDebug 0a: (%f)\n", testTime);
00586 
00587         cv::Size winSize = cv::Size(distanceConstraint, distanceConstraint);
00588         int maxLevel = 3;
00589         cv::TermCriteria criteria = cv::TermCriteria( cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 30, 0.01);
00590         //double derivLambda = 0.5;
00591         int opticalFlowFlags = CV_LKFLOW_GET_MIN_EIGENVALS;
00592 
00593         bool guiding = false;
00594         bool warping = false;
00595 
00596         cv::Mat im1b;
00597         vector<cv::Point2f> pts1b;
00598 
00599         vector<uchar> statusVec;
00600         vector<float> err;
00601 
00602         cv::Mat mask, blank;
00603         blank = cv::Mat::ones(im1.size(), CV_8UC1);
00604         blank *= 255;
00605         
00606         //testTime = timeElapsedMS(test_timer, false);
00607         //printf("XDebug 0b: (%f)\n", testTime);
00608 
00609         //printf("%s << DEBUG A\n", __FUNCTION__);
00610 
00611         /*
00612         double orig_vals[4], new_vals[4];
00613         findIntensityValues(orig_vals, im1, blank);
00614         // findIntensityValues(orig_vals, im1b, mask);
00615         findIntensityValues(new_vals, im2, blank);
00616         */
00617         
00618         //testTime = timeElapsedMS(test_timer, false);
00619         //printf("XDebug 0c: (%f)\n", testTime);
00620 
00621         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 4); }
00622 
00623         //if (debugFlag) { printf("%s << Vals (%f, %f, %f) vs (%f, %f, %f)\n", __FUNCTION__, orig_vals[0], orig_vals[1], orig_vals[2], new_vals[0], new_vals[1], new_vals[2]); }
00624 
00625         vector<cv::Point2f> originalPts, originalEstimates;
00626         originalPts.insert(originalPts.end(), pts1.begin(), pts1.end());
00627         originalEstimates.insert(originalEstimates.end(), pts2.begin(), pts2.end());
00628         
00629         //testTime = timeElapsedMS(test_timer, false);
00630         //printf("XDebug 1: (%f)\n", testTime);
00631         
00632         if (pts2.size() == pts1.size()) {
00633                 if (debugFlag) { printf("%s << guiding is set to TRUE.\n", __FUNCTION__); }
00634                 guiding = true;
00635                 //debugFlag = true;
00636                 originalGuides.insert(originalGuides.end(), pts2.begin(), pts2.end());
00637                 opticalFlowFlags += cv::OPTFLOW_USE_INITIAL_FLOW;
00638         } else {
00639                 if (debugFlag) { printf("%s << guiding is maintained as FALSE.\n", __FUNCTION__); }
00640         }
00641 
00642         if ((H12.rows != 0) && (pts2.size() == pts1.size())) {
00643 
00644                 // More aggressive shift for NUC handling
00645                 /*
00646                 double scale_shift = (new_vals[1] - new_vals[0]) / (orig_vals[1] - orig_vals[0]);
00647                 double vert_shift = new_vals[0] - orig_vals[0];
00648                 double down_shift = orig_vals[0];
00649                 */
00650                 
00651                 warping = true;
00652                 
00653                 
00654                 //printf("%s << Using initial guesses... (distanceConstraint = %d)\n", __FUNCTION__, distanceConstraint);
00655                 
00656 
00657                 pts1b.insert(pts1b.end(), pts1.begin(), pts1.end());
00658                 transformPoints(pts1b, H12);
00659                 warpPerspective(im1, im1b, H12, im1.size());
00660 
00661                 //shiftIntensities(im1b, scale_shift, vert_shift, down_shift);
00662 
00663                 warpPerspective(blank, mask, H12, blank.size());
00664 
00665                 
00666         } else {
00667 
00668                 /*
00669                 double scale_shift = 1.0;
00670                 double vert_shift = new_vals[3] - orig_vals[3];
00671                 double down_shift = 0.0;
00672                 */
00673                 
00674                 im1b = cv::Mat(im1); // .copyTo(im1b);
00675                 // shiftIntensities(im1b, scale_shift, vert_shift, down_shift);
00676 
00677                 // Need to make sure that black border stays as black, and only valid pixels are sampled...
00678 
00679                 
00680                 
00681                 if (!guiding) {
00682                         if (debugFlag) { printf("%s << Clearing second points vector...\n", __FUNCTION__); }
00683                         pts2.clear();
00684                 }
00685         }
00686         
00687         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 5); }
00688 
00689         //testTime = timeElapsedMS(test_timer, false);
00690         //printf("XDebug 2: (%f)\n", testTime);
00691 
00692         if (warping) {
00693                 if (debugFlag) { printf("%s << (warped) Before. (%u, %u) (%u, %u) (%lu) (%u, %u)\n", __FUNCTION__, im1b.rows, im1b.cols, im2.rows, im2.cols, pts1b.size(), winSize.height, winSize.width); }
00694                 cv::calcOpticalFlowPyrLK(im1b, im2, pts1b, pts2, statusVec, err, winSize, maxLevel, criteria, opticalFlowFlags, thresh);
00695                 checkDistances(originalEstimates, pts2, statusVec, (double) distanceConstraint);
00696                 if (debugFlag) { printf("%s << After.\n", __FUNCTION__); }
00697                 markAbsentPoints(pts1b, pts2, statusVec, im1.size());
00698         } else {
00699                 if (debugFlag) { printf("%s << (not-warped) Before. (%u, %u) (%u, %u) (%lu) (%u, %u)\n", __FUNCTION__, im1b.rows, im1b.cols, im2.rows, im2.cols, pts1.size(), winSize.height, winSize.width); }
00700                 
00701                 /*
00702                 for (unsigned int xxx = 0; xxx < pts1.size(); xxx++) {
00703                         
00704                         cv::Point2f disp1;
00705                         
00706                         disp1.x = pts2.at(xxx).x - pts1.at(xxx).x;
00707                         disp1.y = pts2.at(xxx).y - pts1.at(xxx).y;
00708                         
00709                         double totalDisplacement = pow(pow(disp1.x,2.0)+pow(disp1.y,2.0),0.5);
00710                         
00711                         if (totalDisplacement > 100.0) {
00712                                 printf("%s << Point (%d) predicted from (%f, %f) to (%f, %f)\n", __FUNCTION__, xxx, pts1.at(xxx).x, pts1.at(xxx).y, pts2.at(xxx).x, pts2.at(xxx).y);
00713                         }
00714 
00715                         
00716                 }
00717                 */
00718                 
00719                 cv::calcOpticalFlowPyrLK(im1b, im2, pts1, pts2, statusVec, err, winSize, maxLevel, criteria, opticalFlowFlags, thresh);
00720                 checkDistances(originalEstimates, pts2, statusVec, (double) distanceConstraint);
00721                 if (debugFlag) { printf("%s << After.\n", __FUNCTION__); }
00722 
00723                 //printf("%s << (%d) vs (%d)\n", __FUNCTION__, originalEstimates.size(), pts2.size());
00724                 
00725                 /*
00726                 for (unsigned int xxx = 0; xxx < pts1.size(); xxx++) {
00727                         
00728                         
00729                         
00730                         cv::Point2f disp1;
00731                         
00732                         disp1.x = pts2.at(xxx).x - pts1.at(xxx).x;
00733                         disp1.y = pts2.at(xxx).y - pts1.at(xxx).y;
00734                         
00735                         double totalDisplacement = pow(pow(disp1.x,2.0)+pow(disp1.y,2.0),0.5);
00736                         
00737                         if (totalDisplacement > 100.0) {
00738                                 printf("%s << Point displaced: (%f) : winSize = (%d, %d), (%d)\n", __FUNCTION__, totalDisplacement, winSize.width, winSize.height, guiding);
00739                                 
00740                                 printf("%s << Point (%d) from (%f, %f) to (%f, %f) -> (%f, %f) with (%d, %f)\n", __FUNCTION__, xxx, pts1.at(xxx).x, pts1.at(xxx).y, originalEstimates.at(xxx).x, originalEstimates.at(xxx).y, pts2.at(xxx).x, pts2.at(xxx).y, statusVec.at(xxx), err.at(xxx));
00741                         }
00742 
00743                         
00744                 }
00745                 */
00746                 
00747                 if (debugFlag) {
00748                         
00749                         printf("%s << winSize = (%d, %d)\n", __FUNCTION__, winSize.width, winSize.height);
00750                         
00751                         cv::Mat a, b;
00752                         
00753                         displayKeyPoints(im2, pts1, a, CV_RGB(255,0,0), 0);
00754                         displayKeyPoints(im2, pts2, b, CV_RGB(0,0,255), 0);
00755                         
00756                         if /*while*/ (1) {
00757                                 
00758                                 imshow("test1", a);
00759                                 cv::waitKey(1);
00760                                 imshow("test2", b);
00761                                 cv::waitKey(1);
00762                                 
00763                                 printf("%s << After flow: %d good out of / %lu\n", __FUNCTION__, cv::countNonZero(statusVec), statusVec.size());
00764                         }
00765                         
00766                         //for (unsigned int iii = 0; iii < pts1.size(); iii++) {
00767                                 // printf("%s << pts1.at(%d) = [%f, %f]; pts2.at(%d) = [%f, %f]\n", __FUNCTION__, iii, pts1.at(iii).x, pts1.at(iii).y, iii, pts2.at(iii).x, pts2.at(iii).y);
00768                         //}
00769                         
00770                         
00771                 }
00772                 
00773                 //for (unsigned int iii = 0; iii < pts1.size(); iii++) {
00774                         //printf("%s << pt(%d) = (%f, %f) vs (%f, %f)\n", __FUNCTION__, iii, pts1.at(iii).x, pts1.at(iii).y, pts2.at(iii).x, pts2.at(iii).y);
00775                 //}
00776                 
00777                 //testTime = timeElapsedMS(test_timer, false);
00778                 //printf("XDebug 2b: (%f)\n", testTime);
00779 
00780                 //markStationaryPoints(pts1, pts2, statusVec);
00781                 
00782                 //printf("%s << After stationary: %d\n", __FUNCTION__, cv::countNonZero(statusVec));
00783                 
00784                 markAbsentPoints(pts1, pts2, statusVec, im1.size());
00785                 
00786                 if (debugFlag) {
00787                         printf("%s << After absent: %d\n", __FUNCTION__, cv::countNonZero(statusVec));
00788                 }
00789                 
00790 
00791         }
00792         
00793         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 6); }
00794         
00795         //testTime = timeElapsedMS(test_timer, false);
00796         //printf("XDebug 3: (%f)\n", testTime);
00797 
00798         
00799         if (camData.Kx.rows != 0) {
00800                 markEdgyTracks(pts2, statusVec, camData);
00801 
00802                 //printf("%s << After edge filtering: %d\n", __FUNCTION__, cv::countNonZero(statusVec));
00803         }
00804         
00805         //testTime = timeElapsedMS(test_timer, false);
00806         //printf("XDebug 4: (%f)\n", testTime);
00807 
00808         //markBlandTracks(im2, pts2, statusVec, 1.0);
00809 
00810         //testTime = timeElapsedMS(test_timer, false);
00811         //printf("XDebug 5: (%f)\n", testTime);
00812 
00813         //printf("%s << After bland filtering: %d\n", __FUNCTION__, cv::countNonZero(statusVec));
00814 
00815         //markUnrefinedPoints(pts2, statusVec);
00816 
00817         //printf("%s << After unrefined filtering: %d\n", __FUNCTION__, cv::countNonZero(statusVec));
00818 
00819         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 7); }
00820 
00821         if (warping) {
00822                 if (debugFlag) { printf("%s << W: pts1.size() = %u [before filtering]\n", __FUNCTION__, pts1.size()); }
00823                 if (debugFlag) { printf("%s << Debug (%d.%d) : (%u, %u)\n", __FUNCTION__, 7, 1, pts1.size(), pts2.size()); }
00824                 filterVectors(pts1, pts2, statusVec, ((double) std::max(im1.rows, im1.cols)), true);
00825                 if (debugFlag) { printf("%s << Debug (%d.%d)\n", __FUNCTION__, 7, 2); }
00826                 
00827                 if (debugFlag) { printf("%s << Debug (%d.%d)\n", __FUNCTION__, 7, 2); }
00828 
00829                 if (0) {
00830 
00831                         cv::Mat im1x, im2x;
00832                         //warpPerspective(grayImageBuffer[(current_idx-1) % MAXIMUM_FRAMES_TO_STORE], im2, H12, grayImageBuffer[(current_idx-1) % MAXIMUM_FRAMES_TO_STORE].size());
00833 
00834                         im1.copyTo(im1x);
00835                         im2.copyTo(im2x);
00836 
00837                         displayKeyPoints(im1, pts1, im1x, CV_RGB(255,0,0), 0);
00838                         displayKeyPoints(im2x, pts2, im2x, CV_RGB(255,0,0), 0);
00839 
00840                         //warpPerspective(im1, im1b, H12, im1.size());
00841 
00842                         while (1) {
00843 
00844                                 imshow("temp_disp", im1x);      // Previous image with features
00845                                 cv::waitKey(500);
00846                                 imshow("temp_disp", im2x);      // Current image
00847                                 cv::waitKey(500);
00848 
00849                         }
00850                 }
00851         } else {
00852                 if (debugFlag) { printf("%s << pts1.size() = %u [before filtering]\n", __FUNCTION__, pts1.size()); }
00853                 //printf("%s << passed distanceConstraint = %d\n", __FUNCTION__, distanceConstraint);
00854                 if (debugFlag) { printf("%s << Debug (%d.%d)\n", __FUNCTION__, 7, 3); }
00855                 
00856                 if (guiding) {
00857                         filterVectors(pts1, pts2, statusVec, ((double) std::max(im1.rows, im1.cols)), true);
00858                 } else {
00859                         filterVectors(pts1, pts2, statusVec, ((double) distanceConstraint));
00860                 }
00861                 
00862                 if (debugFlag) { printf("%s << Debug (%d.%d)\n", __FUNCTION__, 7, 4); }
00863                 if (debugFlag) { printf("%s << pts1.size() = %d [after filtering]\n", __FUNCTION__, pts1.size()); }
00864 
00865                 if (debugFlag) { printf("%s << Debug (%d.%d)\n", __FUNCTION__, 7, 4); }
00866 
00867                 //printf("%s << After full filtering: %d\n", __FUNCTION__, pts2.size());
00868 
00869                 if (0) { // (pts2.size() < 5) {
00870 
00871                         cv::Mat im1x, im2x;
00872                         //warpPerspective(grayImageBuffer[(current_idx-1) % MAXIMUM_FRAMES_TO_STORE], im2, H12, grayImageBuffer[(current_idx-1) % MAXIMUM_FRAMES_TO_STORE].size());
00873 
00874                         cvtColor(im1b, im1x, CV_GRAY2RGB);
00875                         cvtColor(im2, im2x, CV_GRAY2RGB);
00876 
00877                         displayKeyPoints(im1x, originalPts, im1x, CV_RGB(255,0,0), 0);
00878                         displayKeyPoints(im2x, pts2, im2x, CV_RGB(255,0,0), 0);
00879 
00880                         //warpPerspective(im1, im1b, H12, im1.size());
00881 
00882                         while (1) {
00883 
00884                                 imshow("temp_disp", im1b);      // Previous image with features
00885                                 cv::waitKey(1500);
00886                                 imshow("temp_disp", im2x);      // Current image
00887                                 cv::waitKey(500);
00888 
00889                         }
00890                 }
00891 
00892         }
00893         
00894         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 8); }
00895         
00896         //testTime = timeElapsedMS(test_timer, false);
00897         //printf("XDebug 6: (%f)\n", testTime);
00898 
00899         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
00900                 if (statusVec.at(iii) == 0) {
00901                         lostIndices.push_back(iii);
00902                 }
00903         }
00904         
00905         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 9); }
00906         
00907         //testTime = timeElapsedMS(test_timer, false);
00908         //printf("XDebug 7: (%f)\n", testTime);
00909 
00910 }
00911 
00912 //HGH
00913 void trackPoints2(const cv::Mat& im1, const cv::Mat& im2, vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, int distanceConstraint, double thresh, vector<unsigned int>& lostIndices, const cv::Size patternSize, double& errorThreshold) {
00914 
00915 
00916         unsigned int corners = patternSize.width * patternSize.height;
00917 
00918         bool debugFlag = false;
00919 
00920         if (debugFlag) {
00921                 printf("%s << ENTERED!\n", __FUNCTION__);
00922         }
00923 
00924         if (pts1.size() == 0) {
00925                 return;
00926         }
00927 
00928         if ((distanceConstraint % 2) == 0) {
00929                 distanceConstraint++;
00930         }
00931 
00932         cv::Size winSize = cv::Size(distanceConstraint, distanceConstraint);
00933         int maxLevel = 3;
00934         cv::TermCriteria criteria = cv::TermCriteria( cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 30, 0.01);
00935 
00936         cv::Mat im1b;
00937         cv::Mat blank;
00938 
00939         vector<uchar> statusVec;
00940         vector<float> err;
00941 
00942         blank = cv::Mat::ones(im1.size(), CV_8UC1);
00943         blank *= 255;
00944 
00945 
00946         vector<cv::Point2f> originalPts;
00947         originalPts.insert(originalPts.end(), pts1.begin(), pts1.end());
00948 
00949         im1b = cv::Mat(im1); // .copyTo(im1b);
00950 
00951         pts2.clear();
00952         pts2.insert(pts2.end(), pts1.begin(), pts1.end());
00953 
00954         int opticalFlowFlags = cv::OPTFLOW_USE_INITIAL_FLOW + CV_LKFLOW_GET_MIN_EIGENVALS; // + OPTFLOW_LK_GET_MIN_EIGENVALS;
00955 
00956                 //printf("%s << Before. (%d, %d) (%d, %d) (%d) (%d, %d)\n", __FUNCTION__, im1b.rows, im1b.cols, im2.rows, im2.cols, pts1.size(), winSize.height, winSize.width);
00957         cv::calcOpticalFlowPyrLK(im1b, im2, pts1, pts2, statusVec, err, winSize, maxLevel, criteria, opticalFlowFlags, thresh);
00958 
00959         if (corners != statusVec.size() || corners != err.size()){
00960             lostIndices.push_back(-1);
00961         }
00962 
00963         //cout << *max_element(err.begin(),err.end()) << endl;
00964         for (unsigned int iii = 0; iii < err.size(); iii++) {
00965 
00966             if (err.at(iii) > errorThreshold && errorThreshold != 0.0){
00967                 //cout << err.at(iii)  <<   " for  "  << iii << endl;
00968                 lostIndices.push_back(-2);
00969             }
00970         }
00971 
00972         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
00973             if (statusVec.at(iii) == 0) {
00974                 lostIndices.push_back(iii);
00975             }
00976         }
00977 
00978 
00979 }
00980 
00981 void markAbsentPoints(vector<cv::Point2f>&pts1, vector<cv::Point2f>&pts2, vector<uchar>&statusVec, cv::Size imSize) {
00982 
00983         float buffer = 2.0;
00984 
00985         #pragma omp parallel for
00986         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
00987 
00988                 if (statusVec.at(iii) != 0) {
00989 
00990                         if ((pts1.at(iii).x < buffer) || (pts1.at(iii).x > imSize.width - buffer)) {
00991                                 statusVec.at(iii) = 0;
00992                         } else if ((pts2.at(iii).x < buffer) || (pts2.at(iii).x > imSize.width - buffer)) {
00993                                 statusVec.at(iii) = 0;
00994                         } else if ((pts1.at(iii).y < buffer) || (pts1.at(iii).y > imSize.height - buffer)) {
00995                                 statusVec.at(iii) = 0;
00996                         } else if ((pts2.at(iii).y < buffer) || (pts2.at(iii).y > imSize.height - buffer)) {
00997                                 statusVec.at(iii) = 0;
00998                         }
00999 
01000                 }
01001 
01002         }
01003 
01004 }
01005 
01006 bool constructPatch(cv::Mat& img, cv::Mat& patch, cv::Point2f& center, double radius, int cells) {
01007 
01008     //printf("%s << ENTERED.\n", __FUNCTION__);
01009 
01010         patch.release();
01011 
01012     if ((cells % 2) == 0) {
01013         cells++;
01014     }
01015 
01016     patch = cv::Mat::zeros(cells, cells, CV_64FC1);
01017 
01018     int range = (cells-1)/2;
01019 
01020         for (int iii = -range; iii <= +range; iii++) {
01021                 for (int jjj = -range; jjj <= +range; jjj++) {
01022 
01023                         cv::Point2f currPt = cv::Point2f(center.x + ((double) iii)*radius, center.y + ((double) jjj)*radius);
01024 
01025                         //printf("%s << currPt = (%f, %f)\n", __FUNCTION__, currPt.x, currPt.y);
01026 
01027                         if ((currPt.x <= 0.0) || (currPt.x >= ((double) img.cols)) || (currPt.y >= ((double) img.rows)) || (currPt.y <= 0.0)) {
01028                                 return false;
01029                         }
01030 
01031             //printf("%s << Extracting (%f, %f) of (%d, %d)\n", __FUNCTION__, currPt.x, currPt.y, img.cols, img.rows);
01032                         double val = getInterpolatedVal(img, currPt);
01033                         //printf("%s << Assigning (%d, %d) of (%d, %d)\n", __FUNCTION__, iii+range, jjj+range, cells, cells);
01034                         patch.at<double>(iii+range,jjj+range) = val;
01035 
01036                 }
01037         }
01038 
01039         //printf("%s << EXITING.\n", __FUNCTION__);
01040 
01041         return true;
01042 
01043 }
01044 
01045 
01046 void extendKeyPoints(cv::Mat& img, vector<cv::KeyPoint>& pts, bool updateStrength, bool updateLocation) {
01047 
01048         if (updateLocation) {
01049                 // Use cornersubpix to refine locations
01050 
01051                 vector<cv::Point2f> candidates;
01052                 cv::KeyPoint::convert(pts, candidates);
01053 
01054                 cv::cornerSubPix(img, candidates, cv::Size(1,1), cv::Size(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1));
01055 
01056                 #pragma omp parallel for
01057                 for (unsigned int iii = 0; iii < candidates.size(); iii++) {
01058                         pts.at(iii).pt = candidates.at(iii);
01059                 }
01060 
01061         }
01062 
01063         if (updateStrength) {
01064 
01065 
01066                 #pragma omp parallel for
01067                 for (unsigned int iii = 0; iii < pts.size(); iii++) {
01068                         double radius = ((double) pts.at(iii).size) / 2.0;
01069                         double salience = estimateSalience(img, pts.at(iii).pt, radius);
01070                         pts.at(iii).response = salience;
01071                 }
01072 
01073         }
01074 
01075 }
01076 
01077 double estimateSalience(cv::Mat& img, cv::Point2f& center, double radius) {
01078 
01079         // Assumes 8-bit image
01080         double salience = 0.0;
01081 
01082 
01083 
01084         // Find center
01085         //cv::Point center = Point(((int) kp.pt.x), ((int) kp.pt.y));
01086 
01087         // Find radius
01088 
01089 
01090         if (((center.x - radius) < 0) || ((center.y - radius) < 0) || ((center.x + radius) >= img.cols) || ((center.y + radius) >= img.rows)) {
01091                 return salience;
01092         }
01093 
01094         cv::Mat patch;
01095         int patchSize = radius * 2;
01096         if ((patchSize % 2) == 0) {
01097         //patchSize++;
01098         }
01099 
01100         constructPatch(img, patch, center, radius, patchSize);
01101         //cout << patch << endl;
01102 
01103         salience = getValueFromPatch(patch);
01104 
01105 
01106         return salience;
01107 
01108 }
01109 
01110 double getValueFromPatch(cv::Mat& patch) {
01111 
01112     cv::Mat convertedPatch = cv::Mat::zeros(patch.size(), CV_32FC1);
01113 
01114         #pragma omp parallel for
01115         for (int iii = 0; iii < patch.rows; iii++) {
01116                 for (int jjj = 0; jjj < patch.cols; jjj++) {
01117                         convertedPatch.at<float>(iii,jjj) = ((float) patch.at<double>(iii,jjj));
01118                 }
01119         }
01120 
01121     cv::Mat eigenMat;
01122         cornerMinEigenVal(convertedPatch, eigenMat, patch.rows, CV_SCHARR);
01123 
01124     double eigenValue = 0.0, blankVal;
01125 
01126     minMaxLoc(eigenMat, &blankVal, &eigenValue);
01127 
01128         /*
01129     for (int iii = 0; iii < patch.rows; iii++) {
01130                 for (int jjj = 0; jjj < patch.cols; jjj++) {
01131                         //eigenValue += eigenMat.at<float>(iii,jjj) / ((float) (eigenMat.rows * eigenMat.cols));
01132                 }
01133         }
01134         */
01135         return eigenValue;
01136 
01137 }
01138 
01139 void markUnrefinedPoints(vector<cv::Point2f>& pts, vector<uchar>&statusVec) {
01140 
01141         if (pts.size() == 0) {
01142                 return;
01143         }
01144 
01145         #pragma omp parallel for
01146         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
01147 
01148                 if (statusVec.at(iii) != 0) {
01149 
01150                         if (((pts.at(iii).x - floor(pts.at(iii).x)) == 0.0) && ((pts.at(iii).y - floor(pts.at(iii).y)) == 0.0)) {
01151                                 statusVec.at(iii) = 0;
01152                         }
01153 
01154                 }
01155         }
01156 
01157 }
01158 
01159 
01160 void markBlandTracks(cv::Mat& img, vector<cv::Point2f>& pts, vector<uchar>& statusVec, double thresh) {
01161 
01162         if (pts.size() == 0) {
01163                 return;
01164         }
01165 
01166         cv::Mat patch;
01167         
01168         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
01169 
01170                 if (statusVec.at(iii) != 0) {
01171 
01172                         constructPatch(img, patch, pts.at(iii), 1.5);
01173                         //cout << patch << endl;
01174 
01175                         double salience = getValueFromPatch(patch);
01176 
01177                         //printf("%s << pts.at(%d).response = %f (%f)\n", __FUNCTION__, iii, pts.at(iii).response, thresh);
01178 
01179                         if (salience < thresh) {
01180                                 statusVec.at(iii) = 0;
01181                         }
01182 
01183 
01184                 }
01185         }
01186 
01187 
01188 }
01189 
01190 void filterBlandKeyPoints(cv::Mat& img, vector<cv::KeyPoint>& pts, double thresh) {
01191 
01192         if (pts.size() == 0) {
01193                 return;
01194         }
01195 
01196         for (int iii = pts.size()-1; iii >= 0; iii--) {
01197 
01198                 //printf("%s << pts.at(%d).response = %f (%f)\n", __FUNCTION__, iii, pts.at(iii).response, thresh);
01199 
01200                 if (pts.at(iii).response < thresh) {
01201                         pts.erase(pts.begin() + iii);
01202                 }
01203 
01204         }
01205 
01206 }
01207 
01208 void markStationaryPoints(vector<cv::Point2f>&pts1, vector<cv::Point2f>&pts2, vector<uchar>&statusVec) {
01209 
01210         #pragma omp parallel for
01211         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
01212 
01213                 if (statusVec.at(iii) != 0) {
01214 
01215                         double absDifference = pow(pow(pts1.at(iii).x - pts2.at(iii).x, 2.0) + pow(pts1.at(iii).y - pts2.at(iii).y, 2.0), 0.5);
01216 
01217                         //printf("%s << absDifference = %f\n", __FUNCTION__, absDifference);
01218 
01219                         if (absDifference == 0.0) {
01220                                 statusVec.at(iii) = 0;
01221                         }
01222 
01223                 }
01224         }
01225 
01226 }
01227 
01228 void displayKeyPoints(const cv::Mat& image, const vector<cv::KeyPoint>& KeyPoints, cv::Mat& outImg, const cv::Scalar& color, int thickness, bool pointsOnly) {
01229 
01230     bool randomColours = (color == cv::Scalar::all(-1));
01231 
01232     cv::Scalar newColour;
01233 
01234     if (!randomColours) {
01235         newColour = color;
01236     }
01237 
01238     image.copyTo(outImg);
01239 
01240     //printf("%s << DEBUG %d\n", __FUNCTION__, 0);
01241 
01242         /*
01243     if (image.channels() < 3) {
01244         cvtColor(image, outImg, CV_GRAY2RGB);
01245     } else {
01246         image.copyTo(outImg);
01247     }
01248 
01249     */
01250 
01251     //printf("%s << DEBUG %d\n", __FUNCTION__, 1);
01252 
01253     cv::Point centerPt;
01254 
01255     int radius, crossLength; //, aimedSize;
01256 
01257     if (thickness == 0) {
01258         thickness = 1;
01259     }
01260 
01261     // New method:
01262         for (unsigned int i = 0; i < KeyPoints.size(); i++) {
01263                 //int colorCoeff = (int)( (255.0 * ((double) KeyPoints.size() - (double)i)) / (double) KeyPoints.size());
01264 
01265                 //printf("%s << %d: c = %d\n", __FUNCTION__, i, colorCoeff);
01266                 //cin.get();
01267         newColour = color; // CV_RGB(255, 255-colorCoeff, 0);
01268 
01269         //printf("%s << DEBUG %d_%d\n", __FUNCTION__, 2, i);
01270 
01271         centerPt = KeyPoints.at(i).pt;
01272 
01273         centerPt.x *= 16.0;
01274         centerPt.y *=16.0;
01275 
01276         //aimedSize = 6 - ((int) 4.0*((double) i / (double) pts.size()));
01277 
01278 
01279         //radius = KeyPoints.at(i).size/2;
01280 
01281         //aimedSize = 6 - ((int) 4.0*((double) i / (double) KeyPoints.size()));
01282         radius = 16.0 * (KeyPoints.at(i).size/2.0); // 2
01283         //thickness = 3 - ((int) 2.0*((double) i / (double) KeyPoints.size()));
01284         //crossLength = int (1.5 * (double) aimedSize);
01285         crossLength = 2 * 16.0;
01286         
01287         if (pointsOnly) {
01288                         circle(outImg, centerPt, 1, newColour, 2, CV_AA, 4);
01289                 } else {
01290                          if (radius > 0) {
01291                                 circle(outImg, centerPt, radius, newColour, thickness, CV_AA, 4);
01292                         }
01293 
01294                         line(outImg, cv::Point(centerPt.x-crossLength, centerPt.y), cv::Point(centerPt.x+crossLength, centerPt.y), newColour, thickness, CV_AA, 4);
01295                         line(outImg, cv::Point(centerPt.x, centerPt.y-crossLength), cv::Point(centerPt.x, centerPt.y+crossLength), newColour, thickness, CV_AA, 4);
01296 
01297                 }
01298 
01299        
01300         //printf("%s << DEBUG %d_X_%d\n", __FUNCTION__, 2, i);
01301 
01302         //imshow("tempWin", outImg);
01303 
01304         //cv::waitKey(200);
01305 
01306     }
01307 
01308     return;
01309 
01310 }
01311 
01312 void displayKeyPoints(const cv::Mat& image, const vector<cv::Point2f>& pts, cv::Mat& outImg, cv::Scalar color, int thickness, bool pointsOnly) {
01313 
01314     bool randomColours = (color == cv::Scalar::all(-1));
01315 
01316     cv::Scalar newColour;
01317 
01318     if (!randomColours) {
01319         newColour = color;
01320     }
01321 
01322     image.copyTo(outImg);
01323 
01324     cv::Point centerPt;
01325 
01326     if (thickness == 0) {
01327         thickness = 1;
01328     }
01329 
01330     int crossLength; //, aimedSize;
01331 
01332     // New method:
01333         for (unsigned int i = 0; i < pts.size(); i++) {
01334 
01335         centerPt.x = pts.at(i).x * 16.0;
01336         centerPt.y = pts.at(i).y * 16.0;
01337 
01338         //aimedSize = 6 - ((int) 4.0*((double) i / (double) pts.size()));
01339         crossLength = 2 * 16.0;
01340 
01341                 if (pointsOnly) {
01342                         circle(outImg, centerPt, 1, color, 2, CV_AA, 4);
01343                 } else {
01344                         line(outImg, cv::Point(centerPt.x-crossLength, centerPt.y), cv::Point(centerPt.x+crossLength, centerPt.y), color, thickness, CV_AA, 4);
01345                         line(outImg, cv::Point(centerPt.x, centerPt.y-crossLength), cv::Point(centerPt.x, centerPt.y+crossLength), color, thickness, CV_AA, 4);
01346                 }
01347 
01348         
01349 
01350 
01351     }
01352 
01353     return;
01354 
01355 }
01356 
01357 void sortKeyPoints(vector<cv::KeyPoint>& KeyPoints, unsigned int maxKeyPoints) {
01358     vector<cv::KeyPoint> sortedKeyPoints;
01359 
01360     if (KeyPoints.size() <= 1) {
01361         return;
01362     }
01363 
01364     // Add the first one
01365     sortedKeyPoints.push_back(KeyPoints.at(0));
01366 
01367     for (unsigned int i = 1; i < KeyPoints.size(); i++) {
01368 
01369         unsigned int j = 0;
01370         bool hasBeenAdded = false;
01371 
01372         while ((j < sortedKeyPoints.size()) && (!hasBeenAdded)) {
01373 
01374             if (abs(KeyPoints.at(i).response) > abs(sortedKeyPoints.at(j).response)) {
01375                 sortedKeyPoints.insert(sortedKeyPoints.begin() + j, KeyPoints.at(i));
01376 
01377                 hasBeenAdded = true;
01378             }
01379 
01380             j++;
01381         }
01382 
01383         if (!hasBeenAdded) {
01384             sortedKeyPoints.push_back(KeyPoints.at(i));
01385         }
01386 
01387     }
01388 
01389 
01390 
01391     KeyPoints.swap(sortedKeyPoints);
01392 
01393     if (maxKeyPoints < KeyPoints.size()) {
01394         KeyPoints.erase(KeyPoints.begin()+maxKeyPoints, KeyPoints.end());
01395     }
01396 
01397     return;
01398 
01399 }
01400 
01401 void sortMatches(vector<vector<cv::DMatch> >& matches1to2) {
01402         vector<vector<cv::DMatch> > matchesCpy, newMatches;
01403 
01404         if (matches1to2.size() <= 1) {
01405                 return;
01406         }
01407 
01408         matchesCpy.assign(matches1to2.begin(), matches1to2.end());
01409 
01410         while (matchesCpy.size() > 0) {
01411                 double bestDistance = matchesCpy.at(0).at(0).distance;
01412                 int bestIndex = 0;
01413 
01414                 for (unsigned int iii = 0; iii < matchesCpy.size(); iii++) {
01415 
01416                         if (matchesCpy.at(iii).at(0).distance <= bestDistance) {
01417                                 bestDistance = matchesCpy.at(iii).at(0).distance;
01418                                 bestIndex = iii;
01419                         }
01420                 }
01421 
01422                 newMatches.push_back(matchesCpy.at(bestIndex));
01423                 matchesCpy.erase(matchesCpy.begin() + bestIndex);
01424         }
01425 
01426         newMatches.swap(matches1to2);
01427 }
01428 
01429 void filterMatches(vector<vector<cv::DMatch> >& matches1to2, double threshold) {
01430 
01431         if (matches1to2.size() == 0) {
01432                 return;
01433         }
01434 
01435         int currIndex = matches1to2.size() - 1;
01436 
01437         while (matches1to2.at(currIndex).at(0).distance > threshold) {
01438                 currIndex--;
01439 
01440                 if (currIndex == -1) {
01441                         matches1to2.clear();
01442                         return;
01443                 }
01444         }
01445 
01446         if (currIndex < ((int) matches1to2.size() - 1)) {
01447                         matches1to2.erase(matches1to2.begin() + currIndex + 1, matches1to2.end());
01448         }
01449 
01450 
01451 }
01452 
01453 double distanceBetweenPoints(const cv::Point2f& pt1, const cv::Point2f& pt2) {
01454         double retVal;
01455 
01456         retVal = pow(pow(pt1.x - pt2.x, 2.0) + pow(pt1.y - pt2.y, 2.0), 0.5);
01457 
01458         return retVal;
01459 
01460 }
01461 
01462 double distanceBetweenPoints(const cv::KeyPoint& pt1, const cv::KeyPoint& pt2) {
01463         double retVal; //, a, b, c, d;
01464 
01465         /*
01466         a = pow(pt1.pt.x - pt2.pt.x, 2.0);
01467         b = pow(pt1.pt.y - pt2.pt.y, 2.0);
01468         c = pt1.pt.x - pt2.pt.x;
01469         d = pt1.pt.y - pt2.pt.y;
01470         */
01471 
01472         //printf("%s << %f %f %f %f %f\n", __FUNCTION__, retVal, a, b, c, d);
01473 
01474         retVal = pow(pow(pt1.pt.x - pt2.pt.x, 2.0) + pow(pt1.pt.y - pt2.pt.y, 2.0), 0.5);
01475 
01476         return retVal;
01477 }
01478 
01479 void constrainMatchingMatrix(cv::Mat& matchingMatrix, vector<cv::KeyPoint>& kp1, vector<cv::KeyPoint>& kp2, int distanceConstraint, double sizeConstraint) {
01480 
01481         
01482 
01483         #pragma omp parallel for
01484         for (unsigned int iii = 0; iii < kp1.size(); iii++) {
01485                 for (unsigned int jjj = 0; jjj < kp2.size(); jjj++) {
01486                         // Check distance constraint
01487                         
01488                         int distanceBetween;
01489 
01490                         distanceBetween = (int) distanceBetweenPoints(kp1.at(iii), kp2.at(jjj));
01491                         //printf("%s << distance (%d, %d) = %d (%f) vs %d\n", __FUNCTION__, iii, jjj, distanceBetween, distanceBetweenPoints(kp1.at(iii), kp2.at(jjj)), distanceConstraint);
01492 
01493                         if (distanceBetween > distanceConstraint) {
01494                                 matchingMatrix.at<double>(iii,jjj) = -1;
01495                         }
01496 
01497                         //printf("%s << diameter = %f vs %f\n", __FUNCTION__, kp1.at(iii).size, kp2.at(jjj).size);
01498 
01499                         if (sizeConstraint != 0.0) {
01500                                 if (max(kp1.at(iii).size/kp2.at(jjj).size, kp2.at(jjj).size/kp1.at(iii).size) > (1.00 + sizeConstraint)) {
01501                                         matchingMatrix.at<double>(iii,jjj) = -1;
01502                                 }
01503                         }
01504                         //cin.get();
01505                 }
01506 
01507                 //cin.get();
01508         }
01509 
01510 
01511 }
01512 
01513 void twoWayPriorityMatching(cv::Mat& matchingMatrix, vector<vector<cv::DMatch> >& bestMatches, int mode) {
01514 
01515         bestMatches.clear();
01516 
01517     // void getPriorityScores(Mat& matchingMatrix, vector<vector<double> >& priorityScores, vector<vector<int> >& priorityMatches);
01518 
01519     // Potentially more efficient way of doing things:
01520         // Just search matrix for lowest match score, and record the next best in that 'cross' and blank out that cross,
01521         // then search for the lowest match score remaining in the matrix and so on and so forth...
01522         //
01523         // Actually many-many, 1-many, 1-1 can all use this basic approach, but just with different "blanking" strategies
01524         // e.g. 1-many would blank out the entire column, but not row
01525         // only many-many would not be able to record a valid "second best" score
01526             // and many-many would also have N^2 matches rather than just N for the others...
01527 
01528         bool rowsStillRemain = false;
01529         int remainingRows = 0;
01530 
01531         //printf("%s << Entered function.\n", __FUNCTION__);
01532 
01533 
01534         for (int iii = 0; iii < matchingMatrix.rows; iii++) {
01535                 bool anyInThisRow = false;
01536                 for (int jjj = 0; jjj < matchingMatrix.cols; jjj++) {
01537                         if (matchingMatrix.at<double>(iii,jjj) >= 0) {
01538                                 rowsStillRemain = true;
01539                                 anyInThisRow = true;
01540                         }
01541                 }
01542 
01543                 if (anyInThisRow) {
01544                         remainingRows++;
01545                 }
01546 
01547         }
01548 
01549         //printf("%s << remainingRows = %d\n", __FUNCTION__, remainingRows);
01550 
01551         while (rowsStillRemain) {
01552 
01553                 double bestScore = 9e99;
01554                 int bestRow = -1, bestCol = -1;
01555 
01556                 for (int iii = 0; iii < matchingMatrix.rows; iii++) {
01557                         for (int jjj = 0; jjj < matchingMatrix.cols; jjj++) {
01558                                 if ((matchingMatrix.at<double>(iii,jjj) <= bestScore) && (matchingMatrix.at<double>(iii,jjj) >= 0)) {
01559                                         bestScore = matchingMatrix.at<double>(iii,jjj);
01560                                         bestRow = iii;
01561                                         bestCol = jjj;
01562                                 }
01563                         }
01564                 }
01565 
01566                 if ((bestScore < 0) || (bestScore == 9e99)) {
01567                         rowsStillRemain = false;
01568                         break;
01569                 }
01570 
01571                 matchingMatrix.at<double>(bestRow,bestCol) = -1.0;
01572                 //matchingMatrixCpy.at<double>(bestRow,bestCol) = -1.0;
01573 
01574                 cv::DMatch currentMatch;
01575                 vector<cv::DMatch> currentMatchVector;
01576 
01577                 currentMatch.queryIdx = bestRow;
01578                 currentMatch.trainIdx = bestCol;
01579 
01580                 double secondScore = 9e99;
01581                 //int secondRow = -1, secondCol = -1;
01582 
01583                 for (int iii = 0; iii < matchingMatrix.rows; iii++) {
01584                         if ((matchingMatrix.at<double>(iii,bestCol) <= secondScore) && (matchingMatrix.at<double>(iii,bestCol) >= 0)) {
01585                                 secondScore = matchingMatrix.at<double>(iii,bestCol);
01586                                 //secondRow = iii;
01587                                 //secondCol = bestCol;
01588                         }
01589                         matchingMatrix.at<double>(iii,bestCol) = -1;
01590                 }
01591 
01592                 for (int iii = 0; iii < matchingMatrix.cols; iii++) {
01593                         if ((matchingMatrix.at<double>(bestRow,iii) <= secondScore) && (matchingMatrix.at<double>(bestRow,iii) >= 0)) {
01594                                 secondScore = matchingMatrix.at<double>(bestRow,iii);
01595                                 //secondRow = bestRow;
01596                                 //secondCol = iii;
01597                         }
01598                         matchingMatrix.at<double>(bestRow,iii) = -1;
01599                 }
01600 
01601                 // If it is literally the last match available, it won't have a second best score...
01602                 if (secondScore == 9e99) {
01603                         secondScore = bestScore;
01604                 }
01605 
01606                 // Then normalize the "distance" based on this ratio, or can just use the ratio...
01607                 //currentMatch.distance = bestScore;
01608                 
01609                 if (mode == MATCHING_MODE_NN) {
01610                         currentMatch.distance = bestScore;
01611                 } else if (mode == MATCHING_MODE_NNDR) {
01612                         currentMatch.distance = bestScore / secondScore;
01613                 } else if (mode == MATCHING_MODE_SVM) {
01614                         double gradient = -1.42;
01615                         currentMatch.distance = reweightDistanceWithLinearSVM(bestScore, (bestScore/secondScore), gradient);
01616                 } else {
01617                         currentMatch.distance = bestScore;
01618                 }
01619                 
01620                 
01621                 
01622 
01623                 currentMatchVector.push_back(currentMatch);
01624                 bestMatches.push_back(currentMatchVector);
01625 
01626 
01627         }
01628 
01629         //printf("%s << bestMatches.size() = %d\n", __FUNCTION__, bestMatches.size());
01630         //cin.get();
01631 
01632 }
01633 
01634 double calcDistance(double dist, double ratio, double *coeffs) {
01635     double retVal = 0.0;
01636 
01637     retVal = abs(coeffs[0] * dist - ratio + coeffs[2]) / sqrt(pow(coeffs[0], 2) + 1);
01638 
01639     return retVal;
01640 }
01641 
01642 double reweightDistanceWithLinearSVM(double dist, double ratio, double gradient) {
01643     double retVal = 0.0;    // ratio
01644 
01645     retVal = dist - (1.0 / gradient) * ratio;
01646 
01647     return retVal;
01648 //
01649 //    double LineNeg1[3], LineZero[3], LinePos1[3];
01650 //
01651 //    LineNeg1[0] = LineZero[0] = LinePos1[0] = gradient;
01652 //    LineNeg1[1] = LineZero[1] = LinePos1[1] = -1;
01653 //    LineNeg1[2] = shift[0];
01654 //    LineZero[2] = shift[1];
01655 //    LinePos1[2] = shift[2];
01656 //
01657 //    // Find distance between lines
01658 //    //double negSeg = calcLinePerpDistance(LineNeg1, LineZero);
01659 //    //double posSeg = calcLinePerpDistance(LinePos1, LineZero);
01660 //
01661 //    //printf("%s << Distances between lines = (%f, %f)\n", __FUNCTION__, negSeg, posSeg);
01662 //
01663 //    // Find distance from point to negative line
01664 //    double negDist = calcDistance(dist, ratio, LineNeg1);
01665 //
01666 //    // Find distance from point to neutral line
01667 //    double zeroDist = calcDistance(dist, ratio, LineZero);
01668 //
01669 //    // Find distance from point to positive line
01670 //    double posDist = calcDistance(dist, ratio, LinePos1);
01671 //
01672 //    //printf("%s << distances = (%f, %f, %f)\n", __FUNCTION__, negDist, zeroDist, posDist);
01673 //    //cin.get();
01674 //
01675 //    if (posDist < negDist) {
01676 //        retVal = -1.0 * zeroDist;
01677 //    } else {
01678 //        retVal = +1.0 * zeroDist;
01679 //    }
01680 //
01681 //    retVal = pow(2.0, retVal);
01682 //
01683 //    // Assign total score
01684 //    //printf("%s << dist/ratio = (%f, %f), retVal = %f\n", __FUNCTION__, dist, ratio, retVal);
01685 //    //cin.get();
01686 //
01687 //
01688 //    return retVal;
01689 }
01690 
01691 void createMatchingMatrix(cv::Mat& matchingMatrix, const cv::Mat& desc1, const cv::Mat& desc2) {
01692 
01693     vector<vector<cv::DMatch> > matches1to2, matches2to1;
01694 
01695         cv::Ptr<cv::DescriptorMatcher> dMatcher;
01696 
01697         if (desc1.type() == CV_8UC1) {
01698                 dMatcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
01699         } else if ((desc1.type() == CV_64FC1) || (desc1.type() == CV_32FC1)) {
01700                 dMatcher = cv::DescriptorMatcher::create("BruteForce");
01701         } else {
01702                 printf("%s << ERROR! desc1.type() (%d) unrecognized.\n", __FUNCTION__, desc1.type());
01703         }
01704 
01705 
01706         //printf("%s << desc1.rows = %d; desc2.rows = %d\n", __FUNCTION__, desc1.rows, desc2.rows);
01707 
01708         dMatcher->knnMatch( desc1, desc2, matches1to2, desc1.rows );
01709         dMatcher->knnMatch( desc2, desc1, matches2to1, desc2.rows );
01710 
01711     /*
01712     Mat matMatDisp;
01713     matMatDisp = normForDisplay(matchingMatrix);
01714     imshow("testWin", matMatDisp);
01715     cv::waitKey();
01716     */
01717 
01718     matchingMatrix = cv::Mat::zeros(matches1to2.size(), matches2to1.size(), CV_64FC1);
01719 
01720     cv::Mat countMat = cv::Mat::zeros(matches1to2.size(), matches2to1.size(), CV_64FC1);
01721 
01722     // IM 1 to IM 2
01723     for (unsigned int iii = 0; iii < matches1to2.size(); iii++) {
01724         for (unsigned int jjj = 0; jjj < matches1to2[iii].size(); jjj++) {
01725             matchingMatrix.at<double>(iii, matches1to2.at(iii).at(jjj).trainIdx) += matches1to2.at(iii).at(jjj).distance;
01726             countMat.at<double>(iii, matches1to2.at(iii).at(jjj).trainIdx) += 1.0;
01727         }
01728     }
01729 
01730     // IM 2 to IM 1
01731     for (unsigned int iii = 0; iii < matches2to1.size(); iii++) {
01732         for (unsigned int jjj = 0; jjj < matches2to1[iii].size(); jjj++) {
01733             matchingMatrix.at<double>(matches2to1.at(iii).at(jjj).trainIdx, iii) += matches2to1.at(iii).at(jjj).distance;
01734             countMat.at<double>(matches2to1.at(iii).at(jjj).trainIdx, iii) += 1.0;
01735         }
01736     }
01737 
01738     /*
01739     Mat matMatDisp = normForDisplay(countMat);
01740     imshow("testWin", matMatDisp);
01741     cv::waitKey();
01742     */
01743 
01744     matchingMatrix /= 2.0;
01745 
01746 }
01747 
01748 void filterTrackedPoints(vector<uchar>& statusVec, vector<float>& err, double maxError) {
01749 
01750         for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
01751                 if (err.at(iii) > maxError) {
01752                         statusVec.at(iii) = 0;
01753                 }
01754         }
01755 
01756 }
01757 
01758 void randomlyReducePoints(vector<cv::Point2f>& pts, int maxFeatures) {
01759 
01760         srand (time(NULL) );
01761 
01762         if (((int) pts.size()) <= maxFeatures) {
01763                 return;
01764         }
01765 
01766         int randIndex;
01767 
01768         while (((int) pts.size()) > maxFeatures) {
01769                 randIndex = rand() % pts.size();
01770                 pts.erase(pts.begin() + randIndex);
01771         }
01772 
01773 }
01774 
01775 void checkDistances(vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, vector<uchar>& statusVec, double distanceConstraint) {
01776         
01777         double totalDist, xDist, yDist;
01778         
01779         for (unsigned int iii = 0; iii < pts1.size(); iii++) {
01780                 xDist = pts1.at(iii).x - pts2.at(iii).x;
01781                 yDist = pts1.at(iii).y - pts2.at(iii).y;
01782                 totalDist = pow((pow((xDist), 2.0) + pow((yDist), 2.0)), 0.5);
01783 
01784                 if (totalDist > distanceConstraint) {
01785                         statusVec.at(iii) = 0;
01786                 }
01787         }
01788         
01789 }
01790 
01791 void filterVectors(vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, vector<uchar>& statusVec, double distanceConstraint, bool epipolarCheck) {
01792 
01793         bool debugFlag = false;
01794         //printf("%s << sizes = (%d, %d)\n", __FUNCTION__, pts1.size(), pts2.size());
01795 
01796         double totalDist, xDist, yDist;
01797 
01798         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 1); }
01799 
01800         for (int iii = statusVec.size()-1; iii >= 0; iii--) {
01801                 if (statusVec.at(iii) == 0) {
01802                         pts1.erase(pts1.begin() + iii);
01803                         pts2.erase(pts2.begin() + iii);
01804                 } else {
01805                         // distance check
01806                         xDist = pts1.at(iii).x - pts2.at(iii).x;
01807                         yDist = pts1.at(iii).y - pts2.at(iii).y;
01808                         totalDist = pow((pow((xDist), 2.0) + pow((yDist), 2.0)), 0.5);
01809 
01810                         //printf("%s << totalDist (%f) ([%f, %f]) vs distanceConstraint (%f)\n", __FUNCTION__, totalDist, xDist, yDist, distanceConstraint);
01811 
01812                         if (totalDist > distanceConstraint) {
01813 
01814 
01815 
01816                                 pts1.erase(pts1.begin() + iii);
01817                                 pts2.erase(pts2.begin() + iii);
01818                         }
01819                 }
01820         }
01821         
01822         if (debugFlag) { printf("%s << Debug (%d)\n", __FUNCTION__, 2); }
01823 
01824         //printf("%s << sizes2 = (%d, %d)\n", __FUNCTION__, pts1.size(), pts2.size());
01825 
01826         // Then some kind of epipolar geometry check:
01827 
01828         if ((epipolarCheck) && (pts1.size() > 0) && (pts2.size() > 0)) {
01829                 cv::Mat F, matchesMask_F_matrix;
01830                 
01831                 if ((pts1.size() > 4) && (pts2.size() > 4)) {
01832                         F = findFundamentalMat(cv::Mat(pts1), cv::Mat(pts2), cv::FM_RANSAC, 1.00, 0.99, matchesMask_F_matrix);
01833                 if (debugFlag) { printf("%s << Found.\n", __FUNCTION__); }
01834                 
01835                         for (int iii = matchesMask_F_matrix.rows-1; iii >= 0; iii--) {
01836                                 //printf("%s << matchesMask_F_matrix(%d,0) = %d\n", __FUNCTION__, iii, matchesMask_F_matrix.at<unsigned char>(iii,0));
01837                                 if (matchesMask_F_matrix.at<unsigned char>(iii,0) == 0) {
01838                                         pts1.erase(pts1.begin() + iii);
01839                                         pts2.erase(pts2.begin() + iii);
01840                                 }
01841                         }
01842                 } else {
01843                         pts1.clear();
01844                         pts2.clear();
01845                 }
01846 
01847                 //printf("%s << sizes3 = (%d, %d)\n", __FUNCTION__, pts1.size(), pts2.size());
01848         }
01849 
01850 
01851 }
01852 
01853 bool checkSufficientFeatureSpread(vector<cv::Point2f>& pts, cv::Size matSize, int minFeaturesInImage) {
01854 
01855         cv::Mat countMat;
01856         int horizontalDivisions = 4, verticalDivisions = 3;
01857         countMat = cv::Mat::zeros(3, 4, CV_16UC1);
01858         int minPerSegment = minFeaturesInImage / (8 * horizontalDivisions * verticalDivisions);
01859 
01860         //printf("%s << minPerSegment = %d\n", __FUNCTION__, minPerSegment);
01861 
01862         for (unsigned int iii = 0; iii < pts.size(); iii++) {
01863                 int r, c;
01864                 r = (horizontalDivisions * pts.at(iii).x) / matSize.width;
01865                 c = (verticalDivisions * pts.at(iii).y) / matSize.height;
01866                 countMat.at<unsigned short>(r, c) += 1;
01867         }
01868 
01869         int badSegments = 0;
01870 
01871         for (int iii = 0; iii < countMat.rows; iii++) {
01872                 for (int jjj = 0; jjj < countMat.cols; jjj++) {
01873                         if (countMat.at<unsigned short>(iii, jjj) < minPerSegment) {
01874                                 badSegments++;
01875                         }
01876                 }
01877         }
01878 
01879         //printf("%s << badSegments = %d\n", __FUNCTION__, badSegments);
01880 
01881         if (badSegments > (horizontalDivisions * verticalDivisions / 2)) {
01882                 return false;
01883         }
01884 
01885         return true;
01886 
01887 }
01888 
01889 void drawMatchPaths(cv::Mat& src, cv::Mat& dst, vector<cv::Point2f>& kp1, vector<cv::Point2f>& kp2, const cv::Scalar& color) {
01890 
01891         src.copyTo(dst);
01892         cv::Point a, b;
01893 
01894         for (unsigned int iii = 0; iii < kp1.size(); iii++) {
01895 
01896                 a = cv::Point(kp1.at(iii).x * 16.0, kp1.at(iii).y * 16.0);
01897                 b = cv::Point(kp2.at(iii).x * 16.0, kp2.at(iii).y * 16.0);
01898 
01899                 cv::line(dst, a, b, color, 1, CV_AA, 4);
01900 
01901                 // a = b;
01902 
01903         }
01904 }
01905 
01906 void drawMatchPaths(cv::Mat& src, cv::Mat& dst, vector<cv::KeyPoint>& kp1, vector<cv::KeyPoint>& kp2, vector<vector<cv::DMatch> >& matches1to2) {
01907 
01908         cv::Point a, b;
01909 
01910         for (unsigned int iii = 0; iii < matches1to2.size(); iii++) {
01911                 for (unsigned int jjj = 0; jjj < matches1to2.at(iii).size(); jjj++) {
01912 
01913                         //printf("%s << (%f,%f) vs (%f,%f)\n", __FUNCTION__, kp1.at(iii).pt.x, kp1.at(iii).pt.y, kp2.at(iii).pt.x, kp2.at(iii).pt.y);
01914 
01915                         //printf("%s << (%d, %d) - (%d, %d) / %f\n", __FUNCTION__, iii, jjj, matches1to2.at(iii).at(jjj).trainIdx, matches1to2.at(iii).at(jjj).queryIdx, matches1to2.at(iii).at(jjj).distance);
01916                         //cin.get();
01917                         // matches1to2.at(iii).at(jjj).trainIdx
01918 
01919                         a = cv::Point(kp1.at(matches1to2.at(iii).at(jjj).queryIdx).pt.x * 16.0, kp1.at(matches1to2.at(iii).at(jjj).queryIdx).pt.y * 16.0);
01920                         b = cv::Point(kp2.at(matches1to2.at(iii).at(jjj).trainIdx).pt.x * 16.0, kp2.at(matches1to2.at(iii).at(jjj).trainIdx).pt.y * 16.0);
01921 
01922                         line(dst, a, b, CV_RGB(0,0,255), 1, CV_AA, 4);
01923                         circle(dst, b, 1, CV_RGB(255, 0, 0), 1, CV_AA, 4);
01924                 }
01925         }
01926 }
01927 
01928 void markEdgyTracks(vector<cv::Point2f>& pts, vector<uchar>& statusVec, cameraParameters& camData) {
01929 
01930         vector<cv::Point2f> rpts;
01931 
01932         float minBorderDist = 15.0;
01933 
01934 
01935         redistortPoints(pts, rpts, camData.Kx, camData.distCoeffs, camData.expandedCamMat);
01936 
01937         cv::Mat tmpDisp;
01938 
01939         tmpDisp = cv::Mat::zeros(camData.expandedSize, CV_8UC3);
01940 
01941         cv::Mat testMat;
01942         displayKeyPoints(tmpDisp, rpts, tmpDisp, CV_RGB(0,255,0), 0);
01943 
01944         unsigned int edgyMarks = 0;
01945 
01946         float xDist, yDist, dist;
01947 
01948         for (int iii = pts.size()-1; iii >= 0; iii--) {
01949 
01950                 xDist = min(((float) camData.expandedSize.width) - rpts.at(iii).x, rpts.at(iii).x);
01951                 yDist = min(((float) camData.expandedSize.height) - rpts.at(iii).y, rpts.at(iii).y);
01952                 dist = min(xDist, yDist);
01953 
01954                 if (dist < minBorderDist) {
01955 
01956                         if (statusVec.at(iii) != 0) {
01957                                 edgyMarks++;
01958                         }
01959                         statusVec.at(iii) = 0;
01960                         rpts.erase(rpts.begin() + iii);
01961                 }
01962 
01963         }
01964 
01965         displayKeyPoints(tmpDisp, rpts, tmpDisp, CV_RGB(0,0,255), 0);
01966 
01967         //imshow("tmpDisp", tmpDisp);
01968         //cv::waitKey(1);
01969 
01970         //printf("%s << edgyMarks = %d / %d\n", __FUNCTION__, edgyMarks, pts.size());
01971         //cout << "camData.Kx = " << camData.Kx << endl;
01972 
01973 }
01974 
01975 double estimateStability(cv::Mat& img, cv::Point2f& center, double radius) {
01976     double stability = 0.0;
01977 
01978     if (((center.x - radius) < 0) || ((center.y - radius) < 0) || ((center.x + radius) >= img.cols) || ((center.y + radius) >= img.rows)) {
01979                 //printf("%s << Returning, error.\n", __FUNCTION__);
01980                 return stability;
01981         }
01982 
01983     cv::Mat patch;
01984         constructPatch(img, patch, center, radius, 15);
01985 
01986     double minVal, maxVal;
01987     minMaxLoc(patch, &minVal, &maxVal);
01988 
01989         double variance = getPatchVariance(patch);
01990 
01991     cv::Mat largerMat;
01992     //patch /= maxVal;
01993     //resize(patch, largerMat, Size(patch.rows*4, patch.cols*4), 0, 0, INTER_NEAREST);
01994 
01995     // largerMat /=
01996 
01997 
01998         //imshow("patch", largerMat);
01999         //cv::waitKey();
02000 
02001         //printf("%s << variance = %f\n", __FUNCTION__, variance);
02002 
02003         stability = 1 / variance;
02004 
02005         return stability;
02006 
02007 }
02008 
02009 double getPatchVariance(const cv::Mat& patch) {
02010     double mean = 0.0;
02011         double sigma = 0.0;
02012 
02013         for (int iii = 0; iii < patch.rows; iii++) {
02014                 for (int jjj = 0; jjj < patch.cols; jjj++) {
02015                         mean += patch.at<double>(iii,jjj) / ((double) (patch.rows * patch.cols));
02016                 }
02017         }
02018 
02019         for (int iii = 0; iii < patch.rows; iii++) {
02020                 for (int jjj = 0; jjj < patch.cols; jjj++) {
02021                         //printf("%s << (%f vs %f)\n", __FUNCTION__, patch.at<double>(iii,jjj), mean);
02022                         sigma += pow((patch.at<double>(iii,jjj) - mean), 2.0) / ((double) (patch.rows * patch.cols));
02023                 }
02024         }
02025 
02026         sigma = pow(sigma, 0.5);
02027 
02028         return sigma;
02029 }


thermalvis
Author(s): Stephen Vidas
autogenerated on Sun Jan 5 2014 11:38:44