title: I got bad matching results with OpenCV and SIFT. How could I improve it?
body: <p>I tried to create a matcher which uses sift to detect and match key-points. I tried to use it but I didn't get the results what I expected. It turns out it's not so scale and rotation invariant in my implementation. What is wrong with my code?</p>
  
  <pre><code>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) &amp; 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) &amp; 0xFF == ord('q'):
          break
  
  cap.release()
  cv2.destroyAllWindows()
  </code></pre>
  
  <p>You can see the results here: <a href="http://i.giphy.com/26BRyPZpaoNyB0IkE.gif" rel="nofollow">http://i.giphy.com/26BRyPZpaoNyB0IkE.gif</a></p>