@udarrr/template-matcher
Advanced tools
Comparing version 1.1.7 to 1.1.8
import * as cv from "opencv4nodejs-prebuilt"; | ||
import { Image, Region } from "@nut-tree/nut-js"; | ||
export declare function determineROI(img: Image, roi: Region): cv.Rect; | ||
export declare function determineMatRectROI(img: Image, roi: Region): cv.Rect; | ||
export declare function determineRegionRectROI(roi: cv.Rect): Region; | ||
export declare function validateSearchRegion(search: Region, screen: Region): void; | ||
@@ -14,3 +15,3 @@ /** | ||
*/ | ||
export declare const fromImageWithAlphaChannel: (img: Image, roi?: Region | undefined) => Promise<cv.Mat>; | ||
export declare const fromImageWithAlphaChannel: (img: Image, roi?: cv.Rect | undefined) => Promise<cv.Mat>; | ||
/** | ||
@@ -25,3 +26,3 @@ * fromImageWithoutAlphaChannel should provide a way to create a library specific | ||
*/ | ||
export declare const fromImageWithoutAlphaChannel: (img: Image, roi?: Region | undefined) => Promise<cv.Mat>; | ||
export declare const fromImageWithoutAlphaChannel: (img: Image, roi?: cv.Rect | undefined) => Promise<cv.Mat>; | ||
//# sourceMappingURL=image-processor.class.d.ts.map |
@@ -22,9 +22,13 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.fromImageWithoutAlphaChannel = exports.fromImageWithAlphaChannel = exports.validateSearchRegion = exports.determineROI = void 0; | ||
exports.fromImageWithoutAlphaChannel = exports.fromImageWithAlphaChannel = exports.validateSearchRegion = exports.determineRegionRectROI = exports.determineMatRectROI = void 0; | ||
const cv = __importStar(require("opencv4nodejs-prebuilt")); | ||
const nut_js_1 = require("@nut-tree/nut-js"); | ||
function determineROI(img, roi) { | ||
function determineMatRectROI(img, roi) { | ||
return new cv.Rect(Math.min(Math.max(roi.left, 0), img.width), Math.min(Math.max(roi.top, 0), img.height), Math.min(roi.width, img.width - roi.left), Math.min(roi.height, img.height - roi.top)); | ||
} | ||
exports.determineROI = determineROI; | ||
exports.determineMatRectROI = determineMatRectROI; | ||
function determineRegionRectROI(roi) { | ||
return new nut_js_1.Region(roi.x, roi.y, roi.width, roi.height); | ||
} | ||
exports.determineRegionRectROI = determineRegionRectROI; | ||
function validateSearchRegion(search, screen) { | ||
@@ -70,3 +74,3 @@ if (search.left < 0 || | ||
if (roi) { | ||
return mat.getRegion(determineROI(img, roi)); | ||
return mat.getRegion(roi); | ||
} | ||
@@ -96,3 +100,3 @@ else { | ||
if (roi) { | ||
return mat.getRegion(determineROI(img, roi)); | ||
return mat.getRegion(roi); | ||
} | ||
@@ -99,0 +103,0 @@ else { |
@@ -48,3 +48,3 @@ "use strict"; | ||
// WHEN | ||
const mat = await (0, image_processor_class_1.fromImageWithoutAlphaChannel)(image, new nut_js_1.Region(-100, -100, 10, 10)); | ||
const mat = await (0, image_processor_class_1.fromImageWithoutAlphaChannel)(image, (0, image_processor_class_1.determineMatRectROI)(image, new nut_js_1.Region(-100, -100, 10, 10))); | ||
// THEN | ||
@@ -63,3 +63,3 @@ expect(image.hasAlphaChannel).toBeFalsy(); | ||
// WHEN | ||
const mat = await (0, image_processor_class_1.fromImageWithoutAlphaChannel)(image, new nut_js_1.Region(10, 10, image.width * 2, image.height * 2)); | ||
const mat = await (0, image_processor_class_1.fromImageWithoutAlphaChannel)(image, (0, image_processor_class_1.determineMatRectROI)(image, new nut_js_1.Region(10, 10, image.width * 2, image.height * 2))); | ||
// THEN | ||
@@ -66,0 +66,0 @@ expect(image.hasAlphaChannel).toBeFalsy(); |
@@ -1,7 +0,5 @@ | ||
import * as cv from 'opencv4nodejs-prebuilt'; | ||
import { Image, ImageReader } from '@nut-tree/nut-js'; | ||
export default class implements ImageReader { | ||
load(path: string): Promise<Image>; | ||
readToMat(path: string): Promise<cv.Mat>; | ||
} | ||
//# sourceMappingURL=image-reader.class.d.ts.map |
@@ -36,5 +36,2 @@ "use strict"; | ||
} | ||
async readToMat(path) { | ||
return await cv.imreadAsync(path, cv.IMREAD_GRAYSCALE); | ||
} | ||
} | ||
@@ -41,0 +38,0 @@ exports.default = default_1; |
@@ -30,2 +30,4 @@ import { Image, ImageFinderInterface, MatchRequest, MatchResult, Region } from '@nut-tree/nut-js'; | ||
findMatches(matchRequest: MatchRequest | CustomMatchRequest): Promise<MatchResult[]>; | ||
private getIncreasedRectByPixelDensity; | ||
private getDecreasedRectByPixelDensity; | ||
private getValidatedMatches; | ||
@@ -32,0 +34,0 @@ findMatch(matchRequest: MatchRequest | CustomMatchRequest): Promise<MatchResult>; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -10,16 +7,10 @@ const nut_js_1 = require("@nut-tree/nut-js"); | ||
const image_processor_class_1 = require("./image-processor.class"); | ||
const image_reader_class_1 = __importDefault(require("./image-reader.class")); | ||
class TemplateMatchingFinder { | ||
constructor() { } | ||
async loadNeedle(image, roi) { | ||
async loadNeedle(image) { | ||
if (typeof image !== 'string') { | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(image, roi), rect: null }; | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(image) }; | ||
} | ||
else { | ||
if (!roi) { | ||
return { data: await new image_reader_class_1.default().readToMat(image), rect: null }; | ||
} | ||
else { | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(await (0, nut_js_1.imageResource)(image), roi), rect: null }; | ||
} | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(await (0, nut_js_1.imageResource)(image)) }; | ||
} | ||
@@ -29,20 +20,20 @@ } | ||
if (typeof image !== 'string' && image) { | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(image, roi), rect: null, pixelDensity: image.pixelDensity }; | ||
let validRoi = roi ? (0, image_processor_class_1.determineMatRectROI)(image, this.getIncreasedRectByPixelDensity(roi, image.pixelDensity)) : undefined; | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(image, validRoi), rect: validRoi ? (0, image_processor_class_1.determineRegionRectROI)(validRoi) : undefined, pixelDensity: image.pixelDensity }; | ||
} | ||
else { | ||
if (!image) { | ||
const screenPic = await nut_js_1.screen.grab(); | ||
const mat = await (0, image_processor_class_1.fromImageWithAlphaChannel)(screenPic, roi); | ||
return { data: mat, rect: null, pixelDensity: screenPic.pixelDensity }; | ||
const imageObj = await nut_js_1.screen.grab(); | ||
let validRoi = roi ? (0, image_processor_class_1.determineMatRectROI)(imageObj, this.getIncreasedRectByPixelDensity(roi, imageObj.pixelDensity)) : undefined; | ||
const mat = await (0, image_processor_class_1.fromImageWithAlphaChannel)(imageObj, validRoi); | ||
return { data: mat, rect: validRoi ? (0, image_processor_class_1.determineRegionRectROI)(validRoi) : undefined, pixelDensity: imageObj.pixelDensity }; | ||
} | ||
else { | ||
const screenPic = await nut_js_1.screen.grab(); | ||
let mat = await (0, image_processor_class_1.fromImageWithAlphaChannel)(screenPic, roi); | ||
if (!roi) { | ||
return { data: mat, rect: null, pixelDensity: screenPic.pixelDensity }; | ||
} | ||
else { | ||
const imageObj = await (0, nut_js_1.imageResource)(image); | ||
return { data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(imageObj, roi), rect: null, pixelDensity: imageObj.pixelDensity }; | ||
} | ||
const imageObj = await (0, nut_js_1.imageResource)(image); | ||
let validRoi = roi ? (0, image_processor_class_1.determineMatRectROI)(imageObj, this.getIncreasedRectByPixelDensity(roi, imageObj.pixelDensity)) : undefined; | ||
return { | ||
data: await (0, image_processor_class_1.fromImageWithAlphaChannel)(imageObj, validRoi), | ||
rect: validRoi ? (0, image_processor_class_1.determineRegionRectROI)(validRoi) : undefined, | ||
pixelDensity: imageObj.pixelDensity, | ||
}; | ||
} | ||
@@ -59,3 +50,3 @@ } | ||
async initData(matchRequest) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s; | ||
var _a, _b, _c, _d, _e, _f, _g, _h; | ||
const customMatchRequest = matchRequest; | ||
@@ -74,21 +65,27 @@ const confidence = customMatchRequest.customOptions && ((_a = customMatchRequest.customOptions) === null || _a === void 0 ? void 0 : _a.methodType) === match_image_function_1.MethodEnum.TM_SQDIFF && matchRequest.confidence === 0.99 | ||
const debug = ((_f = customMatchRequest.customOptions) === null || _f === void 0 ? void 0 : _f.debug) || false; | ||
const needle = await this.loadNeedle(matchRequest.needle, (_g = customMatchRequest.customOptions) === null || _g === void 0 ? void 0 : _g.roi); | ||
const needle = await this.loadNeedle(matchRequest.needle); | ||
if (!needle || needle.data.empty) { | ||
throw new Error(`Failed to load ${typeof matchRequest.needle === 'string' ? matchRequest.needle : matchRequest.needle.id}, got empty image.`); | ||
} | ||
const haystack = await this.loadHaystack(matchRequest.haystack, (_h = customMatchRequest.customOptions) === null || _h === void 0 ? void 0 : _h.roi); | ||
const haystack = await this.loadHaystack(matchRequest.haystack, (_g = customMatchRequest.customOptions) === null || _g === void 0 ? void 0 : _g.roi); | ||
if (!haystack || haystack.data.empty) { | ||
throw new Error(`Failed to load ${matchRequest && matchRequest.haystack && typeof matchRequest.haystack === 'string' && !matchRequest.haystack ? matchRequest.haystack : matchRequest.haystack.id}, got empty image.`); | ||
} | ||
if ((_j = customMatchRequest.customOptions) === null || _j === void 0 ? void 0 : _j.roi) { | ||
(0, image_processor_class_1.validateSearchRegion)(new nut_js_1.Region(Number((_k = needle.rect) === null || _k === void 0 ? void 0 : _k.x), Number((_l = needle.rect) === null || _l === void 0 ? void 0 : _l.y), Number((_m = needle.rect) === null || _m === void 0 ? void 0 : _m.width), Number((_o = needle.rect) === null || _o === void 0 ? void 0 : _o.height)), new nut_js_1.Region(Number((_p = haystack.rect) === null || _p === void 0 ? void 0 : _p.x), Number((_q = haystack.rect) === null || _q === void 0 ? void 0 : _q.y), Number((_r = haystack.rect) === null || _r === void 0 ? void 0 : _r.width), Number((_s = haystack.rect) === null || _s === void 0 ? void 0 : _s.height))); | ||
} | ||
if (matchRequest.searchMultipleScales) { | ||
this.throwOnTooLargeNeedle(haystack.data, needle.data, scaleSteps[scaleSteps.length - 1]); | ||
} | ||
return { haystack: haystack, needle: needle, confidence: confidence, scaleSteps: scaleSteps, methodType: methodType, debug: debug, searchMultipleScales: searchMultipleScales }; | ||
return { | ||
haystack: haystack, | ||
needle: needle, | ||
confidence: confidence, | ||
scaleSteps: scaleSteps, | ||
methodType: methodType, | ||
debug: debug, | ||
searchMultipleScales: searchMultipleScales, | ||
roi: (_h = customMatchRequest.customOptions) === null || _h === void 0 ? void 0 : _h.roi, | ||
}; | ||
} | ||
async findMatches(matchRequest) { | ||
let matchResults = []; | ||
let { haystack, needle, confidence, scaleSteps, methodType, debug, searchMultipleScales } = await this.initData(matchRequest); | ||
let { haystack, needle, confidence, scaleSteps, methodType, debug, searchMultipleScales, roi } = await this.initData(matchRequest); | ||
if (!searchMultipleScales) { | ||
@@ -102,18 +99,33 @@ const overwrittenResults = await match_image_function_1.MatchTemplate.matchImagesByWriteOverFounded(haystack.data, needle.data, confidence, methodType, debug); | ||
} | ||
return await this.getValidatedMatches(matchResults, haystack.pixelDensity, confidence); | ||
return await this.getValidatedMatches(matchResults, haystack.pixelDensity, confidence, roi); | ||
} | ||
async getValidatedMatches(matchResults, pixelDensity, confidence) { | ||
const matches = await Promise.all(matchResults).then((results) => { | ||
results.forEach((matchResult) => { | ||
matchResult.location.left /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
matchResult.location.width /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
matchResult.location.top /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
matchResult.location.height /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
getIncreasedRectByPixelDensity(rect, pixelDensity) { | ||
rect.left *= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
rect.width *= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
rect.top *= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
rect.height *= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1; | ||
return rect; | ||
} | ||
getDecreasedRectByPixelDensity(matchResults, pixelDensity) { | ||
return matchResults.map((results) => { | ||
return { | ||
confidence: results.confidence, | ||
error: results.error, | ||
location: new nut_js_1.Region((results.location.left /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1), (results.location.top /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1), (results.location.width /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1), (results.location.height /= pixelDensity.scaleX && pixelDensity.scaleY && pixelDensity.scaleX === pixelDensity.scaleY ? pixelDensity.scaleX : 1)), | ||
}; | ||
}); | ||
} | ||
async getValidatedMatches(matchResults, pixelDensity, confidence, roi) { | ||
matchResults = this.getDecreasedRectByPixelDensity(matchResults, pixelDensity); | ||
if (roi) { | ||
matchResults = matchResults.map((m) => { | ||
return { confidence: m.confidence, error: m.error, location: new nut_js_1.Region(m.location.left + roi.left, m.location.top + roi.top, m.location.width, m.location.height) }; | ||
}); | ||
return results.sort((first, second) => second.confidence - first.confidence); | ||
}); | ||
const potentialMatches = matches.filter((match) => match.confidence >= confidence); | ||
(0, image_processor_class_1.validateSearchRegion)(new nut_js_1.Region(Number(roi.left), Number(roi.top), Number(roi.width), Number(roi.height)), new nut_js_1.Region(0, 0, await nut_js_1.screen.width(), await nut_js_1.screen.height())); | ||
} | ||
matchResults.sort((first, second) => second.confidence - first.confidence); | ||
const potentialMatches = matchResults.filter((match) => match.confidence >= confidence); | ||
if (potentialMatches.length === 0) { | ||
matches.sort((a, b) => a.confidence - b.confidence); | ||
const bestMatch = matches.pop(); | ||
matchResults.sort((a, b) => a.confidence - b.confidence); | ||
const bestMatch = matchResults.pop(); | ||
if (bestMatch) { | ||
@@ -129,6 +141,6 @@ throw new Error(`No match with required confidence ${confidence}. Best match: ${bestMatch.confidence}`); | ||
async findMatch(matchRequest) { | ||
let { haystack, needle, confidence, scaleSteps, methodType, debug, searchMultipleScales } = await this.initData(matchRequest); | ||
let { haystack, needle, confidence, scaleSteps, methodType, debug, searchMultipleScales, roi } = await this.initData(matchRequest); | ||
if (!searchMultipleScales) { | ||
const matches = await match_image_function_1.MatchTemplate.matchImages(haystack.data, needle.data, methodType, debug); | ||
const result = await this.getValidatedMatches([matches.data], haystack.pixelDensity, confidence); | ||
const result = await this.getValidatedMatches([matches.data], haystack.pixelDensity, confidence, roi); | ||
return result[0]; | ||
@@ -138,3 +150,3 @@ } | ||
const scaledResults = await this.searchMultipleScales(haystack.data, needle.data, confidence, scaleSteps, methodType, debug, true); | ||
return (await this.getValidatedMatches([scaledResults[0]], haystack.pixelDensity, confidence))[0]; | ||
return (await this.getValidatedMatches([scaledResults[0]], haystack.pixelDensity, confidence, roi))[0]; | ||
} | ||
@@ -141,0 +153,0 @@ } |
{ | ||
"name": "@udarrr/template-matcher", | ||
"version": "1.1.7", | ||
"version": "1.1.8", | ||
"main": "dist/index", | ||
@@ -60,2 +60,3 @@ "typings": "dist/index", | ||
"dependencies": { | ||
"@nut-tree/nut-js": "^2.3.0", | ||
"opencv4nodejs-prebuilt": "5.3.4" | ||
@@ -62,0 +63,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
110134
68
1036
3
+ Added@nut-tree/nut-js@^2.3.0