@@ -46,22 +46,30 @@ def _findLocalMin_(corrMap, score_threshold=0.4):
46
46
47
47
48
48
49
- def findMatches (listTemplates , image , method = cv2 .TM_CCOEFF_NORMED , N_object = float ("inf" ), score_threshold = 0.5 ):
49
+ def findMatches (listTemplates , image , method = cv2 .TM_CCOEFF_NORMED , N_object = float ("inf" ), score_threshold = 0.5 , searchBox = None ):
50
50
'''
51
51
Find all possible templates locations provided a list of template to search and an image
52
52
- listTemplate : list of tuples [(templateName, templateImage), (templateName2, templateImage2) ]
53
53
- method : one of OpenCV template matching method (0 to 5)
54
54
- N_object: expected number of object in the image
55
- - score_threshold: if N>1, returns local minima/maxima respectively below/above the score_threshold
55
+ - score_threshold: if N>1, returns local minima/maxima respectively below/above the score_threshold
56
+ - searchBox : optional search region as a tuple (X, Y, Width, Height)
56
57
'''
57
58
if N_object != float ("inf" ) and type (N_object )!= int :
58
59
raise TypeError ("N_object must be an integer" )
59
60
60
61
elif N_object < 1 :
61
62
raise ValueError ("At least one object should be expected in the image" )
63
+
64
+ ## Crop image to search region if provided
65
+ if searchBox != None :
66
+ xOffset , yOffset , searchWidth , searchHeight = searchBox
67
+ image = image [yOffset :yOffset + searchHeight , xOffset :xOffset + searchWidth ]
68
+ else :
69
+ xOffset = yOffset = 0
62
70
63
71
## 16-bit image are converted to 32-bit for matchTemplate
64
- if image .dtype == 'uint16' : image = np .float32 (image )
72
+ if image .dtype == 'uint16' : image = np .float32 (image )
65
73
66
74
listHit = []
67
75
for templateName , template in listTemplates :
@@ -99,9 +107,10 @@ def findMatches(listTemplates, image, method=cv2.TM_CCOEFF_NORMED, N_object=floa
99
107
## Create a dictionnary for each hit with {'TemplateName':, 'BBox': (x,y,Width, Height), 'Score':coeff}
100
108
101
109
height , width = template .shape [0 :2 ] # slicing make sure it works for RGB too
110
+
102
111
for peak in Peaks :
103
112
coeff = corrMap [tuple (peak )]
104
- newHit = {'TemplateName' :templateName , 'BBox' : [int (peak [1 ]), int (peak [0 ]), width , height ], 'Score' :coeff }
113
+ newHit = {'TemplateName' :templateName , 'BBox' : [int (peak [1 ])+ xOffset , int (peak [0 ])+ yOffset , width , height ], 'Score' :coeff }
105
114
106
115
# append to list of potential hit before Non maxima suppression
107
116
listHit .append (newHit )
@@ -110,7 +119,7 @@ def findMatches(listTemplates, image, method=cv2.TM_CCOEFF_NORMED, N_object=floa
110
119
return listHit # All possible hit before Non-Maxima Supression
111
120
112
121
113
- def matchTemplates (listTemplates , image , method = cv2 .TM_CCOEFF_NORMED , N_object = float ("inf" ), score_threshold = 0.5 , maxOverlap = 0.25 ):
122
+ def matchTemplates (listTemplates , image , method = cv2 .TM_CCOEFF_NORMED , N_object = float ("inf" ), score_threshold = 0.5 , maxOverlap = 0.25 , searchBox = None ):
114
123
'''
115
124
Search each template in the image, and return the best N_object location which offer the best score and which do not overlap
116
125
- listTemplate : list of tuples (templateName, templateImage)
@@ -121,7 +130,7 @@ def matchTemplates(listTemplates, image, method=cv2.TM_CCOEFF_NORMED, N_object=f
121
130
if maxOverlap < 0 or maxOverlap > 1 :
122
131
raise ValueError ("Maximal overlap between bounding box is in range [0-1]" )
123
132
124
- listHit = findMatches (listTemplates , image , method , N_object , score_threshold )
133
+ listHit = findMatches (listTemplates , image , method , N_object , score_threshold , searchBox )
125
134
126
135
if method == 1 : bestHits = NMS (listHit , N_object = N_object , maxOverlap = maxOverlap , sortDescending = False )
127
136
0 commit comments