//-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始执行 //----------------------------------------------------------------------------------------------- int main( int argc, char** argv ) { //【0】改变console字体颜色 system("color 4F"); //【0】显示帮助文字 ShowHelpText(); //【1】载入源图片 Mat img_1 = imread("1.jpg", 1 ); Mat img_2 = imread( "2.jpg", 1 ); if( !img_1.data || !img_2.data ) { printf("读取图片image0错误~! \n"); return false; } //【2】利用SURF检测器检测的关键点 int minHessian = 300; SURF detector( minHessian ); std::vector<KeyPoint> keypoints_1, keypoints_2; detector.detect( img_1, keypoints_1 ); detector.detect( img_2, keypoints_2 ); //【3】计算描述符(特征向量) SURF extractor; Mat descriptors_1, descriptors_2; extractor.compute( img_1, keypoints_1, descriptors_1 ); extractor.compute( img_2, keypoints_2, descriptors_2 ); //【4】采用FLANN算法匹配描述符向量 FlannBasedMatcher matcher; std::vector< DMatch > matches; matcher.match( descriptors_1, descriptors_2, matches ); double max_dist = 0; double min_dist = 100; //【5】快速计算关键点之间的最大和最小距离 for( int i = 0; i < descriptors_1.rows; i++ ) { double dist = matches[i].distance; if( dist < min_dist ) min_dist = dist; if( dist > max_dist ) max_dist = dist; } //输出距离信息 printf("> 最大距离(Max dist) : %f \n", max_dist ); printf("> 最小距离(Min dist) : %f \n", min_dist ); //【6】存下符合条件的匹配结果(即其距离小于2* min_dist的),使用radiusMatch同样可行 std::vector< DMatch > good_matches; for( int i = 0; i < descriptors_1.rows; i++ ) { if( matches[i].distance < 2*min_dist ) { good_matches.push_back( matches[i]); } } //【7】绘制出符合条件的匹配点 Mat img_matches; drawMatches( img_1, keypoints_1, img_2, keypoints_2, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); //【8】输出相关匹配点信息 for( int i = 0; i < good_matches.size(); i++ ) { printf( ">符合条件的匹配点 [%d] 特征点1: %d -- 特征点2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); } //【9】显示效果图 imshow( "匹配效果图", img_matches ); //按任意键退出程序 waitKey(0); return 0; }
int main(int argc, char* argv[]) { //video input string videoName("A_kind_of_a_Show.avi"); VideoCapture capture(videoName); if (!capture.isOpened()) { cout << "!capture.isOpened()"; return -1; } //path list vector<vector<Point2f>> pathList; vector<int> kpIdx2pathListIdx; vector<KeyPoint> kpTrackedPrev; Mat desTrackedPrev; vector<KeyPoint> kpEdgePrev; Mat desEdgePrev; //firstFrame init Mat firstFrame; Mat frame, framePrev; capture.read(firstFrame); keypointDetectorAnddescriptor.detect(firstFrame, kpTrackedPrev); keypointDetectorAnddescriptor.compute(firstFrame, kpTrackedPrev, desTrackedPrev); getEdgeKeypoint(firstFrame.cols, firstFrame.rows, 0.25, kpTrackedPrev, desTrackedPrev, kpEdgePrev, desEdgePrev); for (int i = 0; i < kpTrackedPrev.size(); ++i) { pathList.push_back(vector<Point2f>()); pathList[i].push_back(kpTrackedPrev[i].pt); kpIdx2pathListIdx.push_back(i); } firstFrame.copyTo(framePrev); //video writer VideoWriter vw("result.avi", CV_FOURCC('M', 'J', 'P', 'G'), 12, Size(firstFrame.cols, firstFrame.rows)); if (!vw.isOpened()) return -1; //frame vector<KeyPoint> kpCur; Mat desCur; int frameIdx = 0; //processing while (capture.read(frame)) { ++frameIdx; keypointDetectorAnddescriptor.detect(frame, kpCur); keypointDetectorAnddescriptor.compute(frame, kpCur, desCur); //edge keypoint matching for homography vector<Point2f> ptEdgeCurMatched; vector<Point2f> ptEdgePrevMatched; vector<vector<DMatch>> vvmatchs; matcher.knnMatch(desEdgePrev, desCur, vvmatchs, 2); for (int i = 0; i < vvmatchs.size(); ++i) { if (vvmatchs[i][0].distance < vvmatchs[i][1].distance * 0.8) { ptEdgeCurMatched.push_back(kpCur[vvmatchs[i][0].trainIdx].pt); ptEdgePrevMatched.push_back(kpEdgePrev[vvmatchs[i][0].queryIdx].pt); } } //findHomography Mat h = findHomography(ptEdgePrevMatched,ptEdgeCurMatched, RANSAC); cout << h << endl; // camera movement compensation for (vector<Point2f>& path : pathList){ perspectiveTransform(path, path, h); } Mat warpedframe; warpPerspective(framePrev, warpedframe, h, frame.size()); imshow("frame", frame); imshow("prev", framePrev); imshow("warpedframe", warpedframe); getEdgeKeypoint(frame.cols, frame.rows, 0.25, kpCur, desCur, kpEdgePrev, desEdgePrev); frame.copyTo(framePrev); //keypoint tracking for pathlist vector<int> kpIdx2pathListIdxTemp; vector<KeyPoint> kpTrackedCur; Mat desTrackedCur; set<int> curMatchedKpIdxSet; matcher.knnMatch(desTrackedPrev, desCur, vvmatchs, 2); for (int i = 0; i < vvmatchs.size(); ++i) { if (vvmatchs[i][0].distance < vvmatchs[i][1].distance * 0.6) { pathList[kpIdx2pathListIdx[i]].push_back(kpCur[vvmatchs[i][0].trainIdx].pt); kpTrackedCur.push_back(kpCur[vvmatchs[i][0].trainIdx]); desTrackedCur.push_back(desCur.row(vvmatchs[i][0].trainIdx)); kpIdx2pathListIdxTemp.push_back(kpIdx2pathListIdx[i]); curMatchedKpIdxSet.insert(vvmatchs[i][0].trainIdx); } } if (frameIdx%5==0) { //add new keypoint for (int i = 0; i < kpCur.size(); ++i) { if (curMatchedKpIdxSet.find(i) == curMatchedKpIdxSet.end()){ kpTrackedCur.push_back(kpCur[i]); desTrackedCur.push_back(desCur.row(i)); pathList.push_back(vector<Point2f>()); pathList.rbegin()->push_back(kpCur[i].pt); kpIdx2pathListIdxTemp.push_back(pathList.size() - 1); } } } kpIdx2pathListIdx = kpIdx2pathListIdxTemp; kpTrackedPrev = kpTrackedCur; desTrackedCur.copyTo(desTrackedPrev); Mat show; drawPathList(frame, show, pathList); imshow("pathlist", show); waitKey(1); vw << show; } vw.release(); //uniform for (vector<Point2f>& path : pathList) { for (Point2f& pt : path) { pt.x /= firstFrame.cols; pt.y /= firstFrame.rows; } } vector<double> motionHist; calMotionHist(pathList, motionHist); cout << "h : " << endl; for (double h : motionHist) cout << h << " "; cout << endl; return 1; }
/** @function main */ int matchKeypoints( int argc, char** argv ) { // if( argc != 3 ) // { readme(); return -1; } cv::initModule_nonfree(); Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE ); Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE ); Codebook codebook; //codebook.readInCSV(string(argv[3])); if( !img_1.data || !img_2.data ) { std::cout<< " --(!) Error reading images " << std::endl; return -1; } //-- Step 1: Detect the keypoints using SURF Detector int minHessian = 15000; //SurfFeatureDetector detector( minHessian); SURF* detector = new SURF(minHessian,1,4,true,true); std::vector<KeyPoint> keypoints_1, keypoints_2; assert(img_1.size[0]>0 && img_1.size[1]>0 && img_2.size[0]>0 && img_2.size[1]>0); (*detector)( img_1, Mat(), keypoints_1 ); (*detector)( img_2, Mat(), keypoints_2 ); Mat img_keypoints_1; Mat img_keypoints_2; // drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT ); // drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT ); cvtColor(img_1,img_keypoints_1,CV_GRAY2RGB); for (KeyPoint k :keypoints_1) { // circle(img_keypoints_1,k.pt,k.size,Scalar(rand()%256,rand()%256,rand()%256)); // cout<<k.size<<endl; Rect rec(k.pt.x-(k.size/2),k.pt.y-(k.size/2),k.size,k.size); rectangle(img_keypoints_1,rec,Scalar(rand()%256,rand()%256,rand()%256)); } cvtColor(img_2,img_keypoints_2,CV_GRAY2RGB); for (KeyPoint k :keypoints_2) { // circle(img_keypoints_2,k.pt,k.size,Scalar(rand()%256,rand()%256,rand()%256)); Rect rec(k.pt.x-(k.size/2),k.pt.y-(k.size/2),k.size,k.size); rectangle(img_keypoints_2,rec,Scalar(rand()%256,rand()%256,rand()%256)); } //-- Show detected (drawn) keypoints imshow("Keypoints 1", img_keypoints_1 ); imshow("Keypoints 2", img_keypoints_2 ); waitKey(0); //-- Step 2: Calculate descriptors (feature vectors) //SurfDescriptorExtractor extractor; Mat descriptors_1, descriptors_2; detector->compute( img_1, keypoints_1, descriptors_1 ); detector->compute( img_2, keypoints_2, descriptors_2 ); //-- Step 3: Matching descriptor vectors using FLANN matcher FlannBasedMatcher matcher; std::vector< std::vector< DMatch > > matches; matcher.knnMatch( descriptors_1, descriptors_2, matches, 10 ); double max_dist = 0; double min_dist = 100; //-- Quick calculation of max and min distances between keypoints for( int i = 0; i < matches.size(); i++ ) { for (int j=0; j < matches[i].size(); j++) { double dist = matches[i][j].distance; if( dist < min_dist ) min_dist = dist; if( dist > max_dist ) max_dist = dist; } } printf("-- Max dist : %f \n", max_dist ); printf("-- Min dist : %f \n", min_dist ); //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist, //-- or a small arbitary value ( 0.02 ) in the event that min_dist is very //-- small) //-- PS.- radiusMatch can also be used here. std::vector< DMatch > good_matches; for( int i = 0; i < matches.size(); i++ ) { for (int j=0; j < matches[i].size(); j++) //if( matches[i][j].distance <= max(2*min_dist, 0.02) ) if( matches[i][j].distance <= max((max_dist-min_dist)/4.0 + min_dist, 0.02) ) { good_matches.push_back( matches[i][j]); } else printf("discard(%d,%d)\n",i,j); } //-- Draw only "good" matches Mat img_matches; drawMatches( img_1, keypoints_1, img_2, keypoints_2, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); //-- Show detected matches imshow( ".... Matches", img_matches ); for( int i = 0; i < (int)good_matches.size(); i++ ) { printf( "-- .... Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); } waitKey(0); // vector<Point2f> corners; // double qualityLevel = 0.01; // double minDistance = 10; // int blockSize = 3; // bool useHarrisDetector = false; // double k = 0.04; // int maxCorners = 23; // int maxTrackbar = 100; // goodFeaturesToTrack( src_gray, // corners, // maxCorners, // qualityLevel, // minDistance, // Mat(), // blockSize, // useHarrisDetector, // k ); return 0; }
int main(int argc, char* argv[]) { SURF extractor; Mat train_descr; SurfFeatureDetector detector(700); BFMatcher match(NORM_L2); //Try to replace with FLANN vector<vector<DMatch> > matches; //namedWindow("Image", CV_WINDOW_AUTOSIZE ); vector<KeyPoint> keypoints; Mat descriptors; FileStorage train; train.open("Train.xml", FileStorage::READ); int correct = 0; float mean_error = 0; float min = 0; int m = 0; string name = argv[1]; for(int x = 2;x<argc;x++) { Mat img = imread(argv[x]); detector.detect(img, keypoints); //drawKeypoints(img,keypoints,img,255); //imshow("Image",img); //waitKey(0); extractor.compute(img, keypoints, descriptors); //Compute errors mean_error = 0; min = 0; m = 0; for(int n = 0; n <CLASSES; n++) { train[set[n]]>>train_descr; match.knnMatch(descriptors,train_descr,matches,NEIGHBOURS); for(int j=0;j<NEIGHBOURS;j++) for(int i=0;i<KEYPOINTS;i++) { mean_error+=matches.at(i).at(j).distance; } mean_error = mean_error/(NEIGHBOURS*KEYPOINTS); if(n==0) min = mean_error; if(min>mean_error) { min = mean_error; m = n; } } if(!name.compare(set[m])) correct+=1; } cout<<"Classification accuracy for "<<name<<" is:"<<(((float)correct)/(argc-2)) * 100<<endl; train.release(); return 0; }