khu*_*ram 8 c java-native-interface android opencv opencv4android
我是java android开发人员,我不太了解C/C++或Matlab函数.在我的代码中做的很简单的事情就是创建sift/Surf图像细节并在.yml文件中保存细节.
这是我如何创建筛选的代码
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);
Run Code Online (Sandbox Code Playgroud)
将结果描述符保存在(.yml)文件中,然后使用OpenCV的FlannBasedMatcher比较yml文件
这是我的代码
descriptors1&descriptors2是从.yml文件创建的两个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 %d s\n", good_matches_sum);
LOGI("the distance k %f s\n", good_matches_sum);
double score = (double) good_matches_sum / (double) good_matches.size();
LOGI("score %f k %d s\n", score, good_matches.size());
Run Code Online (Sandbox Code Playgroud)
问题出在上面的代码中我每次都得到不同的结果
这里我的两张照片是


//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
Run Code Online (Sandbox Code Playgroud)
基于肯定结果和否定,我假设图像更纤细或不相似.但每次都有这种不同的结果,我不能告诉图像是否相似.
请帮助我,我不知道Opencv和c所以,如果有任何想法,那么请建议更正的代码.谢谢.
基本上,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
Run Code Online (Sandbox Code Playgroud)
这是我曾经使用过的一段代码,仍然存在一些缺陷(对于某些特定类型的比赛,得分不合理。但这种情况很少发生)。
请注意,这MY_****_DISTANCE取决于您使用的是 SIFT 还是 SURF,以及您提供的 SIFT/SURF 函数的参数。
//===========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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
当使用参数运行 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
Run Code Online (Sandbox Code Playgroud)
很明显,“错误”匹配的平均值大于“正确”匹配的平均值。但是如果你浏览很多张图片,你会遇到一些异常(例如匹配次数较少但平均距离较低的错误匹配),其中一些我还没有弄清楚如何消除。因此,根据匹配距离的原始数据,您还必须做出相当“个人”的分数。
这是您可能需要的一段演示。
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);
Run Code Online (Sandbox Code Playgroud)
您可以在本教程中找到详细信息
这取决于你如何定义“有效”。看官方的例子,左边的图片(“物体”图像)是右边图片(“场景”图像)的一部分。然后,将单应矩阵应用于“对象”图像的顶点向量,我们最终得到右侧出现的绿色四边形,它标记了“对象”图像所在的位置。
对于我来说,根据教程,我对“有效”的定义是: 1.四个点形成一个四边形 2.四边形的边长都不能太小 3.四边形中没有任何角度应该太小了。4、四边形不宜上下颠倒。
并执行一些基本数学,这是验证过程的一部分。
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;
}
Run Code Online (Sandbox Code Playgroud)
再次,您可能想要创建自己的验证过程,至于验证,这很大程度上取决于您的要求。但在我看来,这部分是最简单的部分,而最本质的部分是评分过程。
| 归档时间: |
|
| 查看次数: |
1098 次 |
| 最近记录: |