@@ -60,6 +60,19 @@ function isValidSearch(needle: cv.Mat, haystack: cv.Mat): boolean {
6060 return ( needle . cols <= haystack . cols ) && ( needle . rows <= haystack . rows ) ;
6161}
6262
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+
6376export default class TemplateMatchingFinder implements FinderInterface {
6477 private initialScale = [ 1.0 ] ;
6578 private scaleSteps = [ 0.9 , 0.8 , 0.7 , 0.6 , 0.5 ] ;
@@ -94,69 +107,15 @@ export default class TemplateMatchingFinder implements FinderInterface {
94107 const matchResults = this . initialScale . map (
95108 async ( currentScale ) => {
96109 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 ) ;
106111 }
107112 const matchResult = await matchImages ( haystack , needle ) ;
108113 return new ScaledMatchResult ( matchResult . confidence , currentScale , matchResult . location ) ;
109114 }
110115 ) ;
116+
111117 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 ) )
160119 }
161120
162121 return Promise . all ( matchResults ) . then ( results => {
@@ -173,24 +132,58 @@ export default class TemplateMatchingFinder implements FinderInterface {
173132 }
174133
175134 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 } ` )
189147 }
190- resolve ( potentialMatches [ 0 ] ) ;
191- } catch ( e ) {
192- reject ( e ) ;
148+ } else {
149+ throw new Error ( `Unable to locate ${ matchRequest . pathToNeedle } , no match!` ) ;
193150 }
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 ] ;
195188 }
196189}
0 commit comments