在.yml文件中比较图像SIFT / SURF细节OpenCV?

我是java android开发人员,我不太了解C / C ++或Matlab函数。 在我的代码中做什么简单的事情就是创build筛选/冲浪图像的详细信息,并保存在.yml文件中的细节。

这里是我如何创build筛选的代码

vector < KeyPoint > keypoints; Mat descriptors; // Create a SIFT keypoint detector. SiftFeatureDetector detector; detector.detect(image, keypoints); LOGI("Detected %d keypoints\n", (int) keypoints.size()); // Compute feature description. detector.compute(image, keypoints, descriptors); 

将结果描述符保存在(.yml)文件中,然后使用OpenCV的FlannBasedMatcher比较这些yml文件

这是我的代码

descriptors1&descriptors2是由.yml文件创build的两个mat对象。

 FlannBasedMatcher matcher; vector<double> ee; vector < DMatch > good_matches; double good_matches_sum = 0.0; vector < vector<DMatch> > matches; matcher.knnMatch(descriptors1, descriptors2, matches, 2); for (int i = 0; i < matches.size(); i++) { if (matches[i][0].distance < 0.8 * matches[i][1].distance) { good_matches.push_back(matches[i][0]); good_matches_sum += matches[i][0].distance; } } LOGI("good_matches_sum %ds\n", good_matches_sum); LOGI("the distance k %fs\n", good_matches_sum); double score = (double) good_matches_sum / (double) good_matches.size(); LOGI("score %fk %ds\n", score, good_matches.size()); 

问题出在上面的代码是我每次都得到不同的结果

这里是我的两个图像

descriptors1

descriptors2

 //first time run for two images good_matches_sum 1006632960 the distance k 3054.279755 scores 254.523313 k 12 s //Second time run for same two images good_matches_sum -402653184 the distance k 2835.513489 score score scores 257.773954 k 11 s //Third time run for same two images good_matches_sum -1946157056 the distance k 2794.588959 score score scores 254.053542 k 11 s 

我假设形象slimier或不同的基础上积极的结果和消极的。 但每次这种不同的结果,我不能告诉图像类似或不。

请帮我我不知道Opencv和C所以如果任何人有任何想法,那么请build议更正的代码。 谢谢。

Solutions Collecting From Web of "在.yml文件中比较图像SIFT / SURF细节OpenCV?"

基本上,SIFT / SURF无法分辨两幅图像是否相似。 它只能告诉你一个图像中的哪个关键点与另一个图像中的哪个对应点相匹配。

幸运的是,这两个函数还为您提供了一些更多信息,例如匹配的“距离”以及图像中匹配的总数。

我的想法是说这两个形象有多相似:

 1. Use findHomography() to get the homography of two images 2. Check whether the homography is valid (such as 4 of the points form a rectangle). 3. Count the number of "good" matches (match.distance < SOME_DISTANCE) 4. Use some math to generate a score 5. If the previous homography is valid, increase the score 

这里是我曾经使用过的一段代码,还是有一些缺陷(对于某些特定types的比赛,比分是不合理的,但这种情况很less发生)。

请注意, MY_****_DISTANCE取决于您是使用SIFT还是SURF,以及您使用的SIFT / SURFfunction的参数。

 //===========SCORE ============ vector<double> matchDistance; double avg = 0; int avgCount = 0; int goodCount = 0 ; for( unsigned i = 0; i < matches.size(); i++ ) { double dist = matches[i].distance; //This is a "average match" if( dist < MY_AVG_DISTANCE && dist > MY_LEAST_DISTANCE ) { avg += dist; //Count the average of distance of "average matches" avgCount++; } //This is a good match, and number of good match have a great impact on the result //Good matches are also average matches, that is, {GOOD_MATCH} is a subset of {AVERAGE_MATCH} if(dist < MY_GOOD_DISTANCE && dist > MY_LEAST_DISTANCE ){ goodCount++; //Count the number of "good matches" } } if(avgCount > 6){ avg /= avgCount; //Gives the average value if(goodCount < 12){ //If there are too few good matches, make a punishment avg = avg + (12-goodCount) * 4; } }else{ avg = MY_MAX_DISTANCE; } avg = avg > MY_AVG_DISTANCE ? MY_AVG_DISTANCE : avg; avg = avg < MY_MIN_DISTANCE ? MY_MIN_DISTANCE : avg; double score_avg = (MY_AVG_DISTANCE - avg) / ( MY_AVG_DISTANCE - MY_MIN_DISTANCE ) * 100; if(homography_valid){ //If the previous homography is valid, make a reward. score_avg += 40; score_avg = score_avg > 100 ? 100 : score_avg; }else{ score_avg -= 5; //Or, make a little punishment score_avg = score_avg < 0 ? 0 : score_avg; } return score_avg 

更新

我_ **** _距离

My_****_DISTANCE是我自己定义的东西,对不起之前没有解释过。 这是我使用的价值,但您可能想要更改它以更好地适合您的代码。

 #define MY_MIN_DISTANCE 200 #define MY_GOOD_DISTANCE 310 #define MY_AVG_DISTANCE 350 #define MY_MAX_DISTANCE 500 #define MY_MIN_HESSIAN 2000 #define MY_LEAST_DISTANCE 100 

