// ########################################################################################## // main() routine entry // ########################################################################################## int main( int argc, char** argv ) { // -------------------------------------------------------------------------------------- // Variables // -------------------------------------------------------------------------------------- int64 app_start_time = getTickCount(); int64 t; string fileWithQueryImages, queryDirName, trainDirName; string fileWithTrainImages; string dirToSaveResImages; string reportFile = "matchReport.html"; bool DEBUG; int matchCount = 0; double rank; // -------------------------------------------------------------------------------------- // Argument check // Application takes one argument of path to directory containing images. // -------------------------------------------------------------------------------------- if(( argc == 1) || ( argc == 2)) { readme(); return -1; } else if ( argc == 3 ) { fileWithQueryImages = argv[1]; fileWithTrainImages = argv[2]; } else if ( argc >= 4 ) { fileWithQueryImages = argv[1]; fileWithTrainImages = argv[2]; for (int i = 3; i < argc; ++i) { if (string(argv[i]) == "--help" || string(argv[i]) == "/?") { readme(); return -1; } else if (string(argv[i]) == "--debug") { DEBUG = true; } else if (string(argv[i]) == "--gpu") { GPUMODE = true; } else if (string(argv[i]) == "--output") { reportFile = string(argv[i+1]); } } } // -------------------------------------------------------------------------------------- // Prepare output report file // -------------------------------------------------------------------------------------- //string outputfilename = "matchreport-" + dt + ".html"; ofstream fout(reportFile); //fout << std::string(dt) << endl; std::time_t result = std::time(NULL); /* old report format fout << "Frog Image Match Report" << endl; // Log file output if (DEBUG == true){ fout << "Ratio, conf, dist, minH: " << ratio << "\t" << confidence << "\t" << dist << "\t" << minHessian << endl; } fout << "Start " << std::asctime(std::localtime(&result)); // Log file output */ // HTML report begin fout << "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>" << endl;; fout << "<head> \n <meta http-equiv='content-type' content='text/html; charset=iso-8859-1' />" << endl; fout << "<title>Wood Frog Match Report</title>" << endl; fout << "<style type='text/css' media='screen'>@import 'includes/layout.css';</style>"; fout << "\n</head>" << endl; fout << "\n<body>\n<div id='Header'>Frog Matching System</div>"; fout << "\n<div id='Content'>"; fout << "\n<h1>Frog Match Report</h1>"; fout << "\n<p><table width='643' border='0' cellspacing='5' cellpadding='5'>"; fout << "\n<tr>\n <td><B>Query Image</td>\n <td>Database Image</td>\n <td>Score</td>\n <td>Rank</B></td>\n </tr>"; fout << endl; // -------------------------------------------------------------------------------------- // Begin image match sequence // -------------------------------------------------------------------------------------- vector<string> queryImagesNames; readSetFilenames(fileWithQueryImages, queryDirName, queryImagesNames); // Iterate through query images OUTER LOOP for ( size_t i = 0; i < queryImagesNames.size(); i++) { string queryfilename = queryDirName + queryImagesNames[i]; int innerCount=0; t = getTickCount(); Mat image1 = imread( queryfilename, CV_LOAD_IMAGE_GRAYSCALE ); if( image1.empty() ) { cout << "\n Error, couldn't read image filename " << queryfilename << endl; return -1; } // -------------------------------------------------------------------------------------- // Loop through database images to test files against the outer loop one by one // -------------------------------------------------------------------------------------- vector<string> trainImagesNames; readSetFilenames(fileWithTrainImages, trainDirName, trainImagesNames); // Iterate through train (database) images INNER LOOP for ( size_t j = 0; j < trainImagesNames.size(); j++) { string trainfilename = trainDirName + trainImagesNames[j]; Mat image2 = imread( trainfilename, CV_LOAD_IMAGE_GRAYSCALE ); if (!image2.data) return 0; // --------------------------------------------------------------------------------- // Prepare the matcher // --------------------------------------------------------------------------------- FrogMatcher fmatcher; fmatcher.setConfidenceLevel(confidence); fmatcher.setMinDistanceToEpipolar(dist); fmatcher.setRatio(ratio); fmatcher.setMinHess(minHessian); if (GPUMODE == true) { //fout << "GPU mode ENABLED" << endl; fmatcher.setGpu(); } //fmatcher.setFeatureDetector(pfd); //fmatcher.setDescriptorExtractor(extractor); // --------------------------------------------------------------------------------- // Match the two images // --------------------------------------------------------------------------------- std::cout << queryfilename << " : " << trainfilename << std::endl; std::vector<cv::DMatch> matches; std::vector<cv::KeyPoint> keypoints1, keypoints2; //cv::Mat fundamental= fmatcher.match(image1,image2,matches, keypoints1, keypoints2); Mat fundamental= fmatcher.match(image1,image2,matches, keypoints1, keypoints2); if (matches.size()>0) { // We have a match; draw the matches cv::Mat imageMatches; //Mat image1, image2; //image1 = Mat(imageGpu1); //image2 = Mat(imageGpu2); /* ----------------------------------------------------------------------------- cv::drawMatches(image1,keypoints1, // 1st image and its keypoints image2,keypoints2, // 2nd image and its keypoints matches, // the matches imageMatches, // the image produced cv::Scalar(255,255,255)); // color of the lines ------------------------------------------------------------------------------- */ // Convert keypoints into Point2f std::vector<cv::Point2f> points1, points2; for (std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it) { // Get the position of left keypoints float x= keypoints1[it->queryIdx].pt.x; float y= keypoints1[it->queryIdx].pt.y; points1.push_back(cv::Point2f(x,y)); cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3); // Get the position of right keypoints x= keypoints2[it->trainIdx].pt.x; y= keypoints2[it->trainIdx].pt.y; cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3); points2.push_back(cv::Point2f(x,y)); } // --------------------------------------------------------------------------------- // Draw the epipolar lines // --------------------------------------------------------------------------------- std::vector<cv::Vec3f> lines1; cv::computeCorrespondEpilines(cv::Mat(points1),1,fundamental,lines1); for (std::vector<cv::Vec3f>::const_iterator it= lines1.begin(); it!=lines1.end(); ++it) { cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]), cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]), cv::Scalar(255,255,255)); } std::vector<cv::Vec3f> lines2; cv::computeCorrespondEpilines(cv::Mat(points2),2,fundamental,lines2); for (std::vector<cv::Vec3f>::const_iterator it= lines2.begin(); it!=lines2.end(); ++it) { cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]), cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]), cv::Scalar(255,255,255)); } Mat combinedImage = cvCreateMat(MAX(image1.rows,image2.rows), image1.cols + image2.cols, image1.type()); cv::Mat tmp = combinedImage(cv::Rect(0, 0, image1.cols, image1.rows)); image1.copyTo(tmp); tmp = combinedImage(cv::Rect(image1.cols, 0, image2.cols, image2.rows)); image2.copyTo(tmp); // --------------------------------------------------------------------------------- // Output the combined image (epipolar lines matches) // --------------------------------------------------------------------------------- string outputFile = ".\\Output\\" + queryImagesNames[i] + ".matches." + trainImagesNames[j]; //string outimFile = ".\\Output\\" + myFileName + ".im." + myFileName2; cv::imwrite(outputFile, combinedImage); //cv::imwrite(outimFile, imageMatches); // Write out filenames and 1 to indicate a match double score1 = fmatcher.getScore(); double score2 = fmatcher.getScore2(); rank = score1/score2; /* old output fout << queryImagesNames[i] + "\t " + trainImagesNames[j] + "\t " << score1 << "\t " << rank; if (DEBUG == true){ fout << "\t " << fmatcher.getFerr() << "\t " << fmatcher.getScore2(); } fout << endl; */ fout << "\n<tr>\n <td>" + queryImagesNames[i] + "</td>\n <td>" + trainImagesNames[j] + "</td>\n <td>" << score1; fout << "</td>\n <td>" << rank << "</td>\n </tr>" << endl; } else if (DEBUG == true){ // Write out filenames and 0 to indicate not a match fout << queryImagesNames[i] + "\t " + trainImagesNames[j] + "\t 0" << "\t " << fmatcher.getScore() << endl; } matchCount += 1; innerCount += 1; } // end INNER LOOP // Next iteration (same left image, next right image) //Output Run time per iteration //fout << queryfilename + "\t " + " run time (secs): " + "\t " + "\t " + "\t " + "\t " + "\t "<< ((getTickCount() - t) / getTickFrequency()) << "\n"; } // end OUTER LOOP // Exit application result = std::time(NULL); /* Old report totals fout << "Total Matches\t" << matchCount << endl; fout << "Run time: " << ((getTickCount() - app_start_time) / getTickFrequency()); // Log file output */ // HTML report totals fout << "\n</tr>\n</table>\n</p>"; fout << "\n<p>Image Pairs Analyzed: " << matchCount << endl; fout << "</p>\n<p>Run time: " << ((getTickCount() - app_start_time) / getTickFrequency()); fout << "</p>\n</body></html>" << endl; fout.close(); return 0; }
// ########################################################################################## // main() routine entry // ########################################################################################## int main( int argc, char** argv ) { // -------------------------------------------------------------------------------------- // Tuning parameters // -------------------------------------------------------------------------------------- float ratio = 0.70f; double confidence = 0.99; double dist = 1.0; double keypoints = 10; // -------------------------------------------------------------------------------------- // Argument check // Application takes one argument of path to directory containing images. // -------------------------------------------------------------------------------------- if( argc!=4 ) { readme(); return 1; } // -------------------------------------------------------------------------------------- // Log activity to a file // -------------------------------------------------------------------------------------- ofstream fout("matchReport.txt"); std::time_t result = std::time(NULL); fout << "Frog Image Match Report" << endl; // Log file output fout << "Ratio, confidence, distance, keypoints: " << ratio << "\t" << confidence << "\t" << dist << "\t" << keypoints << endl; fout << "Start " << std::asctime(std::localtime(&result)); // Log file output // -------------------------------------------------------------------------------------- // Setup image search parameters // -------------------------------------------------------------------------------------- std::string curr_directory = argv[1]; candidateSet = argv[2]; // Example: Rs10 for 2010 set dbSet = argv[3]; // Example: Rs09 for 2009 set int matchCount = 0; // -------------------------------------------------------------------------------------- // Perform search for images in target directory // -------------------------------------------------------------------------------------- search(curr_directory, imageType); // -------------------------------------------------------------------------------------- // Iterate through the images // -------------------------------------------------------------------------------------- if (candidateImage.size() && dbImage.size()){ std::clog << candidateImage.size() << " candidate images were found:" << std::endl; // Outer loop for test candidate images. for (int i = 0; i < candidateImage.size(); ++i) { std::cout << candidateImage[i] << std::endl; GpuMat imageGpu1, imageGpu2; string filePath = curr_directory + "//" + candidateImage[i]; imageGpu1.upload(imread(filePath, CV_LOAD_IMAGE_GRAYSCALE)); if( imageGpu1.empty() ) { cout << "\n Error, couldn't read image filename " << filePath << endl; return 1; } // Inner loop for target db images for (unsigned int j = 0; j < dbImage.size(); ++j) // used unsigned to appease compiler warnings { std::cout << "- \t" << dbImage[j] << std::endl; string filePath2 = curr_directory + "//" + dbImage[j]; imageGpu2.upload(imread(filePath2, CV_LOAD_IMAGE_GRAYSCALE)); if (!imageGpu1.data || !imageGpu2.data) // Check for empty image matrix return 0; // --------------------------------------------------------------------------------- // Prepare the matcher // --------------------------------------------------------------------------------- FrogMatcher fmatcher; fmatcher.setConfidenceLevel(confidence); fmatcher.setMinDistanceToEpipolar(dist); fmatcher.setRatio(ratio); //cv::Ptr<cv::FeatureDetector> pfd= new cv::SurfFeatureDetector(keypoints); //cv::Ptr<cv::DescriptorExtractor> extractor= new cv::SurfDescriptorExtractor; //fmatcher.setFeatureDetector(pfd); //fmatcher.setDescriptorExtractor(extractor); // --------------------------------------------------------------------------------- // Match the two images // --------------------------------------------------------------------------------- std::cout << candidateImage[i] << " : " << dbImage[j] << std::endl; std::vector<cv::DMatch> matches; std::vector<cv::KeyPoint> keypoints1, keypoints2; //cv::Mat fundamental= fmatcher.match(image1,image2,matches, keypoints1, keypoints2); Mat fundamental= fmatcher.match(imageGpu1,imageGpu2,matches, keypoints1, keypoints2); if (matches.size()>0) { // We have a match; draw the matches cv::Mat imageMatches; Mat image1, image2; image1 = Mat(imageGpu1); image2 = Mat(imageGpu2); /* ----------------------------------------------------------------------------- cv::drawMatches(image1,keypoints1, // 1st image and its keypoints image2,keypoints2, // 2nd image and its keypoints matches, // the matches imageMatches, // the image produced cv::Scalar(255,255,255)); // color of the lines ------------------------------------------------------------------------------- */ // Convert keypoints into Point2f std::vector<cv::Point2f> points1, points2; for (std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it) { // Get the position of left keypoints float x= keypoints1[it->queryIdx].pt.x; float y= keypoints1[it->queryIdx].pt.y; points1.push_back(cv::Point2f(x,y)); cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3); // Get the position of right keypoints x= keypoints2[it->trainIdx].pt.x; y= keypoints2[it->trainIdx].pt.y; cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3); points2.push_back(cv::Point2f(x,y)); } // --------------------------------------------------------------------------------- // Draw the epipolar lines // --------------------------------------------------------------------------------- std::vector<cv::Vec3f> lines1; cv::computeCorrespondEpilines(cv::Mat(points1),1,fundamental,lines1); for (std::vector<cv::Vec3f>::const_iterator it= lines1.begin(); it!=lines1.end(); ++it) { cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]), cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]), cv::Scalar(255,255,255)); } std::vector<cv::Vec3f> lines2; cv::computeCorrespondEpilines(cv::Mat(points2),2,fundamental,lines2); for (std::vector<cv::Vec3f>::const_iterator it= lines2.begin(); it!=lines2.end(); ++it) { cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]), cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]), cv::Scalar(255,255,255)); } Mat combinedImage = cvCreateMat(MAX(image1.rows,image2.rows), image1.cols + image2.cols, image1.type()); cv::Mat tmp = combinedImage(cv::Rect(0, 0, image1.cols, image1.rows)); image1.copyTo(tmp); tmp = combinedImage(cv::Rect(image1.cols, 0, image2.cols, image2.rows)); image2.copyTo(tmp); // --------------------------------------------------------------------------------- // Output the combined image (epipolar lines matches) // --------------------------------------------------------------------------------- string outputFile = ".//Output//" + candidateImage[i] + ".matches." + dbImage[j]; //string outimFile = ".\\Output\\" + myFileName + ".im." + myFileName2; cv::imwrite(outputFile, combinedImage); //cv::imwrite(outimFile, imageMatches); // Write out filenames and 1 to indicate a match fout << candidateImage[i] + "\t " + dbImage[j] + "\t 1" << endl; } else{ // Write out filenames and 0 to indicate not a match fout << candidateImage[i] + "\t " + dbImage[j] + "\t 0" << endl; matchCount += 1; } } } } else{ std::cout << "No files ending in '" << imageType << "' were found." << std::endl; } // Exit application result = std::time(NULL); fout << "Total Matches\t" << matchCount << endl; fout << "End " << std::asctime(std::localtime(&result)); // Log file output fout.close(); return 0; }