1 /* 2 * shape_context.cpp -- Shape context demo for shape matching 3 */ 4 5 #include "opencv2/shape.hpp" 6 #include "opencv2/imgcodecs.hpp" 7 #include "opencv2/highgui.hpp" 8 #include "opencv2/imgproc.hpp" 9 #include <opencv2/core/utility.hpp> 10 #include <iostream> 11 #include <string> 12 13 using namespace std; 14 using namespace cv; 15 16 static void help() 17 { 18 printf("\n" 19 "This program demonstrates a method for shape comparisson based on Shape Context\n" 20 "You should run the program providing a number between 1 and 20 for selecting an image in the folder ../data/shape_sample.\n" 21 "Call\n" 22 "./shape_example [number between 1 and 20]\n\n"); 23 } 24 25 static vector<Point> simpleContour( const Mat& currentQuery, int n=300 ) 26 { 27 vector<vector<Point> > _contoursQuery; 28 vector <Point> contoursQuery; 29 findContours(currentQuery, _contoursQuery, RETR_LIST, CHAIN_APPROX_NONE); 30 for (size_t border=0; border<_contoursQuery.size(); border++) 31 { 32 for (size_t p=0; p<_contoursQuery[border].size(); p++) 33 { 34 contoursQuery.push_back( _contoursQuery[border][p] ); 35 } 36 } 37 38 // In case actual number of points is less than n 39 int dummy=0; 40 for (int add=(int)contoursQuery.size()-1; add<n; add++) 41 { 42 contoursQuery.push_back(contoursQuery[dummy++]); //adding dummy values 43 } 44 45 // Uniformly sampling 46 random_shuffle(contoursQuery.begin(), contoursQuery.end()); 47 vector<Point> cont; 48 for (int i=0; i<n; i++) 49 { 50 cont.push_back(contoursQuery[i]); 51 } 52 return cont; 53 } 54 55 int main(int argc, char** argv) 56 { 57 help(); 58 string path = "../data/shape_sample/"; 59 int indexQuery = 1; 60 if( argc < 2 ) 61 { 62 std::cout<<"Using first image as query."<<std::endl; 63 } 64 else 65 { 66 sscanf( argv[1], "%i", &indexQuery ); 67 } 68 cv::Ptr <cv::ShapeContextDistanceExtractor> mysc = cv::createShapeContextDistanceExtractor(); 69 70 Size sz2Sh(300,300); 71 stringstream queryName; 72 queryName<<path<<indexQuery<<".png"; 73 Mat query=imread(queryName.str(), IMREAD_GRAYSCALE); 74 Mat queryToShow; 75 resize(query, queryToShow, sz2Sh); 76 imshow("QUERY", queryToShow); 77 moveWindow("TEST", 0,0); 78 vector<Point> contQuery = simpleContour(query); 79 int bestMatch = 0; 80 float bestDis=FLT_MAX; 81 for ( int ii=1; ii<=20; ii++ ) 82 { 83 if (ii==indexQuery) continue; 84 waitKey(30); 85 stringstream iiname; 86 iiname<<path<<ii<<".png"; 87 cout<<"name: "<<iiname.str()<<endl; 88 Mat iiIm=imread(iiname.str(), 0); 89 Mat iiToShow; 90 resize(iiIm, iiToShow, sz2Sh); 91 imshow("TEST", iiToShow); 92 moveWindow("TEST", sz2Sh.width+50,0); 93 vector<Point> contii = simpleContour(iiIm); 94 float dis = mysc->computeDistance( contQuery, contii ); 95 if ( dis<bestDis ) 96 { 97 bestMatch = ii; 98 bestDis = dis; 99 } 100 std::cout<<" distance between "<<queryName.str()<<" and "<<iiname.str()<<" is: "<<dis<<std::endl; 101 } 102 destroyWindow("TEST"); 103 stringstream bestname; 104 bestname<<path<<bestMatch<<".png"; 105 Mat iiIm=imread(bestname.str(), 0); 106 Mat bestToShow; 107 resize(iiIm, bestToShow, sz2Sh); 108 imshow("BEST MATCH", bestToShow); 109 moveWindow("BEST MATCH", sz2Sh.width+50,0); 110 111 return 0; 112 } 113