11import * as cv from "opencv4nodejs" ;
2+ import * as path from "path" ;
23import { Image } from "../../image.class" ;
34import { MatchRequest } from "../../match-request.class" ;
45import { MatchResult } from "../../match-result.class" ;
@@ -34,21 +35,24 @@ export class TemplateMatchingFinder implements FinderInterface {
3435 private static async scaleAndMatchNeedle (
3536 haystack : cv . Mat ,
3637 needle : cv . Mat ,
38+ debug : boolean = false
3739 ) : Promise < MatchResult > {
3840 const scaledNeedle = await TemplateMatchingFinder . scale (
3941 needle ,
4042 TemplateMatchingFinder . scaleStep ,
4143 ) ;
4244 const matchResult = await TemplateMatchingFinder . match ( haystack , scaledNeedle ) ;
43- // cv.imwriteAsync(`${"scaled_needle.png"}`, scaledNeedle);
44- console . log ( `Scaled needle: ${ matchResult . confidence } ` ) ;
45+ if ( debug ) {
46+ this . debugImage ( scaledNeedle , "scaled_needle.png" ) ;
47+ console . log ( `Scaled needle: ${ matchResult . confidence } ` ) ;
48+ }
4549 return new MatchResult (
4650 matchResult . confidence ,
4751 new Region (
4852 matchResult . location . left ,
4953 matchResult . location . top ,
50- scaledNeedle . cols ,
51- scaledNeedle . rows ,
54+ needle . cols ,
55+ needle . rows ,
5256 ) ,
5357 ) ;
5458 }
@@ -63,14 +67,17 @@ export class TemplateMatchingFinder implements FinderInterface {
6367 private static async scaleAndMatchHaystack (
6468 haystack : cv . Mat ,
6569 needle : cv . Mat ,
70+ debug : boolean = false
6671 ) : Promise < MatchResult > {
6772 const scaledHaystack = await TemplateMatchingFinder . scale (
6873 haystack ,
6974 TemplateMatchingFinder . scaleStep ,
7075 ) ;
7176 const matchResult = await TemplateMatchingFinder . match ( scaledHaystack , needle ) ;
72- // cv.imwriteAsync(`${"scaled_haystack.png"}`, scaledHaystack);
73- console . log ( `Scaled haystack: ${ matchResult . confidence } ` ) ;
77+ if ( debug ) {
78+ this . debugImage ( scaledHaystack , "scaled_haystack.png" ) ;
79+ console . log ( `Scaled haystack: ${ matchResult . confidence } ` ) ;
80+ }
7481 return new MatchResult (
7582 matchResult . confidence ,
7683 new Region (
@@ -82,31 +89,79 @@ export class TemplateMatchingFinder implements FinderInterface {
8289 ) ;
8390 }
8491
92+ private static async debugImage ( image : cv . Mat , filename : string , suffix ?: string ) {
93+ const parsedPath = path . parse ( filename ) ;
94+ let fullFilename = parsedPath . name ;
95+ if ( suffix ) {
96+ fullFilename = fullFilename + "_" + suffix ;
97+ }
98+ fullFilename += parsedPath . ext ;
99+ const fullPath = path . join ( parsedPath . dir , fullFilename ) ;
100+ cv . imwriteAsync ( fullPath , image ) ;
101+ }
102+
103+ private static async debugResult ( image : cv . Mat , result : MatchResult , filename : string , suffix ?: string ) {
104+ const roiRect = new cv . Rect (
105+ result . location . left ,
106+ result . location . top ,
107+ result . location . width ,
108+ result . location . height ) ;
109+ this . debugImage ( image . getRegion ( roiRect ) , filename , suffix ) ;
110+ }
111+
85112 constructor ( ) {
86113 }
87114
88- public async findMatches ( matchRequest : MatchRequest ) : Promise < MatchResult [ ] > {
89- let needle = await this . loadImage ( matchRequest . pathToNeedle ) ;
115+ public async findMatches ( matchRequest : MatchRequest , debug : boolean = false ) : Promise < MatchResult [ ] > {
116+ const needle = await this . loadImage ( matchRequest . pathToNeedle ) ;
90117 if ( needle . empty ) {
91118 throw new Error (
92119 `Failed to load ${ matchRequest . pathToNeedle } , got empty image.` ,
93120 ) ;
94121 }
95- let haystack = await this . loadHaystack ( matchRequest ) ;
122+ const haystack = await this . loadHaystack ( matchRequest ) ;
96123
97- if ( matchRequest . confidence < 0.99 ) {
98- needle = await this . rgbToGrayScale ( needle ) ;
99- haystack = await this . rgbToGrayScale ( haystack ) ;
124+ if ( debug ) {
125+ TemplateMatchingFinder . debugImage ( needle , "input_needle.png" ) ;
126+ TemplateMatchingFinder . debugImage ( haystack , "input_haystack.png" ) ;
100127 }
101- // cv.imwriteAsync(`${"input_needle.png"}`, needle);
102- // cv.imwriteAsync(`${"input_haystack.png"}`, haystack);
103128
104129 const matchResults = [ ] ;
105- matchResults . push ( await TemplateMatchingFinder . match ( haystack , needle ) ) ;
106- if ( matchRequest . searchMultipleScales ) {
107- matchResults . push ( await TemplateMatchingFinder . scaleAndMatchHaystack ( haystack , needle ) ) ;
108- matchResults . push ( await TemplateMatchingFinder . scaleAndMatchNeedle ( haystack , needle ) ) ;
130+ const unscaledResult = await TemplateMatchingFinder . match ( haystack , needle ) ;
131+ if ( debug ) {
132+ console . log ( `Unscaled result: ${ unscaledResult . confidence } ` ) ;
133+ TemplateMatchingFinder . debugResult (
134+ haystack ,
135+ unscaledResult ,
136+ matchRequest . pathToNeedle ,
137+ "unscaled_result" ) ;
138+ }
139+ if (
140+ matchRequest . searchMultipleScales &&
141+ unscaledResult . confidence >= Math . max ( matchRequest . confidence - 0.1 , 0.6 )
142+ ) {
143+ const scaledHaystack = await TemplateMatchingFinder . scaleAndMatchHaystack ( haystack , needle , debug ) ;
144+ if ( debug ) {
145+ TemplateMatchingFinder . debugResult (
146+ haystack ,
147+ scaledHaystack ,
148+ matchRequest . pathToNeedle ,
149+ "scaled_haystack_result"
150+ ) ;
151+ }
152+ matchResults . push ( scaledHaystack ) ;
153+ const scaledNeedle = await TemplateMatchingFinder . scaleAndMatchNeedle ( haystack , needle , debug ) ;
154+ if ( debug ) {
155+ TemplateMatchingFinder . debugResult (
156+ haystack ,
157+ scaledNeedle ,
158+ matchRequest . pathToNeedle ,
159+ "scaled_needle_result"
160+ ) ;
161+ }
162+ matchResults . push ( scaledNeedle ) ;
109163 }
164+ matchResults . push ( unscaledResult ) ;
110165
111166 // Compensate pixel density
112167 matchResults . forEach ( matchResult => {
@@ -121,8 +176,8 @@ export class TemplateMatchingFinder implements FinderInterface {
121176 ) ;
122177 }
123178
124- public async findMatch ( matchRequest : MatchRequest ) : Promise < MatchResult > {
125- const matches = await this . findMatches ( matchRequest ) ;
179+ public async findMatch ( matchRequest : MatchRequest , debug : boolean = false ) : Promise < MatchResult > {
180+ const matches = await this . findMatches ( matchRequest , debug ) ;
126181 if ( matches . length === 0 ) {
127182 throw new Error (
128183 `Unable to locate ${ matchRequest . pathToNeedle } , no match!` ,
0 commit comments