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
help()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
simpleContour(const Mat & currentQuery,int n=300)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
main(int argc,char ** argv)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