@@ -60,6 +60,19 @@ function isValidSearch(needle: cv.Mat, haystack: cv.Mat): boolean {
60
60
return ( needle . cols <= haystack . cols ) && ( needle . rows <= haystack . rows ) ;
61
61
}
62
62
63
+ function createResultForInvalidSearch ( currentScale : number ) {
64
+ return new ScaledMatchResult ( 0 ,
65
+ currentScale ,
66
+ new Region (
67
+ 0 ,
68
+ 0 ,
69
+ 0 ,
70
+ 0
71
+ ) ,
72
+ new Error ( "The provided image sample is larger than the provided search region" )
73
+ )
74
+ }
75
+
63
76
export default class TemplateMatchingFinder implements FinderInterface {
64
77
private initialScale = [ 1.0 ] ;
65
78
private scaleSteps = [ 0.9 , 0.8 , 0.7 , 0.6 , 0.5 ] ;
@@ -94,69 +107,15 @@ export default class TemplateMatchingFinder implements FinderInterface {
94
107
const matchResults = this . initialScale . map (
95
108
async ( currentScale ) => {
96
109
if ( ! isValidSearch ( needle , haystack ) ) {
97
- return new ScaledMatchResult ( 0 ,
98
- currentScale ,
99
- new Region (
100
- 0 ,
101
- 0 ,
102
- 0 ,
103
- 0
104
- )
105
- ) ;
110
+ return createResultForInvalidSearch ( currentScale ) ;
106
111
}
107
112
const matchResult = await matchImages ( haystack , needle ) ;
108
113
return new ScaledMatchResult ( matchResult . confidence , currentScale , matchResult . location ) ;
109
114
}
110
115
) ;
116
+
111
117
if ( matchRequest . searchMultipleScales ) {
112
- const scaledNeedleResult = this . scaleSteps . map (
113
- async ( currentScale ) => {
114
- const scaledNeedle = await scaleImage ( needle , currentScale ) ;
115
- if ( ! isValidSearch ( scaledNeedle , haystack ) ) {
116
- return new ScaledMatchResult ( 0 ,
117
- currentScale ,
118
- new Region (
119
- 0 ,
120
- 0 ,
121
- 0 ,
122
- 0
123
- )
124
- ) ;
125
- }
126
- const matchResult = await matchImages ( haystack , scaledNeedle ) ;
127
- return new ScaledMatchResult (
128
- matchResult . confidence ,
129
- currentScale ,
130
- matchResult . location ,
131
- ) ;
132
- }
133
- ) ;
134
- const scaledHaystackResult = this . scaleSteps . map (
135
- async ( currentScale ) => {
136
- const scaledHaystack = await scaleImage ( haystack , currentScale ) ;
137
- if ( ! isValidSearch ( needle , scaledHaystack ) ) {
138
- return new ScaledMatchResult ( 0 ,
139
- currentScale ,
140
- new Region (
141
- 0 ,
142
- 0 ,
143
- 0 ,
144
- 0
145
- )
146
- ) ;
147
- }
148
- const matchResult = await matchImages ( scaledHaystack , needle ) ;
149
- return new ScaledMatchResult (
150
- matchResult . confidence ,
151
- currentScale ,
152
- scaleLocation (
153
- matchResult . location ,
154
- currentScale
155
- )
156
- ) ;
157
- }
158
- ) ;
159
- matchResults . push ( ...scaledHaystackResult , ...scaledNeedleResult ) ;
118
+ matchResults . push ( ...this . searchMultipleScales ( needle , haystack ) )
160
119
}
161
120
162
121
return Promise . all ( matchResults ) . then ( results => {
@@ -173,24 +132,58 @@ export default class TemplateMatchingFinder implements FinderInterface {
173
132
}
174
133
175
134
public async findMatch ( matchRequest : MatchRequest , debug : boolean = false ) : Promise < MatchResult > {
176
- return new Promise < MatchResult > ( async ( resolve , reject ) => {
177
- try {
178
- const matches = await this . findMatches ( matchRequest , debug ) ;
179
- const potentialMatches = matches
180
- . filter ( match => match . confidence >= matchRequest . confidence ) ;
181
- if ( potentialMatches . length === 0 ) {
182
- matches . sort ( ( a , b ) => a . confidence - b . confidence ) ;
183
- const bestMatch = matches . pop ( ) ;
184
- if ( bestMatch ) {
185
- reject ( `No match with required confidence ${ matchRequest . confidence } . Best match: ${ bestMatch . confidence } at ${ bestMatch . location } ` )
186
- } else {
187
- reject ( `Unable to locate ${ matchRequest . pathToNeedle } , no match!` ) ;
188
- }
135
+
136
+ const matches = await this . findMatches ( matchRequest , debug ) ;
137
+ const potentialMatches = matches
138
+ . filter ( match => match . confidence >= matchRequest . confidence ) ;
139
+ if ( potentialMatches . length === 0 ) {
140
+ matches . sort ( ( a , b ) => a . confidence - b . confidence ) ;
141
+ const bestMatch = matches . pop ( ) ;
142
+ if ( bestMatch ) {
143
+ if ( bestMatch . error ) {
144
+ throw bestMatch . error
145
+ } else {
146
+ throw new Error ( `No match with required confidence ${ matchRequest . confidence } . Best match: ${ bestMatch . confidence } at ${ bestMatch . location } ` )
189
147
}
190
- resolve ( potentialMatches [ 0 ] ) ;
191
- } catch ( e ) {
192
- reject ( e ) ;
148
+ } else {
149
+ throw new Error ( `Unable to locate ${ matchRequest . pathToNeedle } , no match!` ) ;
193
150
}
194
- } ) ;
151
+ }
152
+ return potentialMatches [ 0 ] ;
153
+ }
154
+
155
+ private searchMultipleScales ( needle : cv . Mat , haystack : cv . Mat ) {
156
+ const scaledNeedleResult = this . scaleSteps . map (
157
+ async ( currentScale ) => {
158
+ const scaledNeedle = await scaleImage ( needle , currentScale ) ;
159
+ if ( ! isValidSearch ( scaledNeedle , haystack ) ) {
160
+ return createResultForInvalidSearch ( currentScale ) ;
161
+ }
162
+ const matchResult = await matchImages ( haystack , scaledNeedle ) ;
163
+ return new ScaledMatchResult (
164
+ matchResult . confidence ,
165
+ currentScale ,
166
+ matchResult . location ,
167
+ ) ;
168
+ }
169
+ ) ;
170
+ const scaledHaystackResult = this . scaleSteps . map (
171
+ async ( currentScale ) => {
172
+ const scaledHaystack = await scaleImage ( haystack , currentScale ) ;
173
+ if ( ! isValidSearch ( needle , scaledHaystack ) ) {
174
+ return createResultForInvalidSearch ( currentScale ) ;
175
+ }
176
+ const matchResult = await matchImages ( scaledHaystack , needle ) ;
177
+ return new ScaledMatchResult (
178
+ matchResult . confidence ,
179
+ currentScale ,
180
+ scaleLocation (
181
+ matchResult . location ,
182
+ currentScale
183
+ )
184
+ ) ;
185
+ }
186
+ ) ;
187
+ return [ ...scaledHaystackResult , ...scaledNeedleResult ] ;
195
188
}
196
189
}
0 commit comments