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 : Sélectionner tout - Visualiser dans une fenêtre à part
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:

Nom : out.png
Affichages : 237
Taille : 247,3 Ko

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