J'ai essayé de créer un matcher qui utilise Sift pour détecter et faire correspondre les points clés. J'ai essayé de l'utiliser mais je n'ai pas obtenu les résultats que j'attendais. Il s'avère que ce n'est pas tellement l'échelle et la rotation invariant dans ma mise en œuvre. Quel est le problème avec mon code?J'ai eu de mauvais résultats avec OpenCV et SIFT. Comment pourrais-je l'améliorer?
import numpy as np
import cv2
from matplotlib import pyplot as plt
import sys
def drawMatches(img1, kp1, img2, kp2, matches):
# Create a new output image that concatenates the two images together
# (a.k.a) a montage
rows1 = img1.shape[0]
cols1 = img1.shape[1]
rows2 = img2.shape[0]
cols2 = img2.shape[1]
out = np.zeros((max([rows1,rows2]),cols1+cols2,3), dtype='uint8')
# Place the first image to the left
out[:rows1,:cols1] = np.dstack([img1, img1, img1])
# Place the next image to the right of it
out[:rows2,cols1:] = np.dstack([img2, img2, img2])
# For each pair of points we have between both images
# draw circles, then connect a line between them
for mat in matches:
# Get the matching keypoints for each of the images
img1_idx = mat.queryIdx
img2_idx = mat.trainIdx
# x - columns
# y - rows
(x1,y1) = kp1[img1_idx].pt
(x2,y2) = kp2[img2_idx].pt
# Draw a small circle at both co-ordinates
# radius 4
# colour blue
# thickness = 1
cv2.circle(out, (int(x1),int(y1)), 4, (255, 0, 0), 1)
cv2.circle(out, (int(x2)+cols1,int(y2)), 4, (255, 0, 0), 1)
# Draw a line in between the two points
# thickness = 1
# colour blue
cv2.line(out, (int(x1),int(y1)), (int(x2)+cols1,int(y2)), (255, 0, 0), 1)
# Also return the image if you'd like a copy
return out
img2 = []
cap = cv2.VideoCapture(0)
#Capture the template
while True:
ret, img = cap.read()
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
x=220
y=165
w=200
h=150
cv2.rectangle(img, (x, y), (x+w, y+h), (255,0,0), 2)
cv2.imshow('Capture it!',img)
if cv2.waitKey(1) & 0xFF == ord('q'):
#Crop out roi
img2 = img[y:y+h, x:x+w]
#Resize for stacking
img2 = cv2.resize(img2, (640, 480))
print "Template OK"
break
cv2.destroyAllWindows()
sift = cv2.SIFT_create()
#Detect and compute keypoints on template image
(kp2,des2) = sift.detectAndCompute(img2,None)
while True:
ret, img1 = cap.read()
img1 = cv2.cvtColor(img1, cv2.cv.CV_BGR2GRAY)
# Detect keypoints of original image
(kp1,des1) = sift.detectAndCompute(img1,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 - also save a copy for use later
out = drawMatches(img1, kp1, img2, kp2, matches[:10])
# Show the image
cv2.imshow('Matched Features', out)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Vous pouvez voir les résultats ici: http://i.giphy.com/26BRyPZpaoNyB0IkE.gif
Dans le code que vous utilisez ORB, pas 'EIPD: = orbe cv2.ORB() #Detect et calculer sur l'image keypoints modèle (kp2, des2) = orb.detectAndCompute (img2, None) '. Essayez d'utiliser SIFT ou KAZE/AKAZE – taarraas
Désolé je viens de télécharger le mauvais code, je vais le corriger très bientôt. – Gabe
Ce résultat me semble tout à fait correct. Ton image a beaucoup de bruit de fond, donc c'est normal qu'elle ait des faux positifs puisque tu n'utilises pas de seuil pour les matchs – ZWiki