1
1
import * as cv from "opencv4nodejs" ;
2
+ import * as path from "path" ;
2
3
import { Image } from "../../image.class" ;
3
4
import { MatchRequest } from "../../match-request.class" ;
4
5
import { MatchResult } from "../../match-result.class" ;
@@ -34,21 +35,24 @@ export class TemplateMatchingFinder implements FinderInterface {
34
35
private static async scaleAndMatchNeedle (
35
36
haystack : cv . Mat ,
36
37
needle : cv . Mat ,
38
+ debug : boolean = false
37
39
) : Promise < MatchResult > {
38
40
const scaledNeedle = await TemplateMatchingFinder . scale (
39
41
needle ,
40
42
TemplateMatchingFinder . scaleStep ,
41
43
) ;
42
44
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
+ }
45
49
return new MatchResult (
46
50
matchResult . confidence ,
47
51
new Region (
48
52
matchResult . location . left ,
49
53
matchResult . location . top ,
50
- scaledNeedle . cols ,
51
- scaledNeedle . rows ,
54
+ needle . cols ,
55
+ needle . rows ,
52
56
) ,
53
57
) ;
54
58
}
@@ -63,14 +67,17 @@ export class TemplateMatchingFinder implements FinderInterface {
63
67
private static async scaleAndMatchHaystack (
64
68
haystack : cv . Mat ,
65
69
needle : cv . Mat ,
70
+ debug : boolean = false
66
71
) : Promise < MatchResult > {
67
72
const scaledHaystack = await TemplateMatchingFinder . scale (
68
73
haystack ,
69
74
TemplateMatchingFinder . scaleStep ,
70
75
) ;
71
76
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
+ }
74
81
return new MatchResult (
75
82
matchResult . confidence ,
76
83
new Region (
@@ -82,31 +89,79 @@ export class TemplateMatchingFinder implements FinderInterface {
82
89
) ;
83
90
}
84
91
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
+
85
112
constructor ( ) {
86
113
}
87
114
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 ) ;
90
117
if ( needle . empty ) {
91
118
throw new Error (
92
119
`Failed to load ${ matchRequest . pathToNeedle } , got empty image.` ,
93
120
) ;
94
121
}
95
- let haystack = await this . loadHaystack ( matchRequest ) ;
122
+ const haystack = await this . loadHaystack ( matchRequest ) ;
96
123
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" ) ;
100
127
}
101
- // cv.imwriteAsync(`${"input_needle.png"}`, needle);
102
- // cv.imwriteAsync(`${"input_haystack.png"}`, haystack);
103
128
104
129
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 ) ;
109
163
}
164
+ matchResults . push ( unscaledResult ) ;
110
165
111
166
// Compensate pixel density
112
167
matchResults . forEach ( matchResult => {
@@ -121,8 +176,8 @@ export class TemplateMatchingFinder implements FinderInterface {
121
176
) ;
122
177
}
123
178
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 ) ;
126
181
if ( matches . length === 0 ) {
127
182
throw new Error (
128
183
`Unable to locate ${ matchRequest . pathToNeedle } , no match!` ,
0 commit comments