Home | History | Annotate | Download | only in cpp
      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