1 pièce(s) jointe(s)
[OpenCV] Java matchs invalides
Bonjour à tous,
Je suis en train de développer une solution de reconnaissance d'image insensible au changements d'échelle avec le Wrapper Java de OpenCV.
Le but étant, à long terme de simplement de détecter la présence de logo dans une image peu importe la résolution de l'écran sur laquelle la capture à été faite...
Pour l'instant je teste l'application avec des images qui n'ont que peu a voir avec la solution, voici le code que j'ai produit:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
public SurfPatternMatching() {
this.sourceImg = "C:\\Users\\f.chaillat\\workspace\\testImg\\breakingBad.jpg";
this.subImage = "C:\\Users\\f.chaillat\\workspace\\testImg\\breakingBadCutted.jpg";
//Initializing Matrix for Source and template images
this.sourceMat = Highgui.imread(sourceImg);
this.subMat = Highgui.imread(subImage);
this.img_matches = new Mat();
}
public void match(){
//Step 1: On detecte les points sur les deux images avec la méthode SURF
MatOfKeyPoint keyPointsSource = new MatOfKeyPoint(), keyPointsSubImg = new MatOfKeyPoint();
FeatureDetector fd = FeatureDetector.create(FeatureDetector.SURF);
fd.detect(sourceMat, keyPointsSource);
fd.detect(subMat, keyPointsSubImg);
//Step 2: On défini les descripteurs à partir des points trouvés.
Mat descrMatSource = new Mat(), descrMatSubImg = new Mat();
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.SURF);
extractor.compute(sourceMat, keyPointsSource, descrMatSource);
extractor.compute(subMat, keyPointsSubImg, descrMatSubImg);
//Step 3: On compare ensuite les descripteurs des deux images
MatOfDMatch matches = new MatOfDMatch();
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);
matcher.match(descrMatSubImg, descrMatSource, matches);
//Step 4: Filtre des matchs en fonction des distances
double max_dist = 0;
double min_dist = 100;
for(DMatch oneMatch : matches.toArray()){
if(oneMatch.distance < min_dist)
min_dist = oneMatch.distance;
if(oneMatch.distance > max_dist)
max_dist = oneMatch.distance;
}
ArrayList<DMatch>goodMatch = new ArrayList<DMatch>();
for(DMatch oneMatch : matches.toArray()){
if(oneMatch.distance < min_dist*2){
goodMatch.add(oneMatch);
}
}
System.out.println(goodMatch.size());
System.out.println("maxDist : "+max_dist);
System.out.println("minDist : "+min_dist);
//On dessines les matchs satisfaisants
MatOfDMatch MatGoodMatches = new MatOfDMatch();
MatGoodMatches.fromList(goodMatch);
Features2d.drawMatches(subMat, keyPointsSubImg, sourceMat, keyPointsSource, MatGoodMatches, img_matches, Scalar.all(-1), Scalar.all(-1), new MatOfByte(), Features2d.NOT_DRAW_SINGLE_POINTS);
Highgui.imwrite("...\\testImg\\out.png", this.img_matches);
} |
Le code précédent fonctionne lorsqu'il la sous image se trouve bien dans la scène , cependant il match aussi quand les deux images n'ont rien a voir:
Pièce jointe 169569
Je comprend bien que le programme trouve les similitudes dans les deux images mais cela fausse totalement le matching...
Mes questions sont les suivantes :
-Comment distinguer les vrai positifs des faux?
-Dois-je améliorer le filtre des matchs en utilisant un threshold plus sophistiqué ?
-N'y aurait t'il pas une fonction dans openCV qui me retournerai une valeur numérique indiquant le degrés de probabilité d'un match?
Merci de vos réponses.
Franck