I am creating a small program that detects objects (a small image) in a large image, and I use Java OpenCV. Since I have to consider rotation and scaling, I used FeatureDetector.BRISK and DescriptorExtractor.BRISK.
The following approach is used to filter match results for best matches.
I have two questions
- Is there a way to find below min_dist and max_dist using the loop I used?
- The most important question. Now the problem is that I need to use these matches to determine if an object (template) is found or not. It would be great if someone helped me here.
Thanks in advance.
FeatureDetector fd = FeatureDetector.create(FeatureDetector.BRISK); final MatOfKeyPoint keyPointsLarge = new MatOfKeyPoint(); final MatOfKeyPoint keyPointsSmall = new MatOfKeyPoint(); fd.detect(largeImage, keyPointsLarge); fd.detect(smallImage, keyPointsSmall); System.out.println("keyPoints.size() : "+keyPointsLarge.size()); System.out.println("keyPoints2.size() : "+keyPointsSmall.size()); Mat descriptorsLarge = new Mat(); Mat descriptorsSmall = new Mat(); DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRISK); extractor.compute(largeImage, keyPointsLarge, descriptorsLarge); extractor.compute(smallImage, keyPointsSmall, descriptorsSmall); System.out.println("descriptorsA.size() : "+descriptorsLarge.size()); System.out.println("descriptorsB.size() : "+descriptorsSmall.size()); MatOfDMatch matches = new MatOfDMatch(); DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT); matcher.match(descriptorsLarge, descriptorsSmall, matches); System.out.println("matches.size() : "+matches.size()); MatOfDMatch matchesFiltered = new MatOfDMatch(); List<DMatch> matchesList = matches.toList(); List<DMatch> bestMatches= new ArrayList<DMatch>(); Double max_dist = 0.0; Double min_dist = 100.0; for (int i = 0; i < matchesList.size(); i++) { Double dist = (double) matchesList.get(i).distance; if (dist < min_dist && dist != 0) { min_dist = dist; } if (dist > max_dist) { max_dist = dist; } } System.out.println("max_dist : "+max_dist); System.out.println("min_dist : "+min_dist); double threshold = 3 * min_dist; double threshold2 = 2 * min_dist; if (threshold2 >= max_dist) { threshold = min_dist * 1.1; } else if (threshold >= max_dist) { threshold = threshold2 * 1.4; } System.out.println("Threshold : "+threshold); for (int i = 0; i < matchesList.size(); i++) { Double dist = (double) matchesList.get(i).distance; System.out.println(String.format(i + " match distance best : %s", dist)); if (dist < threshold) { bestMatches.add(matches.toList().get(i)); System.out.println(String.format(i + " best match added : %s", dist)); } } matchesFiltered.fromList(bestMatches); System.out.println("matchesFiltered.size() : " + matchesFiltered.size());
Edit
Edited my code as follows. I know that this is not the best way to conclude whether the found object is found or not based on the best matches. Therefore, please share your views.
System.out.println("max_dist : "+max_dist); System.out.println("min_dist : "+min_dist); if(min_dist > 50 ) { System.out.println("No match found"); System.out.println("Just return "); return false; } double threshold = 3 * min_dist; double threshold2 = 2 * min_dist; if (threshold > 75) { threshold = 75; } else if (threshold2 >= max_dist) { threshold = min_dist * 1.1; } else if (threshold >= max_dist) { threshold = threshold2 * 1.4; } System.out.println("Threshold : "+threshold); for (int i = 0; i < matchesList.size(); i++) { Double dist = (double) matchesList.get(i).distance; if (dist < threshold) { bestMatches.add(matches.toList().get(i));
Emily webb
source share