378099a9319fc5f0e2de9376d775a8c7d65b3a8d
[platform/upstream/opencv.git] /
1 Contours : More Functions {#tutorial_py_contours_more_functions}
2 =========================
3
4 Goal
5 ----
6
7 In this chapter, we will learn about
8     -   Convexity defects and how to find them.
9     -   Finding shortest distance from a point to a polygon
10     -   Matching different shapes
11
12 Theory and Code
13 ---------------
14
15 ### 1. Convexity Defects
16
17 We saw what is convex hull in second chapter about contours. Any deviation of the object from this
18 hull can be considered as convexity defect.
19
20 OpenCV comes with a ready-made function to find this, **cv.convexityDefects()**. A basic function
21 call would look like below:
22 @code{.py}
23 hull = cv.convexHull(cnt,returnPoints = False)
24 defects = cv.convexityDefects(cnt,hull)
25 @endcode
26
27 @note Remember we have to pass returnPoints = False while finding convex hull, in order to find
28 convexity defects.
29
30 It returns an array where each row contains these values - **[ start point, end point, farthest
31 point, approximate distance to farthest point ]**. We can visualize it using an image. We draw a
32 line joining start point and end point, then draw a circle at the farthest point. Remember first
33 three values returned are indices of cnt. So we have to bring those values from cnt.
34
35 @code{.py}
36 import cv2 as cv
37 import numpy as np
38
39 img = cv.imread('star.jpg')
40 img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
41 ret,thresh = cv.threshold(img_gray, 127, 255,0)
42 im2,contours,hierarchy = cv.findContours(thresh,2,1)
43 cnt = contours[0]
44
45 hull = cv.convexHull(cnt,returnPoints = False)
46 defects = cv.convexityDefects(cnt,hull)
47
48 for i in range(defects.shape[0]):
49     s,e,f,d = defects[i,0]
50     start = tuple(cnt[s][0])
51     end = tuple(cnt[e][0])
52     far = tuple(cnt[f][0])
53     cv.line(img,start,end,[0,255,0],2)
54     cv.circle(img,far,5,[0,0,255],-1)
55
56 cv.imshow('img',img)
57 cv.waitKey(0)
58 cv.destroyAllWindows()
59 @endcode
60 And see the result:
61
62 ![image](images/defects.jpg)
63
64 ### 2. Point Polygon Test
65
66 This function finds the shortest distance between a point in the image and a contour. It returns the
67 distance which is negative when point is outside the contour, positive when point is inside and zero
68 if point is on the contour.
69
70 For example, we can check the point (50,50) as follows:
71 @code{.py}
72 dist = cv.pointPolygonTest(cnt,(50,50),True)
73 @endcode
74 In the function, third argument is measureDist. If it is True, it finds the signed distance. If
75 False, it finds whether the point is inside or outside or on the contour (it returns +1, -1, 0
76 respectively).
77
78 @note If you don't want to find the distance, make sure third argument is False, because, it is a
79 time consuming process. So, making it False gives about 2-3X speedup.
80
81 ### 3. Match Shapes
82
83 OpenCV comes with a function **cv.matchShapes()** which enables us to compare two shapes, or two
84 contours and returns a metric showing the similarity. The lower the result, the better match it is.
85 It is calculated based on the hu-moment values. Different measurement methods are explained in the
86 docs.
87 @code{.py}
88 import cv2 as cv
89 import numpy as np
90
91 img1 = cv.imread('star.jpg',0)
92 img2 = cv.imread('star2.jpg',0)
93
94 ret, thresh = cv.threshold(img1, 127, 255,0)
95 ret, thresh2 = cv.threshold(img2, 127, 255,0)
96 im2,contours,hierarchy = cv.findContours(thresh,2,1)
97 cnt1 = contours[0]
98 im2,contours,hierarchy = cv.findContours(thresh2,2,1)
99 cnt2 = contours[0]
100
101 ret = cv.matchShapes(cnt1,cnt2,1,0.0)
102 print( ret )
103 @endcode
104 I tried matching shapes with different shapes given below:
105
106 ![image](images/matchshapes.jpg)
107
108 I got following results:
109
110 -   Matching Image A with itself = 0.0
111 -   Matching Image A with Image B = 0.001946
112 -   Matching Image A with Image C = 0.326911
113
114 See, even image rotation doesn't affect much on this comparison.
115
116 @sa [Hu-Moments](http://en.wikipedia.org/wiki/Image_moment#Rotation_invariant_moments) are seven
117 moments invariant to translation, rotation and scale. Seventh one is skew-invariant. Those values
118 can be found using **cv.HuMoments()** function.
119
120 Additional Resources
121 ====================
122
123 Exercises
124 ---------
125
126 -#  Check the documentation for **cv.pointPolygonTest()**, you can find a nice image in Red and
127     Blue color. It represents the distance from all pixels to the white curve on it. All pixels
128     inside curve is blue depending on the distance. Similarly outside points are red. Contour edges
129     are marked with White. So problem is simple. Write a code to create such a representation of
130     distance.
131 -#  Compare images of digits or letters using **cv.matchShapes()**. ( That would be a simple step
132     towards OCR )