@aspiresys/visor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +45 -0
- package/dist/app.js +102 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +8 -0
- package/dist/index.d.ts +875 -0
- package/dist/index.js +1098 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +9 -0
- package/dist/matcher.d.ts +4 -0
- package/dist/matcher.js +69 -0
- package/dist/mouse.d.ts +3 -0
- package/dist/mouse.js +24 -0
- package/dist/ocr.d.ts +23 -0
- package/dist/ocr.js +83 -0
- package/dist/path.d.ts +1 -0
- package/dist/path.js +15 -0
- package/dist/screen.d.ts +2 -0
- package/dist/screen.js +28 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +39 -0
- package/dist/src/matcher.d.ts +3 -0
- package/dist/src/matcher.js +33 -0
- package/dist/src/mouse.d.ts +2 -0
- package/dist/src/mouse.js +18 -0
- package/dist/src/screen.d.ts +1 -0
- package/dist/src/screen.js +20 -0
- package/dist/src/types.d.ts +7 -0
- package/dist/src/types.js +2 -0
- package/dist/text.d.ts +13 -0
- package/dist/text.js +51 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +2 -0
- package/package.json +41 -0
- package/readme.md +566 -0
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function log(...args: any[]): void;
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Region } from "./types";
|
|
2
|
+
export declare function loadTemplate(path: string): any;
|
|
3
|
+
export declare function matchTemplate(screen: any, template: any, confidence?: number): Region | null;
|
|
4
|
+
export declare function findAllMatches(screen: any, template: any, confidence?: number): Region[];
|
package/dist/matcher.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadTemplate = loadTemplate;
|
|
7
|
+
exports.matchTemplate = matchTemplate;
|
|
8
|
+
exports.findAllMatches = findAllMatches;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const pngjs_1 = require("pngjs");
|
|
11
|
+
const cv = require("@techstark/opencv-js");
|
|
12
|
+
function loadTemplate(path) {
|
|
13
|
+
const buffer = fs_1.default.readFileSync(path);
|
|
14
|
+
const png = pngjs_1.PNG.sync.read(buffer);
|
|
15
|
+
return cv.matFromImageData({
|
|
16
|
+
data: png.data,
|
|
17
|
+
width: png.width,
|
|
18
|
+
height: png.height
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function matchTemplate(screen, template, confidence = 0.8) {
|
|
22
|
+
const result = new cv.Mat();
|
|
23
|
+
cv.matchTemplate(screen, template, result, cv.TM_CCOEFF_NORMED);
|
|
24
|
+
const { maxLoc, maxVal } = cv.minMaxLoc(result);
|
|
25
|
+
result.delete();
|
|
26
|
+
if (maxVal < confidence) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
x: maxLoc.x,
|
|
31
|
+
y: maxLoc.y,
|
|
32
|
+
width: template.cols,
|
|
33
|
+
height: template.rows,
|
|
34
|
+
confidence: maxVal
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function findAllMatches(screen, template, confidence = 0.8) {
|
|
38
|
+
const result = new cv.Mat();
|
|
39
|
+
cv.matchTemplate(screen, template, result, cv.TM_CCOEFF_NORMED);
|
|
40
|
+
const matches = [];
|
|
41
|
+
for (let y = 0; y < result.rows; y++) {
|
|
42
|
+
for (let x = 0; x < result.cols; x++) {
|
|
43
|
+
const score = result.floatAt(y, x);
|
|
44
|
+
if (score >= confidence) {
|
|
45
|
+
matches.push({
|
|
46
|
+
x,
|
|
47
|
+
y,
|
|
48
|
+
width: template.cols,
|
|
49
|
+
height: template.rows,
|
|
50
|
+
confidence: score
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
matches.sort((a, b) => b.confidence - a.confidence);
|
|
56
|
+
const filtered = [];
|
|
57
|
+
for (const match of matches) {
|
|
58
|
+
const tooClose = filtered.some(existing => {
|
|
59
|
+
const dx = Math.abs(existing.x - match.x);
|
|
60
|
+
const dy = Math.abs(existing.y - match.y);
|
|
61
|
+
return dx < 10 && dy < 10;
|
|
62
|
+
});
|
|
63
|
+
if (!tooClose) {
|
|
64
|
+
filtered.push(match);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
result.delete();
|
|
68
|
+
return filtered;
|
|
69
|
+
}
|
package/dist/mouse.d.ts
ADDED
package/dist/mouse.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.moveToRegion = moveToRegion;
|
|
4
|
+
exports.clickRegion = clickRegion;
|
|
5
|
+
const nut_js_1 = require("@nut-tree-fork/nut-js");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const logger_1 = require("./logger");
|
|
8
|
+
async function moveToRegion(region) {
|
|
9
|
+
const scaleFactor = config_1.visorConfig.scaleFactor;
|
|
10
|
+
const centerX = Math.floor((region.x + region.width / 2)
|
|
11
|
+
/ scaleFactor);
|
|
12
|
+
const centerY = Math.floor((region.y + region.height / 2)
|
|
13
|
+
/ scaleFactor);
|
|
14
|
+
(0, logger_1.log)("[MOUSE] Moving mouse to:", centerX, centerY);
|
|
15
|
+
await nut_js_1.mouse.move([
|
|
16
|
+
new nut_js_1.Point(centerX, centerY)
|
|
17
|
+
]);
|
|
18
|
+
}
|
|
19
|
+
async function clickRegion(region) {
|
|
20
|
+
await moveToRegion(region);
|
|
21
|
+
await new Promise(r => setTimeout(r, 200));
|
|
22
|
+
await nut_js_1.mouse.click(nut_js_1.Button.LEFT);
|
|
23
|
+
(0, logger_1.log)("[MOUSE] Left click completed");
|
|
24
|
+
}
|
package/dist/ocr.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminates OCR worker manually.
|
|
3
|
+
*
|
|
4
|
+
* Useful for cleanup after
|
|
5
|
+
* large automation sessions.
|
|
6
|
+
*/
|
|
7
|
+
export declare function terminateOCR(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Extracts OCR text from either:
|
|
10
|
+
* - entire screen
|
|
11
|
+
* - specific screen region
|
|
12
|
+
*
|
|
13
|
+
* Uses:
|
|
14
|
+
* - screenshot-desktop
|
|
15
|
+
* - sharp preprocessing
|
|
16
|
+
* - Tesseract OCR
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractTextFromRegion(region?: {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
}): Promise<any>;
|
package/dist/ocr.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.terminateOCR = terminateOCR;
|
|
7
|
+
exports.extractTextFromRegion = extractTextFromRegion;
|
|
8
|
+
const screenshot_desktop_1 = __importDefault(require("screenshot-desktop"));
|
|
9
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
10
|
+
const tesseract_js_1 = require("tesseract.js");
|
|
11
|
+
const config_1 = require("./config");
|
|
12
|
+
const logger_1 = require("./logger");
|
|
13
|
+
let worker = null;
|
|
14
|
+
/**
|
|
15
|
+
* Returns shared OCR worker.
|
|
16
|
+
*
|
|
17
|
+
* Worker is initialized only once
|
|
18
|
+
* and reused across all OCR calls.
|
|
19
|
+
*/
|
|
20
|
+
async function getWorker() {
|
|
21
|
+
if (!worker) {
|
|
22
|
+
(0, logger_1.log)("[OCR] Initializing worker...");
|
|
23
|
+
worker = await (0, tesseract_js_1.createWorker)("eng");
|
|
24
|
+
(0, logger_1.log)("[OCR] Worker initialized");
|
|
25
|
+
}
|
|
26
|
+
return worker;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Terminates OCR worker manually.
|
|
30
|
+
*
|
|
31
|
+
* Useful for cleanup after
|
|
32
|
+
* large automation sessions.
|
|
33
|
+
*/
|
|
34
|
+
async function terminateOCR() {
|
|
35
|
+
if (worker) {
|
|
36
|
+
(0, logger_1.log)("[OCR] Terminating worker");
|
|
37
|
+
await worker.terminate();
|
|
38
|
+
worker = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Extracts OCR text from either:
|
|
43
|
+
* - entire screen
|
|
44
|
+
* - specific screen region
|
|
45
|
+
*
|
|
46
|
+
* Uses:
|
|
47
|
+
* - screenshot-desktop
|
|
48
|
+
* - sharp preprocessing
|
|
49
|
+
* - Tesseract OCR
|
|
50
|
+
*/
|
|
51
|
+
async function extractTextFromRegion(region) {
|
|
52
|
+
const buffer = await (0, screenshot_desktop_1.default)({
|
|
53
|
+
format: "png"
|
|
54
|
+
});
|
|
55
|
+
let image = (0, sharp_1.default)(buffer);
|
|
56
|
+
if (region) {
|
|
57
|
+
image = image.extract({
|
|
58
|
+
left: Math.floor(region.x *
|
|
59
|
+
config_1.visorConfig.scaleFactor),
|
|
60
|
+
top: Math.floor(region.y *
|
|
61
|
+
config_1.visorConfig.scaleFactor),
|
|
62
|
+
width: Math.floor(region.width *
|
|
63
|
+
config_1.visorConfig.scaleFactor),
|
|
64
|
+
height: Math.floor(region.height *
|
|
65
|
+
config_1.visorConfig.scaleFactor)
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const processed = await image
|
|
69
|
+
.grayscale()
|
|
70
|
+
.normalize()
|
|
71
|
+
.sharpen()
|
|
72
|
+
.png()
|
|
73
|
+
.toBuffer();
|
|
74
|
+
const worker = await getWorker();
|
|
75
|
+
const result = await worker.recognize(processed, {}, {
|
|
76
|
+
blocks: true,
|
|
77
|
+
hocr: true,
|
|
78
|
+
tsv: true
|
|
79
|
+
});
|
|
80
|
+
(0, logger_1.log)("[OCR] Extracted Text:");
|
|
81
|
+
(0, logger_1.log)(result.data.text);
|
|
82
|
+
return result.data;
|
|
83
|
+
}
|
package/dist/path.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveImagePath(image: string): string;
|
package/dist/path.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveImagePath = resolveImagePath;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const config_1 = require("./config");
|
|
9
|
+
function resolveImagePath(image) {
|
|
10
|
+
if (image.includes("/") ||
|
|
11
|
+
image.includes("\\")) {
|
|
12
|
+
return image;
|
|
13
|
+
}
|
|
14
|
+
return path_1.default.join(config_1.visorConfig.imagePath, image);
|
|
15
|
+
}
|
package/dist/screen.d.ts
ADDED
package/dist/screen.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.captureScreen = captureScreen;
|
|
7
|
+
exports.saveScreenshot = saveScreenshot;
|
|
8
|
+
const screenshot_desktop_1 = __importDefault(require("screenshot-desktop"));
|
|
9
|
+
const pngjs_1 = require("pngjs");
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const cv = require("@techstark/opencv-js");
|
|
12
|
+
async function captureScreen() {
|
|
13
|
+
const buffer = await (0, screenshot_desktop_1.default)({
|
|
14
|
+
format: "png"
|
|
15
|
+
});
|
|
16
|
+
const png = pngjs_1.PNG.sync.read(buffer);
|
|
17
|
+
return cv.matFromImageData({
|
|
18
|
+
data: png.data,
|
|
19
|
+
width: png.width,
|
|
20
|
+
height: png.height
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async function saveScreenshot(path) {
|
|
24
|
+
const img = await (0, screenshot_desktop_1.default)({
|
|
25
|
+
format: "png"
|
|
26
|
+
});
|
|
27
|
+
fs_1.default.writeFileSync(path, img);
|
|
28
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.visor = exports.Visor = void 0;
|
|
4
|
+
const screen_1 = require("./screen");
|
|
5
|
+
const matcher_1 = require("./matcher");
|
|
6
|
+
const mouse_1 = require("./mouse");
|
|
7
|
+
class Visor {
|
|
8
|
+
async click(image, confidence = 0.8) {
|
|
9
|
+
console.log("Capturing screen...");
|
|
10
|
+
const screen = await (0, screen_1.captureScreen)();
|
|
11
|
+
console.log("Loading template...");
|
|
12
|
+
const template = (0, matcher_1.loadTemplate)(`src/images/${image}`);
|
|
13
|
+
console.log("Matching image...");
|
|
14
|
+
const region = (0, matcher_1.matchTemplate)(screen, template, confidence);
|
|
15
|
+
if (!region) {
|
|
16
|
+
console.log("Image not found");
|
|
17
|
+
throw new Error("Image not found");
|
|
18
|
+
}
|
|
19
|
+
console.log("Match found:", region);
|
|
20
|
+
await (0, mouse_1.clickRegion)(region);
|
|
21
|
+
console.log("Click completed");
|
|
22
|
+
}
|
|
23
|
+
async exists(image, confidence = 0.8) {
|
|
24
|
+
const screen = await (0, screen_1.captureScreen)();
|
|
25
|
+
const template = (0, matcher_1.loadTemplate)(`src/images/${image}`);
|
|
26
|
+
return (0, matcher_1.matchTemplate)(screen, template, confidence) !== null;
|
|
27
|
+
}
|
|
28
|
+
async wait(image, timeout = 5000) {
|
|
29
|
+
const start = Date.now();
|
|
30
|
+
while (Date.now() - start < timeout) {
|
|
31
|
+
if (await this.exists(image))
|
|
32
|
+
return true;
|
|
33
|
+
await new Promise(r => setTimeout(r, 300));
|
|
34
|
+
}
|
|
35
|
+
throw new Error("Timeout waiting for image");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.Visor = Visor;
|
|
39
|
+
exports.visor = new Visor();
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadTemplate = loadTemplate;
|
|
7
|
+
exports.matchTemplate = matchTemplate;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const pngjs_1 = require("pngjs");
|
|
10
|
+
const cv = require("opencv.js");
|
|
11
|
+
function loadTemplate(path) {
|
|
12
|
+
const buffer = fs_1.default.readFileSync(path);
|
|
13
|
+
const png = pngjs_1.PNG.sync.read(buffer);
|
|
14
|
+
return cv.matFromImageData({
|
|
15
|
+
data: png.data,
|
|
16
|
+
width: png.width,
|
|
17
|
+
height: png.height
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function matchTemplate(screen, template, confidence = 0.8) {
|
|
21
|
+
const result = new cv.Mat();
|
|
22
|
+
cv.matchTemplate(screen, template, result, cv.TM_CCOEFF_NORMED);
|
|
23
|
+
const { maxLoc, maxVal } = cv.minMaxLoc(result);
|
|
24
|
+
if (maxVal < confidence)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
x: maxLoc.x,
|
|
28
|
+
y: maxLoc.y,
|
|
29
|
+
width: template.cols,
|
|
30
|
+
height: template.rows,
|
|
31
|
+
confidence: maxVal
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clickRegion = clickRegion;
|
|
4
|
+
const nut_js_1 = require("@nut-tree-fork/nut-js");
|
|
5
|
+
async function clickRegion(region) {
|
|
6
|
+
const scaleFactor = 1.5;
|
|
7
|
+
const centerX = Math.floor((region.x + region.width / 2) / scaleFactor);
|
|
8
|
+
const centerY = Math.floor((region.y + region.height / 2) / scaleFactor);
|
|
9
|
+
console.log("Moving mouse to:", centerX, centerY);
|
|
10
|
+
await nut_js_1.mouse.move([
|
|
11
|
+
new nut_js_1.Point(centerX, centerY)
|
|
12
|
+
]);
|
|
13
|
+
console.log("Mouse moved");
|
|
14
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
15
|
+
console.log("Clicking now");
|
|
16
|
+
await nut_js_1.mouse.click(nut_js_1.Button.LEFT);
|
|
17
|
+
console.log("Click done");
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function captureScreen(): Promise<any>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.captureScreen = captureScreen;
|
|
7
|
+
const screenshot_desktop_1 = __importDefault(require("screenshot-desktop"));
|
|
8
|
+
const pngjs_1 = require("pngjs");
|
|
9
|
+
const cv = require("opencv.js");
|
|
10
|
+
async function captureScreen() {
|
|
11
|
+
const buffer = await (0, screenshot_desktop_1.default)({
|
|
12
|
+
format: "png"
|
|
13
|
+
});
|
|
14
|
+
const png = pngjs_1.PNG.sync.read(buffer);
|
|
15
|
+
return cv.matFromImageData({
|
|
16
|
+
data: png.data,
|
|
17
|
+
width: png.width,
|
|
18
|
+
height: png.height
|
|
19
|
+
});
|
|
20
|
+
}
|
package/dist/text.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Region } from "./types";
|
|
2
|
+
export declare function findText(text: string, region?: {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}): Promise<Region | null>;
|
|
8
|
+
export declare function existsText(text: string, region?: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}): Promise<boolean>;
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findText = findText;
|
|
4
|
+
exports.existsText = existsText;
|
|
5
|
+
const ocr_1 = require("./ocr");
|
|
6
|
+
async function findText(text, region) {
|
|
7
|
+
const result = await (0, ocr_1.extractTextFromRegion)(region);
|
|
8
|
+
const tsv = result.tsv;
|
|
9
|
+
if (!tsv) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const lines = tsv.split("\n");
|
|
13
|
+
const words = [];
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
const cols = line.split("\t");
|
|
16
|
+
if (cols[0] !== "5")
|
|
17
|
+
continue;
|
|
18
|
+
const wordText = cols[11];
|
|
19
|
+
if (!wordText)
|
|
20
|
+
continue;
|
|
21
|
+
const confidence = Number(cols[10]);
|
|
22
|
+
if (confidence < 40)
|
|
23
|
+
continue;
|
|
24
|
+
words.push({
|
|
25
|
+
text: wordText,
|
|
26
|
+
x: Number(cols[6]),
|
|
27
|
+
y: Number(cols[7]),
|
|
28
|
+
width: Number(cols[8]),
|
|
29
|
+
height: Number(cols[9]),
|
|
30
|
+
confidence
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//console.log(words);
|
|
34
|
+
const match = words.find(w => w.text
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.includes(text.toLowerCase()));
|
|
37
|
+
if (!match) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
x: match.x,
|
|
42
|
+
y: match.y,
|
|
43
|
+
width: match.width,
|
|
44
|
+
height: match.height,
|
|
45
|
+
confidence: match.confidence
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function existsText(text, region) {
|
|
49
|
+
const match = await findText(text, region);
|
|
50
|
+
return match !== null;
|
|
51
|
+
}
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aspiresys/visor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"start": "ts-node src/test.ts"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@nut-tree-fork/nut-js": "^4.1.0",
|
|
12
|
+
"@techstark/opencv-js": "^4.12.0-release.1",
|
|
13
|
+
"pngjs": "^7.0.0",
|
|
14
|
+
"screenshot-desktop": "^1.15.1",
|
|
15
|
+
"sharp": "^0.34.5",
|
|
16
|
+
"tesseract.js": "^7.0.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^24.0.0",
|
|
20
|
+
"@types/pngjs": "^6.0.5",
|
|
21
|
+
"ts-node": "^10.9.2",
|
|
22
|
+
"typescript": "^5.9.0"
|
|
23
|
+
},
|
|
24
|
+
"description": "Desktop visual automation framework using OpenCV, OCR, and desktop interaction APIs.",
|
|
25
|
+
|
|
26
|
+
"keywords": [
|
|
27
|
+
"automation",
|
|
28
|
+
"desktop-automation",
|
|
29
|
+
"opencv",
|
|
30
|
+
"ocr",
|
|
31
|
+
"playwright",
|
|
32
|
+
"testing",
|
|
33
|
+
"computer-vision"
|
|
34
|
+
],
|
|
35
|
+
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
|
|
38
|
+
"files": [
|
|
39
|
+
"dist"
|
|
40
|
+
]
|
|
41
|
+
}
|