forked from bnsreenu/python_for_microscopists
-
Notifications
You must be signed in to change notification settings - Fork 0
/
118_object_detection_by_template_matching.py
85 lines (63 loc) · 3.29 KB
/
118_object_detection_by_template_matching.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python
__author__ = "Sreenivas Bhattiprolu"
__license__ = "Feel free to copy, I appreciate if you acknowledge Python for Microscopists"
#https://youtu.be/P5FTEryiTl4
"""
OBJECT DETECTION WITH TEMPLATES
Need a source image and a template image.
The template image T is slided over the source image (as in 2D convolution),
and the program tries to find matches using statistics.
Several comparison methods are implemented in OpenCV.
It returns a grayscale image, where each pixel denotes how much does the
neighbourhood of that pixel match with template.
Once you got the result, you can use cv2.minMaxLoc() function
to find where is the maximum/minimum value. Take it as the top-left corner of the
rectangle and take (w,h) as width and height of the rectangle.
That rectangle can be drawn on the region of matched template.
"""
### Template matching, single object in an image.
#Multiple methods to see which one works best.
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('images/f16.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('images/f16_template.jpg', 0)
h, w = template.shape[::]
#methods available: ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
# 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
res = cv2.matchTemplate(img_gray, template, cv2.TM_SQDIFF)
# For TM_SQDIFF, Good match yields minimum value; bad match yields large values
# For all others it is exactly opposite, max value = good fit.
plt.imshow(res, cmap='gray')
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = min_loc #Change to max_loc for all except for TM_SQDIFF
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img_gray, top_left, bottom_right, 255, 2) #White rectangle with thickness 2.
cv2.imshow("Matched image", img_gray)
cv2.waitKey()
cv2.destroyAllWindows()
### Template matching - multiple objects
#For multiple occurances, cv2.minMaxLoc() won’t give all the locations
#So we need to set a threshold
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('images/bubbles.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('images/bubbles_template.png',0)
h, w = template.shape[::]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
plt.imshow(res, cmap='gray')
threshold = 0.8 #Pick only values above 0.8. For TM_CCOEFF_NORMED, larger values = good fit.
loc = np.where( res >= threshold)
#Outputs 2 arrays. Combine these arrays to get x,y coordinates - take x from one array and y from the other.
#Reminder: ZIP function is an iterator of tuples where first item in each iterator is paired together,
#then the second item and then third, etc.
for pt in zip(*loc[::-1]): #-1 to swap the values as we assign x and y coordinate to draw the rectangle.
#Draw rectangle around each object. We know the top left (pt), draw rectangle to match the size of the template image.
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) #Red rectangles with thickness 2.
#cv2.imwrite('images/template_matched.jpg', img_rgb)
cv2.imshow("Matched image", img_rgb)
cv2.waitKey()
cv2.destroyAllWindows()