9
votes

Comment visualiser la correspondance des descripteurs à l'aide du module OpenCV dans Python

J'essaie d'utiliser OpenCV avec Python. J'ai écrit un descripteur (tamis, surf ou orb) Code correspondant dans la version C ++ de OpenCV 2.4. Je veux convertir ce code en openc avec Python. J'ai trouvé des documents sur la manière d'utiliser les fonctions OPENCV en C ++, mais bon nombre de la fonction OPENCV dans Python, je n'ai pas pu trouver comment les utiliser. Voici mon code Python et mon problème actuel est que je ne sais pas comment utiliser "Drawmatches" de OpenCV C ++ à Python. J'ai trouvé cv2.draw_matches_flags_default mais je ne sais pas comment l'utiliser. Voici mon code Python de correspondance à l'aide des descripteurs Orb:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'long' object is not callable


0 commentaires

3 Réponses :


2
votes

Comme le dit le message d'erreur, draw_matches_flags_default est de type "long". C'est une constante définie par le module CV2, pas une fonction. Malheureusement, la fonction que vous souhaitez, 'Drawmatches' n'existe que dans l'interface C ++ de OpenCV.


1 commentaires

Plus vrai. Il existe maintenant dans OpenCV 3.x et 4.x. Cependant, les réponses ci-dessus sont des solutions de contournement pour OpenCV 2.x.



15
votes

Vous pouvez visualiser la fonctionnalité correspondant à Python comme suit. Notez l'utilisation de la bibliothèque SciPy.

# matching features of two images
import cv2
import sys
import scipy as sp

if len(sys.argv) < 3:
    print 'usage: %s img1 img2' % sys.argv[0]
    sys.exit(1)

img1_path = sys.argv[1]
img2_path = sys.argv[2]

img1 = cv2.imread(img1_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)

detector = cv2.FeatureDetector_create("SURF")
descriptor = cv2.DescriptorExtractor_create("BRIEF")
matcher = cv2.DescriptorMatcher_create("BruteForce-Hamming")

# detect keypoints
kp1 = detector.detect(img1)
kp2 = detector.detect(img2)

print '#keypoints in image1: %d, image2: %d' % (len(kp1), len(kp2))

# descriptors
k1, d1 = descriptor.compute(img1, kp1)
k2, d2 = descriptor.compute(img2, kp2)

print '#keypoints in image1: %d, image2: %d' % (len(d1), len(d2))

# match the keypoints
matches = matcher.match(d1, d2)

# visualize the matches
print '#matches:', len(matches)
dist = [m.distance for m in matches]

print 'distance: min: %.3f' % min(dist)
print 'distance: mean: %.3f' % (sum(dist) / len(dist))
print 'distance: max: %.3f' % max(dist)

# threshold: half the mean
thres_dist = (sum(dist) / len(dist)) * 0.5

# keep only the reasonable matches
sel_matches = [m for m in matches if m.distance < thres_dist]

print '#selected matches:', len(sel_matches)

# #####################################
# visualization of the matches
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
view = sp.zeros((max(h1, h2), w1 + w2, 3), sp.uint8)
view[:h1, :w1, :] = img1  
view[:h2, w1:, :] = img2
view[:, :, 1] = view[:, :, 0]  
view[:, :, 2] = view[:, :, 0]

for m in sel_matches:
    # draw the keypoints
    # print m.queryIdx, m.trainIdx, m.distance
    color = tuple([sp.random.randint(0, 255) for _ in xrange(3)])
    cv2.line(view, (int(k1[m.queryIdx].pt[0]), int(k1[m.queryIdx].pt[1])) , (int(k2[m.trainIdx].pt[0] + w1), int(k2[m.trainIdx].pt[1])), color)


cv2.imshow("view", view)
cv2.waitKey()


4 commentaires

Lors de l'exécution de votre code, j'obtiens une erreur sur la ligne 66, TypeError: L'argument entier attendu, a été float


@ Wall-e Un utilisateur anonyme vient de modifier votre message, pourrait vouloir vérifier qu'ils ne le sont pas brisés


