web-dev-qa-db-fra.com

Match BFMatcher dans une erreur de lancement OpenCV

J'utilise des descripteurs SURF pour la comparaison d'images. Je prévois de faire correspondre une image donnée à une base de données d'images.

import cv2
import numpy as np
surf = cv2.xfeatures2d.SURF_create(400)

img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)

kp1,des1 = surf.detectAndCompute(img1,None)
kp2,des2 = surf.detectAndCompute(img2,None)


bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=True)
#I am planning to add more descriptors
bf.add(des1)

bf.train()

#This is my test descriptor
bf.match(des2)

Le problème est avec bf.match est que je reçois l'erreur suivante:

OpenCV Error: Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)) in batchDistance, file /build/opencv/src/opencv-3.1.0/modules/core/src/stat.cpp, line 3749
Traceback (most recent call last):
  File "image_match4.py", line 16, in <module>
    bf.match(des2)
cv2.error: /build/opencv/src/opencv-3.1.0/modules/core/src/stat.cpp:3749: error: (-215) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function batchDistance

L'erreur est similaire à this post. L'explication donnée est incomplète et inadéquate. Je veux savoir comment résoudre ce problème. J'ai aussi utilisé des descripteurs ORB, BFMatcher ayant NORM_HAMMING distance. L'erreur refait surface . Toute aide sera appréciée.

Les deux images que j'ai utilisées pour cela sont:

 box.png

box.png 

 box_in_scene.png

box_in_scene.png

J'utilise Python 3.5.2 et OpenCV 3.1.x sous Linux.

9
motiur

Pour rechercher entre les descripteurs de deux images, utilisez:

img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)

kp1,des1 = surf.detectAndCompute(img1,None)
kp2,des2 = surf.detectAndCompute(img2,None)


bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False)
matches = bf.match(des1,des2)

Pour rechercher parmi plusieurs images

La méthode add est utilisée pour ajouter un descripteur de plusieurs images de test. Une fois que tous les descripteurs sont indexés, vous exécutez la méthode train pour construire une structure de données sous-jacente (exemple: KdTree qui sera utilisé pour la recherche dans le cas de FlannBasedMatcher). Vous pouvez ensuite exécuter match pour déterminer si l'image de test correspond le mieux à quelle image de requête. Vous pouvez vérifier K-d_tree et voir comment il peut être utilisé pour rechercher des vecteurs multidimensionnels (Surf donne un vecteur à 64 dimensions).

Remarque: - BruteForceMatcher, comme son nom l’indique, n’a pas de recherche interne optimisant la structure des données et a donc une méthode de train vide.

Exemple de code pour la recherche d'images multiples

import cv2
import numpy as np
surf = cv2.xfeatures2d.SURF_create(400)

# Read Images
train = cv2.imread('box.png',0)
test = cv2.imread('box_in_scene.png',0)

# Find Descriptors    
kp1,trainDes1 = surf.detectAndCompute(train, None)
kp2,testDes2  = surf.detectAndCompute(test, None)

# Create BFMatcher and add cluster of training images. One for now.
bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False) # crossCheck not supported by BFMatcher
clusters = np.array([trainDes1])
bf.add(clusters)

# Train: Does nothing for BruteForceMatcher though.
bf.train()

matches = bf.match(testDes2)
matches = sorted(matches, key = lambda x:x.distance)

# Since, we have index of only one training image, 
# all matches will have imgIdx set to 0.
for i in range(len(matches)):
    print matches[i].imgIdx

Pour la sortie DMatch de bf.match, voir docs .

Voir l'exemple complet pour cela ici: Documents opencv3.0 .

Autre info

OS: Mac.
Python: 2.7.10.
Opencv: 3.0.0-dev [Si souvenez-vous bien, installé en utilisant infusion]. 

7
saurabheights

J'ai trouvé que j'avais la même erreur. Il a fallu un certain temps pour comprendre - certaines de mes images étaient quelque peu dépourvues de traits, donc aucun point clé n'a été trouvé, et detectAndCompute a retourné None pour les descripteurs. Cela vaut peut-être la peine de vérifier la liste des descripteurs pour les éléments None avant de passer à BFMatcher.add().

3
eldorz

J'avais la même erreur. Mais dans mon cas, c’était parce que j’utilisais SIFT avec la métrique cv2.NORM_HAMMING dans cv2.BFMatcher_create. Le fait de changer la métrique en cv2.NORM_L1 a résolu le problème. 

Citation de documents pour BFMatcher

normType - L'un des NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2. L1 et les normes L2 sont des choix préférables pour les descripteurs SIFT et SURF, NORM_HAMMING doit être utilisé avec ORB, BRISK et BRIEF, NORM_HAMMING2 doit être utilisé avec ORB lorsque WTA_K==3 ou 4 (voir la description du constructeur ORB::ORB .__). 

2
Georgy

Édition: Versions utilisées Python 3.6, OpenCV 3.4.1

J'ai eu beaucoup de mal à préparer un programme qui utiliseSIFTouORBselon le choix de l'utilisateur. Enfin, je pourrais trouver les paramètres corrects pour BFMatcher pourSIFTetORB

import cv2
import numpy as np

# ask user whether to use SIFT or ORB
detect_by = input("sift or orb")
  1. Création d'objet matcher

    if detect_by == "sift":
        matcher = cv2.BFMatcher(normType=cv2.NORM_L2, crossCheck=False)
    
    Elif detect_by is "orb":
        matcher = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=False)
    
  2. Lors de la capture et du traitement des images

    while there_is_frame_to_process:
        if detect_by is "sift":
            matches = matcher.knnMatch(np.asarray(gray_des, np.float32), np.asarray(target_des, np.float32), k=2)
    
        Elif detect_by is "orb":
            matches = matcher.knnMatch(np.asarray(gray_des, np.uint8), np.asarray(target_des, np.uint8), k=2)
    
0
Ali Eren Çelik