Skip to content

Commit dfe3c50

Browse files
committed
Coverage
1 parent af35c7e commit dfe3c50

File tree

3 files changed

+98
-30
lines changed

3 files changed

+98
-30
lines changed
12.9 KB
Loading
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import * as path from "path";
2+
import { Image } from "../../image.class";
3+
import { MatchRequest } from "../../match-request.class";
4+
import { Region } from "../../region.class";
5+
import { TemplateMatchingFinder } from "./template-matching-finder.class";
6+
7+
describe("Template-matching finder", () => {
8+
it("loadImage should resolve to a non-empty Mat on successful load", async () => {
9+
// GIVEN
10+
const SUT = new TemplateMatchingFinder();
11+
const imagePath = path.resolve(__dirname, "./__mocks__/mouse.png");
12+
13+
// WHEN
14+
const result = await SUT.loadImage(imagePath);
15+
16+
// THEN
17+
expect(result.rows).toBeGreaterThan(0);
18+
expect(result.cols).toBeGreaterThan(0);
19+
expect(result.empty).toBeFalsy();
20+
});
21+
22+
it("loadImage should reject on unsuccessful load", async () => {
23+
// GIVEN
24+
const SUT = new TemplateMatchingFinder();
25+
const imagePath = "./__mocks__/foo.png";
26+
27+
// WHEN
28+
const call = SUT.loadImage;
29+
30+
// THEN
31+
await expect(call(imagePath)).rejects.toEqual("empty Mat");
32+
});
33+
34+
it("findMatch should return a match when present in image", async () => {
35+
// GIVEN
36+
const SUT = new TemplateMatchingFinder();
37+
const imagePath = path.resolve(__dirname, "./__mocks__/mouse.png");
38+
const needle = await SUT.loadImage(imagePath);
39+
const minConfidence = 0.99;
40+
const searchRegion = new Region(0, 0, needle.cols, needle.rows);
41+
const haystack = new Image(needle.cols, needle.rows, needle.getData(), 3);
42+
const matchRequest = new MatchRequest(haystack, imagePath, searchRegion, minConfidence);
43+
44+
// WHEN
45+
const result = await SUT.findMatch(matchRequest);
46+
47+
// THEN
48+
expect(result.confidence).toBeGreaterThanOrEqual(minConfidence);
49+
expect(result.location).toEqual(searchRegion);
50+
});
51+
52+
it("findMatch should return a match within a search region when present in image", async () => {
53+
// GIVEN
54+
const SUT = new TemplateMatchingFinder();
55+
const imagePath = path.resolve(__dirname, "./__mocks__/mouse.png");
56+
const needle = await SUT.loadImage(imagePath);
57+
const minConfidence = 0.99;
58+
const searchRegion = new Region(10, 20, 100, 100);
59+
const haystack = new Image(needle.cols, needle.rows, needle.getData(), 3);
60+
const matchRequest = new MatchRequest(haystack, imagePath, searchRegion, minConfidence);
61+
62+
// WHEN
63+
const result = await SUT.findMatch(matchRequest);
64+
65+
// THEN
66+
expect(result.confidence).toBeGreaterThanOrEqual(minConfidence);
67+
expect(result.location).toEqual(searchRegion);
68+
});
69+
70+
it("findMatch should throw on invalid image paths", async () => {
71+
// GIVEN
72+
const SUT = new TemplateMatchingFinder();
73+
const imagePath = path.resolve(__dirname, "./__mocks__/foo.png");
74+
75+
// WHEN
76+
const call = await SUT.loadImage;
77+
78+
// THEN
79+
await expect(call(imagePath)).rejects.toEqual("empty Mat");
80+
});
81+
});

