OpenCV C++形状匹配
这个程序使用OpenCV shape模块进行形状匹配。
数据库里有20张图片:
可以很容易看出来每两张图片是一组匹配的形状。
大概就是这个意思:用第一张图片查询时会找到第二张图片。
现在查询左边的第14张图片,可以看到最佳匹配(Best Match)的是右边显示的第13张图片。
代码:
#include "opencv2/shape.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include <iostream> #include <string> static vector<Point> simpleContour( const Mat& currentQuery, int n=300 ) { vector<vector<Point> > _contoursQuery; vector <Point> contoursQuery; findContours(currentQuery, _contoursQuery, RETR_LIST, CHAIN_APPROX_NONE); for (size_t border=0; border<_contoursQuery.size(); border++) { for (size_t p=0; p<_contoursQuery[border].size(); p++) { contoursQuery.push_back( _contoursQuery[border][p] ); } } int dummy=0; for (int add=(int)contoursQuery.size()-1; add<n; add++) { contoursQuery.push_back(contoursQuery[dummy++]); } cv::randShuffle(contoursQuery); vector<Point> cont; for (int i=0; i<n; i++) { cont.push_back(contoursQuery[i]); } return cont; } int main() { int indexQuery = 14; string path = "data/shape_sample/"; cv::Ptr <cv::ShapeContextDistanceExtractor> mysc = cv::createShapeContextDistanceExtractor(); Size sz2Sh(300,300); stringstream queryName; queryName<<path<<indexQuery<<".png"; Mat query=imread(queryName.str(), IMREAD_GRAYSCALE); Mat queryToShow; resize(query, queryToShow, sz2Sh, 0, 0, INTER_LINEAR_EXACT); imshow("QUERY", queryToShow); vector<Point> contQuery = simpleContour(query); int bestMatch = 0; float bestDis=FLT_MAX; for ( int ii=1; ii<=20; ii++ ) { if (ii==indexQuery) continue; stringstream iiname; iiname<<path<<ii<<".png"; Mat iiIm=imread(iiname.str(), 0); Mat iiToShow; resize(iiIm, iiToShow, sz2Sh, 0, 0, INTER_LINEAR_EXACT); vector<Point> contii = simpleContour(iiIm); float dis = mysc->computeDistance( contQuery, contii ); if ( dis<bestDis ) { bestMatch = ii; bestDis = dis; } } stringstream bestname; bestname<<path<<bestMatch<<".png"; Mat iiIm=imread(bestname.str(), 0); Mat bestToShow; resize(iiIm, bestToShow, sz2Sh, 0, 0, INTER_LINEAR_EXACT); imshow("BEST MATCH", bestToShow); moveWindow("BEST MATCH", sz2Sh.width+50,0); waitKey(); return 0; }