~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Feature Matching + Homography to find Objects {#tutorial_py_feature_homography}
 
2
=============================================
 
3
 
 
4
Goal
 
5
----
 
6
 
 
7
In this chapter,
 
8
    -   We will mix up the feature matching and findHomography from calib3d module to find known
 
9
        objects in a complex image.
 
10
 
 
11
Basics
 
12
------
 
13
 
 
14
So what we did in last session? We used a queryImage, found some feature points in it, we took
 
15
another trainImage, found the features in that image too and we found the best matches among them.
 
16
In short, we found locations of some parts of an object in another cluttered image. This information
 
17
is sufficient to find the object exactly on the trainImage.
 
18
 
 
19
For that, we can use a function from calib3d module, ie **cv2.findHomography()**. If we pass the set
 
20
of points from both the images, it will find the perpective transformation of that object. Then we
 
21
can use **cv2.perspectiveTransform()** to find the object. It needs atleast four correct points to
 
22
find the transformation.
 
23
 
 
24
We have seen that there can be some possible errors while matching which may affect the result. To
 
25
solve this problem, algorithm uses RANSAC or LEAST_MEDIAN (which can be decided by the flags). So
 
26
good matches which provide correct estimation are called inliers and remaining are called outliers.
 
27
**cv2.findHomography()** returns a mask which specifies the inlier and outlier points.
 
28
 
 
29
So let's do it !!!
 
30
 
 
31
Code
 
32
----
 
33
 
 
34
First, as usual, let's find SIFT features in images and apply the ratio test to find the best
 
35
matches.
 
36
@code{.py}
 
37
import numpy as np
 
38
import cv2
 
39
from matplotlib import pyplot as plt
 
40
 
 
41
MIN_MATCH_COUNT = 10
 
42
 
 
43
img1 = cv2.imread('box.png',0)          # queryImage
 
44
img2 = cv2.imread('box_in_scene.png',0) # trainImage
 
45
 
 
46
# Initiate SIFT detector
 
47
sift = cv2.xfeatures2d.SIFT_create()
 
48
 
 
49
# find the keypoints and descriptors with SIFT
 
50
kp1, des1 = sift.detectAndCompute(img1,None)
 
51
kp2, des2 = sift.detectAndCompute(img2,None)
 
52
 
 
53
FLANN_INDEX_KDTREE = 0
 
54
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
 
55
search_params = dict(checks = 50)
 
56
 
 
57
flann = cv2.FlannBasedMatcher(index_params, search_params)
 
58
 
 
59
matches = flann.knnMatch(des1,des2,k=2)
 
60
 
 
61
# store all the good matches as per Lowe's ratio test.
 
62
good = []
 
63
for m,n in matches:
 
64
    if m.distance < 0.7*n.distance:
 
65
        good.append(m)
 
66
@endcode
 
67
Now we set a condition that atleast 10 matches (defined by MIN_MATCH_COUNT) are to be there to
 
68
find the object. Otherwise simply show a message saying not enough matches are present.
 
69
 
 
70
If enough matches are found, we extract the locations of matched keypoints in both the images. They
 
71
are passed to find the perpective transformation. Once we get this 3x3 transformation matrix, we use
 
72
it to transform the corners of queryImage to corresponding points in trainImage. Then we draw it.
 
73
@code{.py}
 
74
if len(good)>MIN_MATCH_COUNT:
 
75
    src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
 
76
    dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
 
77
 
 
78
    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
 
79
    matchesMask = mask.ravel().tolist()
 
80
 
 
81
    h,w,d = img1.shape
 
82
    pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
 
83
    dst = cv2.perspectiveTransform(pts,M)
 
84
 
 
85
    img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA)
 
86
 
 
87
else:
 
88
    print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
 
89
    matchesMask = None
 
90
@endcode
 
91
Finally we draw our inliers (if successfully found the object) or matching keypoints (if failed).
 
92
@code{.py}
 
93
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
 
94
                   singlePointColor = None,
 
95
                   matchesMask = matchesMask, # draw only inliers
 
96
                   flags = 2)
 
97
 
 
98
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
 
99
 
 
100
plt.imshow(img3, 'gray'),plt.show()
 
101
@endcode
 
102
See the result below. Object is marked in white color in cluttered image:
 
103
 
 
104
![image](images/homography_findobj.jpg)
 
105
 
 
106
Additional Resources
 
107
--------------------
 
108
 
 
109
Exercises
 
110
---------