lib/provider/opencv/template-matching-finder.class.ts

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,9 @@ import { FinderInterface } from "./finder.interface";
88
export class TemplateMatchingFinder implements FinderInterface {
99
private static scaleStep = 0.5;
1010

11-
private static async dropAlphaChannel(img: cv.Mat): Promise<cv.Mat> {
12-
if (img.channels === 4) {
13-
return img.cvtColorAsync(cv.COLOR_BGRA2BGR);
14-
} else {
15-
return Promise.resolve(img);
16-
}
11+
constructor() {
1712
}
1813

19-
constructor() {}
20-
2114
public async findMatches(matchRequest: MatchRequest): Promise<MatchResult[]> {
2215
let needle = await this.loadImage(matchRequest.pathToNeedle);
2316
if (needle.empty) {
@@ -29,8 +22,8 @@ export class TemplateMatchingFinder implements FinderInterface {
2922
needle = await this.rgbToGrayScale(needle);
3023
haystack = await this.rgbToGrayScale(haystack);
3124
}
32-
cv.imwriteAsync(`${"input_needle.png"}`, needle);
33-
cv.imwriteAsync(`${"input_haystack.png"}`, haystack);
25+
// cv.imwriteAsync(`${"input_needle.png"}`, needle);
26+
// cv.imwriteAsync(`${"input_haystack.png"}`, haystack);
3427

3528
const matchResults = [];
3629
matchResults.push(await this.match(haystack, needle));
@@ -80,19 +73,6 @@ export class TemplateMatchingFinder implements FinderInterface {
8073
}
8174
}
8275

83-
public async loadImageWithAlphaChannel(imagePath: string): Promise<cv.Mat> {
84-
const image = await this.loadImage(imagePath);
85-
if (image.channels < 4) {
86-
return image.cvtColorAsync(cv.COLOR_BGR2BGRA);
87-
}
88-
return Promise.resolve(image);
89-
}
90-
91-
public async loadImageWithoutAlphaChannel(path: string): Promise<cv.Mat> {
92-
const image = await this.loadImage(path);
93-
return Promise.resolve(TemplateMatchingFinder.dropAlphaChannel(image));
94-
}
95-
9676
public async rgbToGrayScale(img: cv.Mat): Promise<cv.Mat> {
9777
return img.cvtColorAsync(cv.COLOR_BGR2GRAY);
9878
}
@@ -101,11 +81,14 @@ export class TemplateMatchingFinder implements FinderInterface {
10181
img: Image,
10282
roi?: Region,
10383
): Promise<cv.Mat> {
104-
const newMat = await this.fromImageWithAlphaChannel(img, roi);
105-
if (newMat.channels > 3) {
106-
return newMat.cvtColorAsync(cv.COLOR_BGRA2BGR);
84+
const mat = new cv.Mat(img.data, img.height, img.width, cv.CV_8UC3);
85+
if (roi) {
86+
return Promise.resolve(
87+
mat.getRegion(new cv.Rect(roi.left, roi.top, roi.width, roi.height)),
88+
);
89+
} else {
90+
return Promise.resolve(mat);
10791
}
108-
return Promise.resolve(newMat);
10992
}
11093

11194
private async loadHaystack(matchRequest: MatchRequest): Promise<cv.Mat> {
@@ -139,7 +122,7 @@ export class TemplateMatchingFinder implements FinderInterface {
139122
TemplateMatchingFinder.scaleStep,
140123
);
141124
const matchResult = await this.match(scaledHaystack, needle);
142-
cv.imwriteAsync(`${"scaled_haystack.png"}`, scaledHaystack);
125+
// cv.imwriteAsync(`${"scaled_haystack.png"}`, scaledHaystack);
143126
console.log(`Scaled haystack: ${matchResult.confidence}`);
144127
return new MatchResult(
145128
matchResult.confidence,
@@ -161,7 +144,7 @@ export class TemplateMatchingFinder implements FinderInterface {
161144
TemplateMatchingFinder.scaleStep,
162145
);
163146
const matchResult = await this.match(haystack, scaledNeedle);
164-
cv.imwriteAsync(`${"scaled_needle.png"}`, scaledNeedle);
147+
// cv.imwriteAsync(`${"scaled_needle.png"}`, scaledNeedle);
165148
console.log(`Scaled needle: ${matchResult.confidence}`);
166149
return new MatchResult(
167150
matchResult.confidence,
@@ -182,7 +165,11 @@ export class TemplateMatchingFinder implements FinderInterface {
182165
const minMax = await match.minMaxLocAsync();
183166
return new MatchResult(
184167
1.0 - minMax.minVal,
185-
new Region(minMax.minLoc.x, minMax.minLoc.y, needle.cols, needle.rows),
168+
new Region(
169+
minMax.minLoc.x,
170+
minMax.minLoc.y,
171+
Math.min(needle.cols, haystack.cols),
172+
Math.min(needle.rows, haystack.rows)),
186173
);
187174
}
188175

0 commit comments

Comments
 (0)