Voir [: H1,: W1,:] = IMG1 ValueError: Impossible de diffuser une matrice d'entrée de la forme (322 518) en forme (322 518,3)


OK Le problème est que l'IMG n'est pas toujours à 3 canaux car @Brainless a souligné. Cela dépend de la version OpenCV. Donc, dans mon cas (j'utilise 2.7.13), j'ai dû retourner à la version originale que Wall-e posté



15
votes

J'ai aussi écrit quelque chose moi-même qui utilise simplement l'interface Python OpenCV et je n'ai pas utilisé Scipy code>. Drawmatches Code> fait partie de OpenCV 3.0.0 et ne fait pas partie de OpenCV 2, ce qui vous utilise actuellement. Même si je suis en retard à la fête, voici ma propre implémentation qui imite drawmatches code> au mieux de mes capacités.

J'ai fourni mes propres images où l'on est d'un homme de caméra, et l'autre est la même image mais tourné par 55 degrés dans le sens inverse des aiguilles d'une montre. P>

La prémisse de base de ce que j'ai écrit est J'accepterais une image RVB de sortie où la quantité de lignes est le maximum des deux images pour accueillir les deux images de l'image de sortie et que les colonnes sont simplement la sommation des colonnes ensemble. Je place chaque image dans leurs endroits correspondants, puis passez à travers une boucle de tous les claviers correspondants. J'extrise lesquels les claviers correspondaient entre les deux images, puis extrayez leur (x, y) code> coordonnées. Je dessine ensuite des cercles à chacun des emplacements détectés, puis dessinez une ligne reliant ces cercles ensemble. P>

Gardez à l'esprit que le clavier détecté dans la deuxième image concerne son propre système de coordonnées. Si vous souhaitez placer cela dans l'image de sortie finale, vous devez compenser la colonne coordonnée par la quantité de colonnes à partir de la première image de sorte que la colonne coordonnée soit par rapport au système de coordonnée de l'image de sortie de l'image. . P>

sans autre ado: p> xxx pré>


Pour illustrer que cela fonctionne, voici les deux images que j'ai utilisées: p> Entrez la description de l'image ici p>

 Entrez la description de l'image ici p>

J'ai utilisé le détecteur d'orb d'OpenCV pour détecter les claviers et utiliser la distance de halogerie normalisée comme mesure de distance pour la similarité que ceci est un descripteur binaire. En tant que tel: p>

import numpy as np
import cv2

img1 = cv2.imread('cameraman.png') # Original image
img2 = cv2.imread('cameraman_rot55.png') # Rotated image

# Create ORB detector with 1000 keypoints with a scaling pyramid factor
# of 1.2
orb = cv2.ORB(1000, 1.2)

# Detect keypoints of original image
(kp1,des1) = orb.detectAndCompute(img1, None)

# Detect keypoints of rotated image
(kp2,des2) = orb.detectAndCompute(img2, None)

# Create matcher
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# Do matching
matches = bf.match(des1,des2)

# Sort the matches based on distance.  Least distance
# is better
matches = sorted(matches, key=lambda val: val.distance)

# Show only the top 10 matches
drawMatches(img1, kp1, img2, kp2, matches[:10])


2 commentaires

Hii @rayryeng quand j'essaie de courir au-dessus du code, je reçois la trace de trace (dernier appel le dernier): fichier "orb1.py", ligne 33, dans Out [: row1,: cols1 ,:] = np. DASTACK ([IMG1, IMG1, IMG1]) ValueError: Impossible de diffuser une matrice d'entrée de la forme (900, 1440,9) en forme (900, 1440,3)


@BHUSHANPATIL - Lisez la doctrine de la fonction soigneusement . Il nécessite des images en niveaux de gris. Vous utilisez des images RGB . Vous devez convertir les images en niveaux de gris avant d'utiliser la fonction. Un appel simple cv2.cvtcolor devrait suffire: img = cv2.cvtcolor (img, cv2.color_bgray) fonctionnera. Veuillez réellement lire la documentation de la fonction avant de l'utiliser la prochaine fois. Il s'agit d'une compétence standard que tous les développeurs doivent apprendre lors de l'utilisation du code de quelqu'un d'autre.