关键点匹配只能工作两次……? (java opencv)

我有一个非常奇怪的问题。 我正在使用此代码来检测另一个图像(java opencv):

更新的代码:

public void startRecognition() { //load images, I want to find img_object in img_scene Mat img_scene = Highgui.imread("D:/opencvws/ImageRecognition/src/main/resources/ascene.jpg"); Mat img_object = Highgui.imread("D:/opencvws/ImageRecognition/src/main/resources/aobj1.jpg"); run++; System.out.println("RUN NO: " + run); //init detector FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF); //keypoint detection for both images (keyponts_scene for img_scene, keypoint_object for img_object) MatOfKeyPoint keypoints_object = new MatOfKeyPoint(); MatOfKeyPoint keypoints_scene = new MatOfKeyPoint(); detector.detect(img_object, keypoints_object); detector.detect(img_scene, keypoints_scene); System.out.println("OK: " + keypoints_object.total()); System.out.println("SK: " + keypoints_scene.total()); //extractor init DescriptorExtractor extractor = DescriptorExtractor.create(2); //2 = SURF; Mat descriptor_object = new Mat(); Mat descriptor_scene = new Mat() ; //Compute descriptors extractor.compute(img_object, keypoints_object, descriptor_object); extractor.compute(img_scene, keypoints_scene, descriptor_scene); //init matcher DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED); // 1 = FLANNBASED matcher.clear(); MatOfDMatch matches = new MatOfDMatch(); //match both descriptors matcher.match(descriptor_object, descriptor_scene, matches); List matchesList = matches.toList(); //calc min/max dist Double max_dist = 0.0; Double min_dist = 100.0; for(int i = 0; i < descriptor_object.rows(); i++){ Double dist = (double) matchesList.get(i).distance; if(dist  max_dist) max_dist = dist; } //filter good matches LinkedList good_matches = new LinkedList(); MatOfDMatch gm = new MatOfDMatch(); //good match = distance > 2*min_distance ==> put them in a list for(int i = 0; i < descriptor_object.rows(); i++){ if(matchesList.get(i).distance  Mat gm.fromList(good_matches); //mat for resulting image Mat img_matches = new Mat(); //filter keypoints (use only good matches); First in a List, iterate, afterwards ==> Mat LinkedList objList = new LinkedList(); LinkedList sceneList = new LinkedList(); List keypoints_objectList = keypoints_object.toList(); List keypoints_sceneList = keypoints_scene.toList(); for(int i = 0; i<good_matches.size(); i++){ objList.addLast(keypoints_objectList.get(good_matches.get(i).queryIdx).pt); sceneList.addLast(keypoints_sceneList.get(good_matches.get(i).trainIdx).pt); } MatOfPoint2f obj = new MatOfPoint2f(); obj.fromList(objList); MatOfPoint2f scene = new MatOfPoint2f(); scene.fromList(sceneList); //calc transformation matrix; method = 8 (RANSAC) ransacReprojThreshold=3 Mat hg = Calib3d.findHomography(obj, scene, 8,3); //init corners Mat obj_corners = new Mat(4,1,CvType.CV_32FC2); Mat scene_corners = new Mat(4,1,CvType.CV_32FC2); //obj obj_corners.put(0, 0, new double[] {0,0}); obj_corners.put(1, 0, new double[] {img_object.cols(),0}); obj_corners.put(2, 0, new double[] {img_object.cols(),img_object.rows()}); obj_corners.put(3, 0, new double[] {0,img_object.rows()}); //transform obj corners to scene_img (stored in scene_corners) Core.perspectiveTransform(obj_corners,scene_corners, hg); //move points for img_obg width to the right to fit the matching image Point p1 = new Point(scene_corners.get(0,0)[0]+img_object.cols(), scene_corners.get(0,0)[1]); Point p2 = new Point(scene_corners.get(1,0)[0]+img_object.cols(), scene_corners.get(1,0)[1]); Point p3 = new Point(scene_corners.get(2,0)[0]+img_object.cols(), scene_corners.get(2,0)[1]); Point p4 = new Point(scene_corners.get(3,0)[0]+img_object.cols(), scene_corners.get(3,0)[1]); //create the matching image Features2d.drawMatches( img_object, keypoints_object, img_scene, keypoints_scene, gm, img_matches); //draw lines to the matching image Core.line(img_matches, p1 , p2, new Scalar(0, 255, 0),4); Core.line(img_matches, p2, p3, new Scalar(0, 255, 0),4); Core.line(img_matches, p3, p4, new Scalar(0, 255, 0),4); Core.line(img_matches, p4, p1, new Scalar(0, 255, 0),4); // resizing... Mat resizeimage = new Mat(); Size sz = new Size(1200, 1000); Imgproc.resize(img_matches, img_matches, sz); panel1.setimagewithMat(img_matches); frame1.repaint(); //tried to prevent any old references to mix up new calculation matcher.clear(); img_matches = new Mat(); img_object = new Mat(); img_scene = new Mat(); keypoints_object = new MatOfKeyPoint(); keypoints_scene = new MatOfKeyPoint(); hg = new Mat(); } 

如果我在运行的应用程序中运行startRecognition方法两次(在启动时加载opencv库),我得到两个识别的相同结果。 对于第三次尝试,它检测其他关键点并计算另一个转换矩阵(hg)。 例子:

第二次尝试后:

在此处输入图像描述

第3次之后:

图片描述

有人可以解释为什么吗 或者告诉我如何预防呢? 当我重新启动整个程序时,它将再次检测2次正确,然后变化。 经过几次尝试后,它将再次计算出正确的hg(从第一次和seceond尝试)。 我无法弄清楚为什么会这样。

提前致谢

gemorra