编辑:这不适用于旋转。对matchTemplate
. 我还没有尝试bjoernz 答案中的findContours
+ ,这听起来很有希望。moments
失败的解决方案:
我尝试使用OpenCV 3.0 中可用的ShapeContextDistanceExtractor
( 1findContours
) 以及您的示例图像来获得良好的结果。样本图像被裁剪为与原始图像相同的大小(128 * 200)。您也可以resize
在 OpenCV 中使用。
下面的代码将images
文件夹1.png
中的图像与基本图像进行比较。
#include "opencv2/shape.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
#include <string>
using namespace std;
using namespace cv;
const int MAX_SHAPES = 7;
vector<Point> findContours( const Mat& compareToImg )
{
vector<vector<Point> > contour2D;
findContours(compareToImg, contour2D, RETR_LIST, CHAIN_APPROX_NONE);
//converting 2d vector contours to 1D vector for comparison
vector <Point> contour1D;
for (size_t border=0; border < contour2D.size(); border++) {
for (size_t p=0; p < contour2D[border].size(); p++) {
contour1D.push_back( contour2D[border][p] );
}
}
//limiting contours size to reduce distance comparison time
contour1D.resize( 300 );
return contour1D;
}
int main()
{
string path = "./images/";
cv::Ptr <cv::ShapeContextDistanceExtractor> distanceExtractor = cv::createShapeContextDistanceExtractor();
//base image
Mat baseImage= imread( path + "1.png", IMREAD_GRAYSCALE);
vector<Point> baseImageContours= findContours( baseImage );
for ( int idx = 2; idx <= MAX_SHAPES; ++idx ) {
stringstream imgName;
imgName << path << idx << ".png";
Mat compareToImg=imread( imgName.str(), IMREAD_GRAYSCALE ) ;
vector<Point> contii = findContours( compareToImg );
float distance = distanceExtractor->computeDistance( baseImageContours, contii );
std::cout<<" distance to " << idx << " : " << distance << std::endl;
}
return 0;
}
结果
到 2 的
距离:89.7951 到 3 的
距离:14.6793 到 4 的
距离:6.0063 到 5 的
距离:4.79834 到 6 的
距离:0.0963184 到 7 的距离:0.00212693