Utilisation basique de matchTemplate cv2

Fermé
Paya200 Messages postés 2 Date d'inscription lundi 5 décembre 2022 Statut Membre Dernière intervention 5 décembre 2022 - Modifié le 5 déc. 2022 à 12:14
Paya200 Messages postés 2 Date d'inscription lundi 5 décembre 2022 Statut Membre Dernière intervention 5 décembre 2022 - 5 déc. 2022 à 12:42

Bonjour,

Je suis débutant en programmation et j'aimerais utiliser très simplement, du moins le plus simplement possible, utiliser "matchTemplate" de cv2 dans python :

https://docs.opencv.org/4.x/d4/dc6/tutorial_py_template_matching.html

J'arrive à utiliser cette fonction comme dans l'exemple, c'est-à-dire en comparant mes deux images et en affichant le résultat. Mais je souhaite faire encore plus simple.

Comment puis-je juste comparer mes deux images et sortir uniquement un booléen,"true" si ma première image est détectée dans ma deuxième, "false" si ma première image n'est pas détectée dans ma deuxième.

Pouvez-vous, s'il vous plaît, m'aider à écrire ce script qui semble extrêmement simple ? 

Merci d'avance pour vos réponses et bonne journée à vous :-)

2 réponses

mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
Modifié le 5 déc. 2022 à 13:38

Bonjour,

Si tu lis la documentation de matchTemplate, tu verras que la fonction permet de retrouver la région avec MinMaxLoc, qui elle même est utilisée dans l'exemple que tu as partagé. C'est le résultat de cette fonction qui permet de déterminer la position et la taille du rectangle dessiné sur l'image de droite (detected point).

Selon la méthode de reconnaissance d'image utilisée, le rectangle optimal est le min, soit le max.

    # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
    if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc

Cependant, j'ai l'impression que peu importe la méthode de reconnaissance d'image utilisée, matchTemplate retourne toujours un rectangle, même s'il est très mauvais. Je suppose donc qu'il faut regarder si la valeur retournée (min_val pour cv.TM_SQDIFF et cv.TM_SQNORMED) ne dépasse pas une valeur seuil (que tu devras choisir) pour déterminer si le résultat est acceptable ou non.

Je n'ai pas regardé les valeurs retournées par ces méthodes, mais d'après leur noms, je suspecte que les méthodes cv2.*NORMED retournent une valeur entre 0 et 1. Tu peux alors définir pour ces méthodes un seuil, par exemple, min_val < 0.1 pour cv.TM_SQDIFF_NORMED et max_loc > 0.9 pour les autres.

Je n'ai pas testé, mais voici à quoi ça pourrait peut-être ressembler :

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('messi5.jpg',0)
img2 = img.copy()
template = cv.imread('template.jpg',0)
(w, h) = template.shape[::-1]

methods = ['cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF_NORMED']

for meth in methods:
    img = img2.copy()
    method = eval(meth)

    # Apply template Matching
    res = cv.matchTemplate(img, template, method)
    (min_val, max_val, min_loc, max_loc) = cv.minMaxLoc(res)

    # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
    print(min_val, max_val, min_loc, max_loc)

    if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
        top_left = min_loc
        found = min_val < 0.1
    else:
        top_left = max_loc
        found = max_val > 0.9

    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv.rectangle(img,top_left, bottom_right, 255, 2)
    plt.subplot(121),plt.imshow(res,cmap = 'gray')
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(img,cmap = 'gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.suptitle(meth)
    plt.show()

    if found:
        print("FOUND")
    else:
        print("NOT FOUND")

Bonne chance

1
Paya200 Messages postés 2 Date d'inscription lundi 5 décembre 2022 Statut Membre Dernière intervention 5 décembre 2022
5 déc. 2022 à 12:42

merci beaucoup pour cette réponse rapide mamiemando ! je vais tester ça rapidement !

0