使用参数SiftFeatureDetector detector(400, 3, 0.04, 10.0, 1.6);运行SIFT时SiftFeatureDetector detector(400, 3, 0.04, 10.0, 1.6); ,某些“错误”匹配与某些“正确”匹配相比的结果是:

 Wrong Right 307.993 330.124 470.419 307.374 219.775 371.026 294.389 400.696 355.321 259.239 331.926 189.042 222.317 457.089 320.718 379.061 423.09 201.95 371.098 200.646 362.427 343.229 441.167 359.32 253.253 382.15 367.191 215.678 405.19 358.686 390.251 343.798 341.905 238.002 341.073 226.519 363.775 262.5 340.742 174.877 320.214 415.802 249.405 195.261 347.357 328.76 343.839 116.331 351.058 383.93 286.224 111.472 352.976 138.701 298.409 238.044 385.34 223.716 264.571 331.115 333.339 208.103 329.588 128.168 372.971 267.83 331.804 222.578 301.935 232.459 351.504 342.524 300.762 379.87 346.872 390.031 374.281 308.198 304.746 401.452 307.184 193.298 229.943 98.0714 286.163 133.978 363.634 171.415 361.656 111.077 357.108 134.186 289.712 123.199 371.496 339.944 318.708 192.164 360.547 425.937 331.225 336.535 297.688 309.419 351.898 162.296 408.206 311.055 309.023 457.352 281.375 337.529 362.266 407.757 229.295 388.567 317.005 161.118 386.907 108.936 363.942 215.311 374.832 343.376 311.264 184.318 364.745 188.963 466.795 308.48 381.667 318.828 381.826 119.591 377.338 105.527 377.333 199.206 279.228 369.394 295.078 387.979 267.408 196.942 386.063 307.815 372.14 184.83 294.927 417.138 348.458 97.8621 234.199 144.094 172.377 131.412 250.503 227.139 233.32 116.258 205.331 354.505 95.0368 108.434 116.46 138.246 406.135 308.2 92.817 194.838 312.103 323.163 312.946 377.798 359.393 396.191 320.272 375.025 309.383 280.826 278.456 

很明显,“错误”匹配的平均值大于“正确”匹配的平均值。 但是如果你跑遍了很多的图片,你会发现一些例外(比如匹配较less但平均距离较小的错误匹配),其中一些我还没有想出如何消除。 因此,根据匹配距离的原始数据,你还必须做出一个漂亮的“个人”得分。

findHomography

这是您可能需要的一个演示。

 std::vector<Point2f> obj_corners(4); obj_corners[0] = Point(0,0); obj_corners[1] = Point( img_object.cols, 0 ); obj_corners[2] = Point( img_object.cols, img_object.rows ); obj_corners[3] = Point( 0, img_object.rows ); std::vector<Point2f> scene_corners(4); Mat H = findHomography( obj, scene, RANSAC ); perspectiveTransform( obj_corners, scene_corners, H); 

你可以在本教程中find详细的信息

更新#2

Check_Valid_Homography

这取决于你如何定义“有效”。 看官方的例子,左边的图片(“对象”图片)是右边图片的一部分(“场景”图片)。 然后,将单应matrix应用到“对象”图像的顶点vector上,最后在右边出现一个绿色的四边形,标出“对象”图像所在的位置。

就我而言,根据教程,我对“有效”的定义是:1.四​​点形成一个四边形2.四边形边的长度都不应该太小3.四边形中没有angular度应该太小了。 4.四边形不应该倒立。

并执行一些基本的math,这是validation过程的一部分。

 bool RectChecker::check_order(const vector<Point2f> &corners, int height, int width){ if(corners[0].y + 5 >= corners[3].y || corners[1].y + 5 >= corners[2].y){ //Point 0 should be above Point 3, so do Point1 and Point2 return false; } if(corners[0].x + 5 >= corners[1].x || corners[3].x + 5 >= corners[2].x){ //Point 0 should be on the left of Point 1, so do Point3 and Point2 return false; } int cnt = 0; for(int i = 0 ; i < corners.size() ; i++){ if(corners[i].x < -30 || corners[i].x > width + 30){ cnt++; continue; } if(corners[i].y < -20 || corners[i].y > height + 20){ //This point is outside the image cnt++; } } if(cnt == 4){ //All points are outside the image return false; } return true; } 

再一次,你可能想创build自己的validation过程,至于validation,这很大程度上取决于你的要求。 但就我而言,这部分是最简单的部分,而最重要的部分是评分过程。

问题是在上面的代码是我每次得到不同的结果

这是因为FLANN匹配器是find近似最近邻居,并且基于使用随机数的初始化。 为了保证在每次运行中得到相同的答案,可以使用随机数生成器(例如,调用srand(123456); )或者使用较慢的BruteForceMatcher ,但总会得到最准确的结果。