ms-vite-plugin 1.4.40 → 1.4.41
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/docs/api/dotocr.md +4 -4
- package/docs/api/node.md +90 -3
- package/docs/api/opencv.md +46 -356
- package/docs/apicn/dotocr.md +2 -2
- package/docs/apicn/node.md +89 -3
- package/docs/apipython/dotocr.md +2 -2
- package/docs/apipython/node.md +86 -4
- package/package.json +1 -1
package/docs/api/dotocr.md
CHANGED
|
@@ -75,7 +75,7 @@ function recognizeAbs(
|
|
|
75
75
|
y?: number,
|
|
76
76
|
ex?: number,
|
|
77
77
|
ey?: number,
|
|
78
|
-
confidenceThreshold?: number
|
|
78
|
+
confidenceThreshold?: number
|
|
79
79
|
): OCRChar[];
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -85,7 +85,7 @@ function recognizeAbs(
|
|
|
85
85
|
| `input` | string | 是 | | 输入源,支持 `"screen"`、图片文件路径、URL 或 imageId |
|
|
86
86
|
| `x`, `y` | number | 否 | 0 | 裁剪区域左上角坐标 |
|
|
87
87
|
| `ex`, `ey` | number | 否 | 0 | 裁剪区域右下角坐标;`ex` 或 `ey` 为 0 时分别使用图像宽度或高度 |
|
|
88
|
-
| `confidenceThreshold` | number
|
|
88
|
+
| `confidenceThreshold` | number | 否 | 0.8 | 相似度下限;`<=0` 时按 `0.8`;低于阈值的字符会被过滤;`>0.95` 时要求像素完全一致 |
|
|
89
89
|
|
|
90
90
|
**返回值:**`OCRChar[]`。按行从上到下、同一行从左到右排列。颜色按字库各字自带的前景色/偏色匹配,无需额外传色。
|
|
91
91
|
|
|
@@ -108,7 +108,7 @@ function findTextAbs(
|
|
|
108
108
|
ex?: number,
|
|
109
109
|
ey?: number,
|
|
110
110
|
confidenceThreshold?: number,
|
|
111
|
-
exactMatch?: boolean
|
|
111
|
+
exactMatch?: boolean
|
|
112
112
|
): OCRChar[];
|
|
113
113
|
```
|
|
114
114
|
|
|
@@ -120,7 +120,7 @@ function findTextAbs(
|
|
|
120
120
|
| `x`, `y` | number | 否 | 0 | 裁剪区域左上角坐标 |
|
|
121
121
|
| `ex`, `ey` | number | 否 | 0 | 裁剪区域右下角坐标;`ex` 或 `ey` 为 0 时分别使用图像宽度或高度 |
|
|
122
122
|
| `confidenceThreshold` | number | 否 | 0.8 | 单字符识别相似度下限;语义同 `recognizeAbs` |
|
|
123
|
-
| `exactMatch` | boolean | 否 | false
|
|
123
|
+
| `exactMatch` | boolean | 否 | false | `false` 为行内子串包含匹配;`true` 要求某一整行文本完全等于目标字符串 |
|
|
124
124
|
|
|
125
125
|
**返回值:**命中结果数组。每个目标最多返回一次命中(最先匹配到的行);每项的 `text` 是目标字符串。
|
|
126
126
|
|
package/docs/api/node.md
CHANGED
|
@@ -84,6 +84,13 @@ interface NodeInfo {
|
|
|
84
84
|
clickCenter(): boolean; // 点击中心
|
|
85
85
|
clickRandom(): boolean; // 随机点击
|
|
86
86
|
hittable(): boolean; // 节点是否可接收事件,用于判断节点是否在屏幕可见
|
|
87
|
+
tap(): boolean; // 无障碍点击
|
|
88
|
+
doubleTap(): boolean; // 无障碍双击
|
|
89
|
+
press(duration: number): boolean; // 无障碍长按,duration 单位毫秒
|
|
90
|
+
scrollToVisible(): boolean; // 将节点滚动到可见区域
|
|
91
|
+
clearInput(): boolean; // 清空输入
|
|
92
|
+
input(text: string): boolean; // 追加输入(聚焦后输入)
|
|
93
|
+
setValue(text: string): boolean; // 设置节点的值(见下方支持控件)
|
|
87
94
|
parent(): NodeInfo | null; // 获取父节点
|
|
88
95
|
child(index: number): NodeInfo | null; // 获取子节点
|
|
89
96
|
allChildren(): NodeInfo[]; // 获取所有子节点
|
|
@@ -263,16 +270,81 @@ selector.releaseNode();
|
|
|
263
270
|
#### 点击操作
|
|
264
271
|
|
|
265
272
|
```typescript
|
|
266
|
-
//
|
|
273
|
+
// 点击节点中心(坐标点击)
|
|
267
274
|
node.clickCenter(): boolean;
|
|
268
275
|
|
|
269
|
-
//
|
|
276
|
+
// 随机点击节点区域(坐标点击)
|
|
270
277
|
node.clickRandom(): boolean;
|
|
271
278
|
|
|
272
279
|
// 节点是否可接收事件(用于判断是否显示在屏幕上)
|
|
273
280
|
node.hittable(): boolean;
|
|
281
|
+
|
|
282
|
+
// 无障碍点击
|
|
283
|
+
node.tap(): boolean;
|
|
284
|
+
|
|
285
|
+
// 无障碍双击
|
|
286
|
+
node.doubleTap(): boolean;
|
|
287
|
+
|
|
288
|
+
// 无障碍长按,duration 单位毫秒
|
|
289
|
+
node.press(duration: number): boolean;
|
|
290
|
+
|
|
291
|
+
// 将节点滚动到可见区域
|
|
292
|
+
node.scrollToVisible(): boolean;
|
|
293
|
+
|
|
294
|
+
// 清空输入
|
|
295
|
+
node.clearInput(): boolean;
|
|
296
|
+
|
|
297
|
+
// 追加输入
|
|
298
|
+
node.input(text: string): boolean;
|
|
299
|
+
|
|
300
|
+
// 设置节点的值
|
|
301
|
+
node.setValue(text: string): boolean;
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
#### tap / doubleTap / press - 无障碍手势
|
|
305
|
+
|
|
306
|
+
通过无障碍 API 直接操作节点,不依赖坐标点击。
|
|
307
|
+
|
|
308
|
+
| 方法 | 参数 | 说明 |
|
|
309
|
+
| --- | --- | --- |
|
|
310
|
+
| `tap()` | 无 | 无障碍单击 |
|
|
311
|
+
| `doubleTap()` | 无 | 无障碍双击 |
|
|
312
|
+
| `press(duration)` | `duration`:长按持续时间,单位毫秒 | 无障碍长按 |
|
|
313
|
+
|
|
314
|
+
**示例:**
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
const selector = createNodeSelector();
|
|
318
|
+
|
|
319
|
+
const btn = selector.label("确定").type("XCUIElementTypeButton").getOneNodeInfo(3000);
|
|
320
|
+
if (btn) {
|
|
321
|
+
// 无障碍单击
|
|
322
|
+
btn.tap();
|
|
323
|
+
|
|
324
|
+
// 无障碍双击
|
|
325
|
+
btn.doubleTap();
|
|
326
|
+
|
|
327
|
+
// 无障碍长按 800ms
|
|
328
|
+
btn.press(800);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
selector.releaseNode();
|
|
274
332
|
```
|
|
275
333
|
|
|
334
|
+
#### setValue - 设置节点的值
|
|
335
|
+
|
|
336
|
+
按控件类型自动处理,常用支持如下:
|
|
337
|
+
|
|
338
|
+
| 控件类型 | 传参示例 | 说明 |
|
|
339
|
+
| --- | --- | --- |
|
|
340
|
+
| `XCUIElementTypePickerWheel` | `"1小时"` | 滚轮选到对应选项文案 |
|
|
341
|
+
| `XCUIElementTypeTextField` | `"hello"` | 先聚焦再输入文本 |
|
|
342
|
+
| `XCUIElementTypeSecureTextField` | `"123456"` | 同上 |
|
|
343
|
+
| `XCUIElementTypeTextView` | `"多行内容"` | 同上 |
|
|
344
|
+
| `XCUIElementTypeSearchField` | `"关键词"` | 同上 |
|
|
345
|
+
|
|
346
|
+
文本类控件不会先清空已有内容;需要清空时先调用 `clearInput()`。
|
|
347
|
+
|
|
276
348
|
**示例:**
|
|
277
349
|
|
|
278
350
|
```typescript
|
|
@@ -288,12 +360,27 @@ if (confirmBtn) {
|
|
|
288
360
|
const isHittable = confirmBtn.hittable();
|
|
289
361
|
logi(`是否可接收事件: ${isHittable}`);
|
|
290
362
|
|
|
291
|
-
|
|
363
|
+
confirmBtn.scrollToVisible();
|
|
364
|
+
// 优先使用无障碍点击;也可用 clickCenter / clickRandom 做坐标点击
|
|
365
|
+
const clicked = confirmBtn.tap();
|
|
292
366
|
if (clicked) {
|
|
293
367
|
logi("成功点击确定按钮");
|
|
294
368
|
}
|
|
295
369
|
}
|
|
296
370
|
|
|
371
|
+
// 文本框:可先清空再设值,或直接追加输入
|
|
372
|
+
const field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000);
|
|
373
|
+
if (field) {
|
|
374
|
+
field.clearInput();
|
|
375
|
+
field.setValue("hello");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// 滚轮:传界面上的选项文案
|
|
379
|
+
const wheel = selector.type("XCUIElementTypePickerWheel").getOneNodeInfo(3000);
|
|
380
|
+
if (wheel) {
|
|
381
|
+
wheel.setValue("1小时");
|
|
382
|
+
}
|
|
383
|
+
|
|
297
384
|
// 随机点击避免检测
|
|
298
385
|
const randomClick = confirmBtn?.clickRandom();
|
|
299
386
|
|
package/docs/api/opencv.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
注意:
|
|
6
6
|
|
|
7
7
|
- Mat 用字符串句柄表示,形如 `$CV_MAT$_…`。
|
|
8
|
-
- 多数算子返回新句柄;`rectangle` / `circle` / `line` / `putText` / `fillPoly` / `polylines` / `drawContours` / `floodFill` / `ellipse` / `drawMarker` / `arrowedLine` / `fillConvexPoly`
|
|
8
|
+
- 多数算子返回新句柄;`rectangle` / `circle` / `line` / `putText` / `fillPoly` / `polylines` / `drawContours` / `floodFill` / `ellipse` / `drawMarker` / `arrowedLine` / `fillConvexPoly` 等会就地修改输入 Mat(或 options 中指定的目标句柄)。
|
|
9
9
|
- 与 `image` 可通过 `fromImageId` / `toImageId` 互通(独立拷贝)。
|
|
10
10
|
- 路径 / msbundle / imageId / `screen` 等读图只用 `imread`;其它 API 只接受 Mat 句柄;`imdecode` 只解 base64。
|
|
11
11
|
- 用完请 `release` / `releaseAll`(同时存活句柄上限约 32)。
|
|
@@ -17,17 +17,16 @@
|
|
|
17
17
|
| --- | --- |
|
|
18
18
|
| 读图 / 截屏 | `capture` · `imread` · `imdecode` · `imwrite` · `imencode` · `fromImageId` / `toImageId` |
|
|
19
19
|
| Mat | `Mat` / `zeros` / `ones` · `clone` · `empty` / `isRelease` · `release` / `releaseAll` · `getSize` / `at` / `set` · `copyTo` |
|
|
20
|
-
| 颜色 / 阈值 | `cvtColor` · `threshold` · `adaptiveThreshold` · `inRange` · `CLAHE` / `equalizeHist`
|
|
21
|
-
| 算术 / 位运算 | `add` / `subtract` / `multiply` / `divide` · bitwise_* · `absdiff` · `addWeighted` · `convertScaleAbs` · `normalize` / `norm` · `meanStdDev` · `findNonZero` · `countNonZero` · `minMaxLoc` / `mean` / `sum` · `split` / `merge` · `hconcat` / `vconcat` · `LUT` · `compare` · `min` / `max` · `extractChannel`
|
|
22
|
-
| 滤波边缘 | `GaussianBlur` / `blur` / `medianBlur` / `bilateralFilter` / `boxFilter`
|
|
23
|
-
| 几何 | `resize` / `crop` / `rotate` / `flip` · `copyMakeBorder` · `warpAffine` / `warpPerspective`
|
|
20
|
+
| 颜色 / 阈值 | `cvtColor` · `threshold` · `adaptiveThreshold` · `inRange` · `CLAHE` / `equalizeHist` |
|
|
21
|
+
| 算术 / 位运算 | `add` / `subtract` / `multiply` / `divide` · bitwise_* · `absdiff` · `addWeighted` · `convertScaleAbs` · `normalize` / `norm` · `meanStdDev` · `findNonZero` · `countNonZero` · `minMaxLoc` / `mean` / `sum` · `split` / `merge` · `hconcat` / `vconcat` · `LUT` · `compare` · `min` / `max` · `extractChannel` |
|
|
22
|
+
| 滤波边缘 | `GaussianBlur` / `blur` / `medianBlur` / `bilateralFilter` / `boxFilter` · `Canny` / `Sobel` / `Laplacian` / `Scharr` · `filter2D` · `pyrDown` / `pyrUp` · `fastNlMeansDenoising` / `fastNlMeansDenoisingColored` · `inpaint` |
|
|
23
|
+
| 几何 | `resize` / `crop` / `rotate` / `flip` · `copyMakeBorder` · `warpAffine` / `warpPerspective` · `getRotationMatrix2D` · `getAffineTransform` · `getPerspectiveTransform` · `invertAffineTransform` · `findHomography` · `perspectiveTransform` · `estimateAffine2D` / `estimateAffinePartial2D` · `getRectSubPix` · `phaseCorrelate` |
|
|
24
24
|
| 绘制 | `rectangle` / `circle` / `line` / `ellipse` / `arrowedLine` / `drawMarker` · `putText` / `fillPoly` / `fillConvexPoly` / `polylines` / `drawContours` · `getTextSize` |
|
|
25
|
-
| 匹配 | `matchTemplate` / `matchTemplateLoc` · `SIFT` / `ORB` / `
|
|
25
|
+
| 匹配 | `matchTemplate` / `matchTemplateLoc` · `SIFT` / `ORB` / `FAST` · `BFMatcher` / `knnMatch` · `FlannBasedMatcher` / `flannKnnMatch` · `drawKeypoints` / `drawMatches` |
|
|
26
26
|
| 轮廓 | `findContours` · `boundingRect` / `minAreaRect` / `boxPoints` · `contourArea` / `arcLength` / `approxPolyDP` / `convexHull` / `convexityDefects` / `isContourConvex` · `moments` / `HuMoments` / `matchShapes` · `pointPolygonTest` · `fitEllipse` / `fitLine` / `minEnclosingCircle` |
|
|
27
|
-
| 霍夫 / 连通域
|
|
27
|
+
| 霍夫 / 连通域 | `HoughLinesP` / `HoughCircles` · `connectedComponents` / `connectedComponentsWithStats` · `distanceTransform` · `floodFill` · `goodFeaturesToTrack` / `cornerHarris` / `cornerSubPix` |
|
|
28
28
|
| 直方图 | `calcHist` · `compareHist` · `calcBackProject` |
|
|
29
|
-
|
|
|
30
|
-
| 扫码 / 检测 | `detectQRCode` · `detectBarcode` · `encodeQRCode` · `CascadeClassifier` · `HOGDetect` |
|
|
29
|
+
| 扫码 | `encodeQRCode` · `detectQRCode` · `detectBarcode` |
|
|
31
30
|
|
|
32
31
|
---
|
|
33
32
|
|
|
@@ -906,37 +905,25 @@ const score = cv.compareHist(h1, h2, { method: cv.HISTCMP_CORREL });
|
|
|
906
905
|
cv.release(h1); cv.release(h2);
|
|
907
906
|
```
|
|
908
907
|
|
|
909
|
-
###
|
|
910
|
-
|
|
911
|
-
```typescript
|
|
912
|
-
function boxPoints(options: { center: Point; size: Size | [number, number]; angle?: number }): Point[] | null;
|
|
913
|
-
function pointPolygonTest(contour: Point[], ptOrOptions: Point | { pt: Point; measureDist?: boolean }): number;
|
|
914
|
-
function minEnclosingCircle(points: Point[]): { center: Point; radius: number } | null;
|
|
915
|
-
function fitEllipse(points: Point[]): RotatedRect | null;
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
**示例:**
|
|
919
|
-
|
|
920
|
-
```javascript
|
|
921
|
-
const rr = cv.minAreaRect(contour);
|
|
922
|
-
const corners = cv.boxPoints(rr);
|
|
923
|
-
const inside = cv.pointPolygonTest(contour, { pt: { x: 100, y: 100 } });
|
|
924
|
-
```
|
|
925
|
-
|
|
926
|
-
### detectQRCode / detectBarcode
|
|
908
|
+
### encodeQRCode / detectQRCode / detectBarcode
|
|
927
909
|
|
|
928
910
|
```typescript
|
|
911
|
+
function encodeQRCode(text: string): Mat | null;
|
|
929
912
|
function detectQRCode(mat: Mat): { decoded: string; points: Point[] } | null;
|
|
930
913
|
function detectBarcode(mat: Mat): { decoded: string[]; types: string[]; points: Point[] } | null;
|
|
931
914
|
```
|
|
932
915
|
|
|
916
|
+
`encodeQRCode` 返回可显示/可识别的 BGR Mat(已放大并加静区),可直接交给 `detectQRCode`。
|
|
917
|
+
|
|
933
918
|
**示例:**
|
|
934
919
|
|
|
935
920
|
```javascript
|
|
936
|
-
const
|
|
921
|
+
const qrMat = cv.encodeQRCode("https://example.com");
|
|
922
|
+
const qr = cv.detectQRCode(qrMat); // { decoded, points }
|
|
937
923
|
if (qr) logi(qr.decoded);
|
|
938
924
|
const codes = cv.detectBarcode(src);
|
|
939
925
|
if (codes) logi(codes.decoded.join(","));
|
|
926
|
+
cv.release(qrMat);
|
|
940
927
|
```
|
|
941
928
|
|
|
942
929
|
### filter2D / ellipse / getTextSize
|
|
@@ -1054,30 +1041,6 @@ cv.release(a.descriptors);
|
|
|
1054
1041
|
cv.release(b.descriptors);
|
|
1055
1042
|
```
|
|
1056
1043
|
|
|
1057
|
-
### AKAZE / BRISK / FAST
|
|
1058
|
-
|
|
1059
|
-
```typescript
|
|
1060
|
-
function AKAZE(mat: Mat, options?: { mask?: Mat }): FeatureResult | null;
|
|
1061
|
-
function BRISK(mat: Mat, options?: { thresh?: number; octaves?: number; mask?: Mat }): FeatureResult | null;
|
|
1062
|
-
function FAST(mat: Mat, options?: { threshold?: number; nonmaxSuppression?: boolean; mask?: Mat }): { keypoints: KeyPoint[] } | null;
|
|
1063
|
-
```
|
|
1064
|
-
|
|
1065
|
-
**说明:**
|
|
1066
|
-
|
|
1067
|
-
- `AKAZE` / `BRISK` 返回关键点 + 描述子。
|
|
1068
|
-
- `FAST` **只检测关键点**,无 `descriptors`。
|
|
1069
|
-
- `BRISK`:`thresh` 默认 30,`octaves` 默认 3。
|
|
1070
|
-
- `FAST`:`threshold` 默认 10,`nonmaxSuppression` 默认 `true`。
|
|
1071
|
-
|
|
1072
|
-
**示例:**
|
|
1073
|
-
|
|
1074
|
-
```javascript
|
|
1075
|
-
const fast = cv.FAST(gray, { threshold: 20 });
|
|
1076
|
-
logi(`FAST count=${fast.keypoints.length}`);
|
|
1077
|
-
const brisk = cv.BRISK(gray, { thresh: 30, octaves: 3 });
|
|
1078
|
-
cv.release(brisk.descriptors);
|
|
1079
|
-
```
|
|
1080
|
-
|
|
1081
1044
|
### BFMatcher
|
|
1082
1045
|
|
|
1083
1046
|
```typescript
|
|
@@ -1235,75 +1198,6 @@ const d1 = cv.fastNlMeansDenoising(gray, { h: 3 });
|
|
|
1235
1198
|
const d2 = cv.fastNlMeansDenoisingColored(src, { h: 3, hColor: 3 });
|
|
1236
1199
|
```
|
|
1237
1200
|
|
|
1238
|
-
### edgePreservingFilter / detailEnhance / stylization
|
|
1239
|
-
|
|
1240
|
-
```typescript
|
|
1241
|
-
function edgePreservingFilter(mat: Mat, options?: { flags?: number; sigma_s?: number; sigma_r?: number }): Mat | null;
|
|
1242
|
-
function detailEnhance(mat: Mat, options?: { sigma_s?: number; sigma_r?: number }): Mat | null;
|
|
1243
|
-
function stylization(mat: Mat, options?: { sigma_s?: number; sigma_r?: number }): Mat | null;
|
|
1244
|
-
```
|
|
1245
|
-
|
|
1246
|
-
```javascript
|
|
1247
|
-
const soft = cv.edgePreservingFilter(src, { flags: cv.RECURS_FILTER });
|
|
1248
|
-
const sharp = cv.detailEnhance(src);
|
|
1249
|
-
const art = cv.stylization(src);
|
|
1250
|
-
```
|
|
1251
|
-
|
|
1252
|
-
### pencilSketch / decolor
|
|
1253
|
-
|
|
1254
|
-
```typescript
|
|
1255
|
-
function pencilSketch(mat: Mat, options?: {
|
|
1256
|
-
sigma_s?: number; sigma_r?: number; shade_factor?: number;
|
|
1257
|
-
}): { gray: Mat; color: Mat } | null;
|
|
1258
|
-
function decolor(mat: Mat): { grayscale: Mat; colorBoost: Mat } | null;
|
|
1259
|
-
```
|
|
1260
|
-
|
|
1261
|
-
返回两个新句柄,用完需分别 `release`。
|
|
1262
|
-
|
|
1263
|
-
```javascript
|
|
1264
|
-
const sketch = cv.pencilSketch(src);
|
|
1265
|
-
const dc = cv.decolor(src);
|
|
1266
|
-
cv.release(sketch.gray); cv.release(sketch.color);
|
|
1267
|
-
cv.release(dc.grayscale); cv.release(dc.colorBoost);
|
|
1268
|
-
```
|
|
1269
|
-
|
|
1270
|
-
### seamlessClone
|
|
1271
|
-
|
|
1272
|
-
```typescript
|
|
1273
|
-
function seamlessClone(src: Mat, options: {
|
|
1274
|
-
dst: Mat; mask: Mat; p?: Point; x?: number; y?: number; flags?: number;
|
|
1275
|
-
}): Mat | null;
|
|
1276
|
-
```
|
|
1277
|
-
|
|
1278
|
-
| 参数名 | 类型 | 是否必填 | 默认值 | 描述 |
|
|
1279
|
-
| --- | --- | --- | --- | --- |
|
|
1280
|
-
| `dst` | Mat | 是 | - | 背景图 |
|
|
1281
|
-
| `mask` | Mat | 是 | - | 前景有效区域 |
|
|
1282
|
-
| `p` / `x,y` | Point | 是 | - | 贴入中心 |
|
|
1283
|
-
| `flags` | number | 否 | `NORMAL_CLONE` | `NORMAL_CLONE` / `MIXED_CLONE` / `MONOCHROME_TRANSFER` |
|
|
1284
|
-
|
|
1285
|
-
```javascript
|
|
1286
|
-
const blend = cv.seamlessClone(fg, { dst: bg, mask, p: { x: 200, y: 150 }, flags: cv.NORMAL_CLONE });
|
|
1287
|
-
```
|
|
1288
|
-
|
|
1289
|
-
### colorChange / illuminationChange / textureFlattening
|
|
1290
|
-
|
|
1291
|
-
```typescript
|
|
1292
|
-
function colorChange(mat: Mat, options: { mask: Mat; red_mul?: number; green_mul?: number; blue_mul?: number }): Mat | null;
|
|
1293
|
-
function illuminationChange(mat: Mat, options: { mask: Mat; alpha?: number; beta?: number }): Mat | null;
|
|
1294
|
-
function textureFlattening(mat: Mat, options: {
|
|
1295
|
-
mask: Mat; low_threshold?: number; high_threshold?: number; kernel_size?: number;
|
|
1296
|
-
}): Mat | null;
|
|
1297
|
-
```
|
|
1298
|
-
|
|
1299
|
-
```javascript
|
|
1300
|
-
const c = cv.colorChange(src, { mask, red_mul: 1.5, green_mul: 1.0, blue_mul: 0.8 });
|
|
1301
|
-
const i = cv.illuminationChange(src, { mask, alpha: 0.2, beta: 0.4 });
|
|
1302
|
-
const f = cv.textureFlattening(src, { mask });
|
|
1303
|
-
```
|
|
1304
|
-
|
|
1305
|
-
---
|
|
1306
|
-
|
|
1307
1201
|
## Core 扩展
|
|
1308
1202
|
|
|
1309
1203
|
### LUT / compare / min / max
|
|
@@ -1322,168 +1216,9 @@ const mask = cv.compare(a, { src2: b, cmpop: cv.CMP_GT });
|
|
|
1322
1216
|
const lo = cv.min(a, { src2: b });
|
|
1323
1217
|
```
|
|
1324
1218
|
|
|
1325
|
-
### extractChannel / insertChannel / mixChannels
|
|
1326
|
-
|
|
1327
|
-
```typescript
|
|
1328
|
-
function extractChannel(mat: Mat, options: { coi: number }): Mat | null;
|
|
1329
|
-
/** 就地写入 dst,返回 dst 句柄 */
|
|
1330
|
-
function insertChannel(srcChannel: Mat, options: { dst: Mat; coi: number }): Mat | null;
|
|
1331
|
-
/** 就地改写 dst,成功返回 true */
|
|
1332
|
-
function mixChannels(options: { src: Mat[]; dst: Mat[]; fromTo: number[] }): boolean;
|
|
1333
|
-
```
|
|
1334
|
-
|
|
1335
|
-
```javascript
|
|
1336
|
-
const b = cv.extractChannel(src, { coi: 0 });
|
|
1337
|
-
cv.insertChannel(b, { dst: out, coi: 0 }); // 就地改 out
|
|
1338
|
-
cv.mixChannels({ src: [src], dst: [out], fromTo: [0, 2, 1, 1, 2, 0] });
|
|
1339
|
-
```
|
|
1340
|
-
|
|
1341
|
-
### pow / sqrt / exp / log / magnitude / cartToPolar / polarToCart
|
|
1342
|
-
|
|
1343
|
-
```typescript
|
|
1344
|
-
function pow(mat: Mat, options: { power: number }): Mat | null;
|
|
1345
|
-
function sqrt(mat: Mat): Mat | null;
|
|
1346
|
-
function exp(mat: Mat): Mat | null;
|
|
1347
|
-
function log(mat: Mat): Mat | null;
|
|
1348
|
-
function magnitude(options: { x: Mat; y: Mat }): Mat | null;
|
|
1349
|
-
function cartToPolar(options: { x: Mat; y: Mat; angleInDegrees?: boolean }): { magnitude: Mat; angle: Mat } | null;
|
|
1350
|
-
function polarToCart(options: { magnitude: Mat; angle: Mat; angleInDegrees?: boolean }): { x: Mat; y: Mat } | null;
|
|
1351
|
-
```
|
|
1352
|
-
|
|
1353
|
-
```javascript
|
|
1354
|
-
const mag = cv.magnitude({ x: dx, y: dy });
|
|
1355
|
-
const polar = cv.cartToPolar({ x: dx, y: dy, angleInDegrees: true });
|
|
1356
|
-
cv.release(polar.magnitude); cv.release(polar.angle);
|
|
1357
|
-
```
|
|
1358
|
-
|
|
1359
|
-
### PSNR / scaleAdd / sum
|
|
1360
|
-
|
|
1361
|
-
```typescript
|
|
1362
|
-
function PSNR(src1: Mat, options: { src2: Mat; R?: number }): number;
|
|
1363
|
-
function scaleAdd(src1: Mat, options: { alpha: number; src2: Mat }): Mat | null;
|
|
1364
|
-
function sum(mat: Mat): number[] | null;
|
|
1365
|
-
```
|
|
1366
|
-
|
|
1367
|
-
```javascript
|
|
1368
|
-
const psnr = cv.PSNR(a, { src2: b });
|
|
1369
|
-
const s = cv.sum(src); // 各通道和
|
|
1370
|
-
```
|
|
1371
|
-
|
|
1372
|
-
---
|
|
1373
|
-
|
|
1374
1219
|
## Imgproc 几何 / 滤波扩展
|
|
1375
1220
|
|
|
1376
|
-
###
|
|
1377
|
-
|
|
1378
|
-
```typescript
|
|
1379
|
-
function stackBlur(mat: Mat, options: { ksize: number | [number, number] | Size }): Mat | null;
|
|
1380
|
-
function sepFilter2D(mat: Mat, options: { kernelX: Mat; kernelY: Mat; ddepth?: number; delta?: number }): Mat | null;
|
|
1381
|
-
function remap(mat: Mat, options: { map1: Mat; map2: Mat; interpolation?: number; borderMode?: number }): Mat | null;
|
|
1382
|
-
function warpPolar(mat: Mat, options: {
|
|
1383
|
-
width?: number; height?: number;
|
|
1384
|
-
center: Point; maxRadius: number; flags?: number;
|
|
1385
|
-
}): Mat | null;
|
|
1386
|
-
```
|
|
1387
|
-
|
|
1388
|
-
```javascript
|
|
1389
|
-
const blur = cv.stackBlur(src, { ksize: 7 });
|
|
1390
|
-
const polar = cv.warpPolar(src, {
|
|
1391
|
-
width: 300, height: 300, center: { x: 160, y: 160 }, maxRadius: 150,
|
|
1392
|
-
flags: cv.INTER_LINEAR | cv.WARP_POLAR_LINEAR,
|
|
1393
|
-
});
|
|
1394
|
-
```
|
|
1395
|
-
|
|
1396
|
-
### invertAffineTransform / getRectSubPix / phaseCorrelate
|
|
1397
|
-
|
|
1398
|
-
```typescript
|
|
1399
|
-
function invertAffineTransform(M: Mat): Mat | null;
|
|
1400
|
-
function getRectSubPix(mat: Mat, options: {
|
|
1401
|
-
patchSize: Size | [number, number]; center: Point;
|
|
1402
|
-
}): Mat | null;
|
|
1403
|
-
function phaseCorrelate(src1: Mat, options: { src2: Mat; window?: Mat }): {
|
|
1404
|
-
x: number; y: number; response?: number;
|
|
1405
|
-
} | null;
|
|
1406
|
-
```
|
|
1407
|
-
|
|
1408
|
-
```javascript
|
|
1409
|
-
const inv = cv.invertAffineTransform(M);
|
|
1410
|
-
const shift = cv.phaseCorrelate(a, { src2: b });
|
|
1411
|
-
```
|
|
1412
|
-
|
|
1413
|
-
### HoughLines / LSD
|
|
1414
|
-
|
|
1415
|
-
```typescript
|
|
1416
|
-
function HoughLines(mat: Mat, options?: {
|
|
1417
|
-
rho?: number; theta?: number; threshold?: number; srn?: number; stn?: number;
|
|
1418
|
-
}): Array<{ rho: number; theta: number }> | null;
|
|
1419
|
-
function LSD(mat: Mat, options?: object): Array<{ x1: number; y1: number; x2: number; y2: number }> | null;
|
|
1420
|
-
```
|
|
1421
|
-
|
|
1422
|
-
```javascript
|
|
1423
|
-
const lines = cv.HoughLines(edges, { threshold: 80 });
|
|
1424
|
-
const segs = cv.LSD(gray);
|
|
1425
|
-
```
|
|
1426
|
-
|
|
1427
|
-
### cornerHarris / cornerSubPix / cornerMinEigenVal / preCornerDetect / spatialGradient
|
|
1428
|
-
|
|
1429
|
-
```typescript
|
|
1430
|
-
function cornerHarris(mat: Mat, options?: { blockSize?: number; ksize?: number; k?: number }): Mat | null;
|
|
1431
|
-
function cornerSubPix(mat: Mat, options: {
|
|
1432
|
-
corners: Point[]; winSize?: Size | [number, number]; zeroZone?: Size | [number, number];
|
|
1433
|
-
criteria?: { type?: number; maxCount?: number; epsilon?: number };
|
|
1434
|
-
}): Point[] | null;
|
|
1435
|
-
function cornerMinEigenVal(mat: Mat, options?: { blockSize?: number; ksize?: number }): Mat | null;
|
|
1436
|
-
function preCornerDetect(mat: Mat, options?: { ksize?: number }): Mat | null;
|
|
1437
|
-
function spatialGradient(mat: Mat, options?: { ksize?: number }): { dx: Mat; dy: Mat } | null;
|
|
1438
|
-
```
|
|
1439
|
-
|
|
1440
|
-
```javascript
|
|
1441
|
-
const corners = cv.goodFeaturesToTrack(gray, { maxCorners: 50, qualityLevel: 0.01, minDistance: 10 });
|
|
1442
|
-
const refined = cv.cornerSubPix(gray, { corners, winSize: [5, 5] });
|
|
1443
|
-
const g = cv.spatialGradient(gray);
|
|
1444
|
-
cv.release(g.dx); cv.release(g.dy);
|
|
1445
|
-
```
|
|
1446
|
-
|
|
1447
|
-
### calcBackProject / applyColorMap / HuMoments / pyrMeanShiftFiltering / integral
|
|
1448
|
-
|
|
1449
|
-
```typescript
|
|
1450
|
-
function calcBackProject(mat: Mat, options: {
|
|
1451
|
-
hist: Mat; channels?: number[]; ranges?: number[]; scale?: number;
|
|
1452
|
-
}): Mat | null;
|
|
1453
|
-
function applyColorMap(mat: Mat, options: { colormap: number }): Mat | null;
|
|
1454
|
-
function HuMoments(contourOrMoments: Point[] | object | Mat): number[] | null;
|
|
1455
|
-
function pyrMeanShiftFiltering(mat: Mat, options?: { sp?: number; sr?: number; maxLevel?: number }): Mat | null;
|
|
1456
|
-
function integral(mat: Mat): Mat | null;
|
|
1457
|
-
```
|
|
1458
|
-
|
|
1459
|
-
```javascript
|
|
1460
|
-
const back = cv.calcBackProject(hsv, { hist, channels: [0], ranges: [0, 180] });
|
|
1461
|
-
const heat = cv.applyColorMap(gray, { colormap: cv.COLORMAP_JET });
|
|
1462
|
-
const hu = cv.HuMoments(contour); // length 7
|
|
1463
|
-
```
|
|
1464
|
-
|
|
1465
|
-
### drawMarker / arrowedLine / fillConvexPoly(就地)
|
|
1466
|
-
|
|
1467
|
-
```typescript
|
|
1468
|
-
function drawMarker(mat: Mat, options: {
|
|
1469
|
-
position: Point; color?: number[] | string;
|
|
1470
|
-
markerType?: number; markerSize?: number; thickness?: number;
|
|
1471
|
-
}): Mat | null;
|
|
1472
|
-
function arrowedLine(mat: Mat, options: {
|
|
1473
|
-
pt1: Point; pt2: Point; color?: number[] | string; thickness?: number; tipLength?: number;
|
|
1474
|
-
}): Mat | null;
|
|
1475
|
-
function fillConvexPoly(mat: Mat, options: { pts: Point[]; color?: number[] | string }): Mat | null;
|
|
1476
|
-
```
|
|
1477
|
-
|
|
1478
|
-
就地修改输入 Mat,返回同一句柄。
|
|
1479
|
-
|
|
1480
|
-
```javascript
|
|
1481
|
-
cv.drawMarker(src, { position: { x: 100, y: 80 }, markerType: cv.MARKER_CROSS });
|
|
1482
|
-
cv.arrowedLine(src, { pt1: { x: 10, y: 10 }, pt2: { x: 200, y: 120 }, color: [0, 0, 255] });
|
|
1483
|
-
cv.fillConvexPoly(src, { pts: [{ x: 10, y: 10 }, { x: 100, y: 20 }, { x: 50, y: 80 }], color: [0, 255, 0] });
|
|
1484
|
-
```
|
|
1485
|
-
|
|
1486
|
-
### connectedComponents / convexityDefects / isContourConvex / fitLine
|
|
1221
|
+
### connectedComponents / convexityDefects / isContourConvex / fitLine / fitEllipse
|
|
1487
1222
|
|
|
1488
1223
|
```typescript
|
|
1489
1224
|
function connectedComponents(mat: Mat, options?: { connectivity?: number }): { count: number; labels: Mat } | null;
|
|
@@ -1493,46 +1228,29 @@ function isContourConvex(contour: Point[]): boolean;
|
|
|
1493
1228
|
function fitLine(points: Point[], options?: {
|
|
1494
1229
|
distType?: number; param?: number; reps?: number; aeps?: number;
|
|
1495
1230
|
}): [number, number, number, number] | null;
|
|
1231
|
+
function fitEllipse(points: Point[]): RotatedRect | null;
|
|
1496
1232
|
```
|
|
1497
1233
|
|
|
1498
|
-
`hull` 可为索引数组,或与 `convexHull` 返回格式相同的 Point[]
|
|
1234
|
+
`hull` 可为索引数组,或与 `convexHull` 返回格式相同的 Point[]。`fitEllipse` 至少需要 5 个点。
|
|
1499
1235
|
|
|
1500
1236
|
```javascript
|
|
1501
1237
|
const cc = cv.connectedComponents(bin, { connectivity: 8 });
|
|
1502
1238
|
const hull = cv.convexHull(contour);
|
|
1503
1239
|
const defects = cv.convexityDefects(contour, { hull });
|
|
1504
1240
|
const line = cv.fitLine(points); // [vx, vy, x0, y0]
|
|
1241
|
+
const ell = cv.fitEllipse(contour); // { center, size, angle }
|
|
1505
1242
|
cv.release(cc.labels);
|
|
1506
1243
|
```
|
|
1507
1244
|
|
|
1508
|
-
###
|
|
1245
|
+
### getRectSubPix / phaseCorrelate / estimateAffine2D / estimateAffinePartial2D
|
|
1509
1246
|
|
|
1510
1247
|
```typescript
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
/** 就地改写 mask,返回 mask 句柄 */
|
|
1514
|
-
function grabCut(mat: Mat, options: {
|
|
1515
|
-
mask: Mat; rect?: Rect; iterCount?: number; mode?: number;
|
|
1248
|
+
function getRectSubPix(mat: Mat, options: {
|
|
1249
|
+
patchSize: Size | [number, number]; center: Point;
|
|
1516
1250
|
}): Mat | null;
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
cv.watershed(src, { markers }); // 就地改 markers
|
|
1521
|
-
cv.grabCut(src, {
|
|
1522
|
-
mask,
|
|
1523
|
-
rect: { x: 50, y: 50, width: 200, height: 200 },
|
|
1524
|
-
iterCount: 5,
|
|
1525
|
-
mode: cv.GC_INIT_WITH_RECT,
|
|
1526
|
-
}); // 就地改 mask
|
|
1527
|
-
```
|
|
1528
|
-
|
|
1529
|
-
---
|
|
1530
|
-
|
|
1531
|
-
## Calib3d / Features / Objdetect
|
|
1532
|
-
|
|
1533
|
-
### estimateAffine2D / estimateAffinePartial2D
|
|
1534
|
-
|
|
1535
|
-
```typescript
|
|
1251
|
+
function phaseCorrelate(src1: Mat, options: { src2: Mat; window?: Mat }): {
|
|
1252
|
+
x: number; y: number; response?: number;
|
|
1253
|
+
} | null;
|
|
1536
1254
|
function estimateAffine2D(options: {
|
|
1537
1255
|
srcPoints: Point[]; dstPoints: Point[]; method?: number; ransacReprojThreshold?: number;
|
|
1538
1256
|
}): Mat | null;
|
|
@@ -1541,57 +1259,34 @@ function estimateAffinePartial2D(options: {
|
|
|
1541
1259
|
}): Mat | null;
|
|
1542
1260
|
```
|
|
1543
1261
|
|
|
1544
|
-
|
|
1545
|
-
const M = cv.estimateAffine2D({
|
|
1546
|
-
srcPoints, dstPoints, method: cv.RANSAC, ransacReprojThreshold: 3,
|
|
1547
|
-
});
|
|
1548
|
-
```
|
|
1549
|
-
|
|
1550
|
-
### KAZE / MSER / SimpleBlobDetector / AGAST
|
|
1551
|
-
|
|
1552
|
-
```typescript
|
|
1553
|
-
function KAZE(mat: Mat, options?: { mask?: Mat }): { keypoints: KeyPoint[]; descriptors: Mat | null } | null;
|
|
1554
|
-
function MSER(mat: Mat, options?: { mask?: Mat }): { keypoints: KeyPoint[] } | null;
|
|
1555
|
-
function SimpleBlobDetector(mat: Mat, options?: { mask?: Mat }): { keypoints: KeyPoint[] } | null;
|
|
1556
|
-
function AGAST(mat: Mat, options?: {
|
|
1557
|
-
threshold?: number; nonmaxSuppression?: boolean; mask?: Mat;
|
|
1558
|
-
}): { keypoints: KeyPoint[] } | null;
|
|
1559
|
-
```
|
|
1262
|
+
`phaseCorrelate` 估计两帧位移(滚动/拖拽);`estimateAffinePartial2D` 为相似变换(平移+旋转+等比缩放)。
|
|
1560
1263
|
|
|
1561
1264
|
```javascript
|
|
1562
|
-
const
|
|
1563
|
-
const
|
|
1564
|
-
const blobs = cv.SimpleBlobDetector(gray);
|
|
1565
|
-
const agast = cv.AGAST(gray, { threshold: 10 });
|
|
1566
|
-
if (kaze.descriptors) cv.release(kaze.descriptors);
|
|
1265
|
+
const shift = cv.phaseCorrelate(prevGray, { src2: gray });
|
|
1266
|
+
const M = cv.estimateAffinePartial2D({ srcPoints, dstPoints, method: cv.RANSAC });
|
|
1567
1267
|
```
|
|
1568
1268
|
|
|
1569
|
-
###
|
|
1269
|
+
### drawMarker / arrowedLine / fillConvexPoly(就地)
|
|
1570
1270
|
|
|
1571
1271
|
```typescript
|
|
1572
|
-
function
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1272
|
+
function drawMarker(mat: Mat, options: {
|
|
1273
|
+
position: Point; color?: number[] | string;
|
|
1274
|
+
markerType?: number; markerSize?: number; thickness?: number;
|
|
1275
|
+
}): Mat | null;
|
|
1276
|
+
function arrowedLine(mat: Mat, options: {
|
|
1277
|
+
pt1: Point; pt2: Point; color?: number[] | string; thickness?: number; tipLength?: number;
|
|
1278
|
+
}): Mat | null;
|
|
1279
|
+
function fillConvexPoly(mat: Mat, options: { pts: Point[]; color?: number[] | string }): Mat | null;
|
|
1578
1280
|
```
|
|
1579
1281
|
|
|
1580
|
-
|
|
1282
|
+
就地修改输入 Mat,返回同一句柄。适合调试标注匹配点、滑动方向等。
|
|
1581
1283
|
|
|
1582
1284
|
```javascript
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
scaleFactor: 1.1,
|
|
1587
|
-
minNeighbors: 3,
|
|
1588
|
-
});
|
|
1589
|
-
const people = cv.HOGDetect(src);
|
|
1590
|
-
cv.release(qr);
|
|
1285
|
+
cv.drawMarker(src, { position: { x: 100, y: 80 }, markerType: cv.MARKER_CROSS });
|
|
1286
|
+
cv.arrowedLine(src, { pt1: { x: 10, y: 10 }, pt2: { x: 120, y: 80 }, color: [0, 255, 0] });
|
|
1287
|
+
cv.fillConvexPoly(src, { pts: [{ x: 20, y: 20 }, { x: 70, y: 20 }, { x: 45, y: 60 }], color: [128, 0, 128] });
|
|
1591
1288
|
```
|
|
1592
1289
|
|
|
1593
|
-
---
|
|
1594
|
-
|
|
1595
1290
|
## 常用常量
|
|
1596
1291
|
|
|
1597
1292
|
挂在 `cv` 上,例如:
|
|
@@ -1614,13 +1309,9 @@ cv.release(qr);
|
|
|
1614
1309
|
- 形状匹配:`CONTOURS_MATCH_I1` / `I2` / `I3`
|
|
1615
1310
|
- 连通域统计列:`CC_STAT_LEFT` / `TOP` / `WIDTH` / `HEIGHT` / `AREA`
|
|
1616
1311
|
- 读标志:`IMREAD_COLOR`、`IMREAD_GRAYSCALE`、`IMREAD_UNCHANGED`
|
|
1617
|
-
-
|
|
1618
|
-
- 无缝克隆:`NORMAL_CLONE`、`MIXED_CLONE`、`MONOCHROME_TRANSFER`
|
|
1312
|
+
- 修复:`INPAINT_NS`、`INPAINT_TELEA`
|
|
1619
1313
|
- 比较:`CMP_EQ` / `CMP_GT` / `CMP_GE` / `CMP_LT` / `CMP_LE` / `CMP_NE`
|
|
1620
|
-
-
|
|
1621
|
-
- 极坐标:`WARP_POLAR_LINEAR`、`WARP_POLAR_LOG`
|
|
1622
|
-
- 标记:`MARKER_CROSS`、`MARKER_STAR`、`MARKER_DIAMOND`、…
|
|
1623
|
-
- GrabCut:`GC_BGD` / `GC_FGD` / `GC_PR_BGD` / `GC_PR_FGD`、`GC_INIT_WITH_RECT` / `GC_INIT_WITH_MASK` / `GC_EVAL`
|
|
1314
|
+
- 标记:`MARKER_CROSS`、`MARKER_STAR`、`MARKER_DIAMOND`、`MARKER_SQUARE`、…
|
|
1624
1315
|
|
|
1625
1316
|
完整列表见类型提示 `types/opencv.d.ts`。
|
|
1626
1317
|
|
|
@@ -1628,11 +1319,10 @@ cv.release(qr);
|
|
|
1628
1319
|
|
|
1629
1320
|
## 限制与建议
|
|
1630
1321
|
|
|
1631
|
-
1. 同时存活的 Mat 句柄有上限(约 32),用完请 `release`,或阶段结束 `releaseAll
|
|
1322
|
+
1. 同时存活的 Mat 句柄有上限(约 32),用完请 `release`,或阶段结束 `releaseAll`。
|
|
1632
1323
|
2. 路径 / msbundle / imageId / `screen` 只走 `imread`;其它 API 只接受 Mat 句柄。
|
|
1633
1324
|
3. SIFT 描述子优先 `flannKnnMatch`;ORB 用 `BFMatcher` + `NORM_HAMMING`。
|
|
1634
1325
|
4. 特征匹配前建议转灰度;大图可先 `pyrDown` / `resize`。
|
|
1635
1326
|
5. `findHomography` 至少需要 4 对对应点,不足会返回 `null`。
|
|
1636
|
-
6. 绘制类、`floodFill
|
|
1637
|
-
7. 与 `image` 互通时,两边句柄各自 `release`。
|
|
1638
|
-
8. `CascadeClassifier` 需要设备上可访问的级联 xml 路径。
|
|
1327
|
+
6. 绘制类、`floodFill` 会改原图或指定目标句柄;需保留原图请先 `clone`。
|
|
1328
|
+
7. 与 `image` 互通时,两边句柄各自 `release`。
|
package/docs/apicn/dotocr.md
CHANGED
|
@@ -85,7 +85,7 @@ function 识别绝对坐标(
|
|
|
85
85
|
| `输入源` | 字符串 | 是 | | 输入源,支持 `"screen"`、图片文件路径、URL 或 imageId |
|
|
86
86
|
| `左`, `上` | 数字 | 否 | 0 | 裁剪区域左上角坐标 |
|
|
87
87
|
| `右`, `下` | 数字 | 否 | 0 | 裁剪区域右下角坐标;`右` 或 `下` 为 0 时分别使用图像宽度或高度 |
|
|
88
|
-
| `置信度阈值` | 数字 | 否 | 0.8
|
|
88
|
+
| `置信度阈值` | 数字 | 否 | 0.8 | 相似度下限;`<=0` 时按 `0.8`;低于阈值的字符会被过滤;`>0.95` 时要求像素完全一致 |
|
|
89
89
|
|
|
90
90
|
**返回值:**`数组<OCR字符>`。按行从上到下、同一行从左到右排列。颜色按字库各字自带的前景色/偏色匹配,无需额外传色。
|
|
91
91
|
|
|
@@ -121,7 +121,7 @@ function 查找文本绝对坐标(
|
|
|
121
121
|
| `左`, `上` | 数字 | 否 | 0 | 裁剪区域左上角坐标 |
|
|
122
122
|
| `右`, `下` | 数字 | 否 | 0 | 裁剪区域右下角坐标;`右` 或 `下` 为 0 时分别使用图像宽度或高度 |
|
|
123
123
|
| `置信度阈值` | 数字 | 否 | 0.8 | 单字符识别相似度下限;语义同 `识别绝对坐标` |
|
|
124
|
-
| `完整匹配` | 布尔值 | 否 | false
|
|
124
|
+
| `完整匹配` | 布尔值 | 否 | false | `false` 为行内子串包含匹配;`true` 要求某一整行文本完全等于目标字符串 |
|
|
125
125
|
|
|
126
126
|
**返回值:**命中结果数组。每个目标最多返回一次命中(最先匹配到的行);每项的 `text` 是目标字符串。
|
|
127
127
|
|
package/docs/apicn/node.md
CHANGED
|
@@ -90,6 +90,13 @@ interface $节点信息 {
|
|
|
90
90
|
点击中心(): 布尔值; // 点击中心
|
|
91
91
|
点击随机范围(): 布尔值; // 随机点击
|
|
92
92
|
hittable(): 布尔值; // 节点是否可接收事件,用于判断节点是否在屏幕可见
|
|
93
|
+
tap(): 布尔值; // 无障碍点击
|
|
94
|
+
doubleTap(): 布尔值; // 无障碍双击
|
|
95
|
+
press(duration: 数字): 布尔值; // 无障碍长按,duration 单位毫秒
|
|
96
|
+
scrollToVisible(): 布尔值; // 将节点滚动到可见区域
|
|
97
|
+
clearInput(): 布尔值; // 清空输入
|
|
98
|
+
input(text: 字符串): 布尔值; // 追加输入(聚焦后输入)
|
|
99
|
+
setValue(text: 字符串): 布尔值; // 设置节点的值(见下方支持控件)
|
|
93
100
|
parent(): $节点信息 | null; // 获取父节点
|
|
94
101
|
child(index: 数字): $节点信息 | null; // 获取子节点
|
|
95
102
|
allChildren(): $节点信息[]; // 获取所有子节点
|
|
@@ -274,16 +281,82 @@ const xpathElements = 选择器.xpath("//*[@title='快点JS']").获取所有节
|
|
|
274
281
|
#### 点击操作
|
|
275
282
|
|
|
276
283
|
```typescript
|
|
277
|
-
//
|
|
284
|
+
// 点击节点中心(坐标点击)
|
|
278
285
|
node.点击中心(): 布尔值;
|
|
279
286
|
|
|
280
|
-
//
|
|
287
|
+
// 随机点击节点区域(坐标点击)
|
|
281
288
|
node.点击随机范围(): 布尔值;
|
|
282
289
|
|
|
283
290
|
// 节点是否可接收事件(用于判断是否显示在屏幕上)
|
|
284
291
|
node.hittable(): 布尔值;
|
|
292
|
+
|
|
293
|
+
// 无障碍点击
|
|
294
|
+
node.tap(): 布尔值;
|
|
295
|
+
|
|
296
|
+
// 无障碍双击
|
|
297
|
+
node.doubleTap(): 布尔值;
|
|
298
|
+
|
|
299
|
+
// 无障碍长按,duration 单位毫秒
|
|
300
|
+
node.press(duration: 数字): 布尔值;
|
|
301
|
+
|
|
302
|
+
// 将节点滚动到可见区域
|
|
303
|
+
node.scrollToVisible(): 布尔值;
|
|
304
|
+
|
|
305
|
+
// 清空输入
|
|
306
|
+
node.clearInput(): 布尔值;
|
|
307
|
+
|
|
308
|
+
// 追加输入
|
|
309
|
+
node.input(text: 字符串): 布尔值;
|
|
310
|
+
|
|
311
|
+
// 设置节点的值
|
|
312
|
+
node.setValue(text: 字符串): 布尔值;
|
|
285
313
|
```
|
|
286
314
|
|
|
315
|
+
#### tap / doubleTap / press - 无障碍手势
|
|
316
|
+
|
|
317
|
+
通过无障碍 API 直接操作节点,不依赖坐标点击。
|
|
318
|
+
|
|
319
|
+
| 方法 | 参数 | 说明 |
|
|
320
|
+
| --- | --- | --- |
|
|
321
|
+
| `tap()` | 无 | 无障碍单击 |
|
|
322
|
+
| `doubleTap()` | 无 | 无障碍双击 |
|
|
323
|
+
| `press(duration)` | `duration`:长按持续时间,单位毫秒 | 无障碍长按 |
|
|
324
|
+
|
|
325
|
+
**示例:**
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const 选择器 = $创建节点选择器();
|
|
329
|
+
|
|
330
|
+
const btn = 选择器.label("确定").type("XCUIElementTypeButton").获取一个节点(3000);
|
|
331
|
+
if (btn) {
|
|
332
|
+
// 无障碍单击
|
|
333
|
+
btn.tap();
|
|
334
|
+
|
|
335
|
+
// 无障碍双击
|
|
336
|
+
btn.doubleTap();
|
|
337
|
+
|
|
338
|
+
// 无障碍长按 800ms
|
|
339
|
+
btn.press(800);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// 释放选择器内存
|
|
343
|
+
选择器.释放内存();
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
#### setValue - 设置节点的值
|
|
347
|
+
|
|
348
|
+
按控件类型自动处理,常用支持如下:
|
|
349
|
+
|
|
350
|
+
| 控件类型 | 传参示例 | 说明 |
|
|
351
|
+
| --- | --- | --- |
|
|
352
|
+
| `XCUIElementTypePickerWheel` | `"1小时"` | 滚轮选到对应选项文案 |
|
|
353
|
+
| `XCUIElementTypeTextField` | `"hello"` | 先聚焦再输入文本 |
|
|
354
|
+
| `XCUIElementTypeSecureTextField` | `"123456"` | 同上 |
|
|
355
|
+
| `XCUIElementTypeTextView` | `"多行内容"` | 同上 |
|
|
356
|
+
| `XCUIElementTypeSearchField` | `"关键词"` | 同上 |
|
|
357
|
+
|
|
358
|
+
文本类控件不会先清空已有内容;需要清空时先调用 `clearInput()`。
|
|
359
|
+
|
|
287
360
|
**示例:**
|
|
288
361
|
|
|
289
362
|
```typescript
|
|
@@ -298,12 +371,25 @@ if (confirmBtn) {
|
|
|
298
371
|
const isHittable = confirmBtn.hittable();
|
|
299
372
|
$打印信息日志(`是否可接收事件: ${isHittable}`);
|
|
300
373
|
|
|
301
|
-
|
|
374
|
+
confirmBtn.scrollToVisible();
|
|
375
|
+
// 优先使用无障碍点击;也可用 点击中心 / 点击随机范围 做坐标点击
|
|
376
|
+
const clicked = confirmBtn.tap();
|
|
302
377
|
if (clicked) {
|
|
303
378
|
$打印信息日志("成功点击确定按钮");
|
|
304
379
|
}
|
|
305
380
|
}
|
|
306
381
|
|
|
382
|
+
const field = 选择器.type("XCUIElementTypeTextField").获取一个节点(3000);
|
|
383
|
+
if (field) {
|
|
384
|
+
field.clearInput();
|
|
385
|
+
field.setValue("hello");
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const wheel = 选择器.type("XCUIElementTypePickerWheel").获取一个节点(3000);
|
|
389
|
+
if (wheel) {
|
|
390
|
+
wheel.setValue("1小时");
|
|
391
|
+
}
|
|
392
|
+
|
|
307
393
|
// 随机点击避免检测
|
|
308
394
|
const randomClick = confirmBtn?.点击随机范围();
|
|
309
395
|
if (randomClick) {
|
package/docs/apipython/dotocr.md
CHANGED
|
@@ -81,7 +81,7 @@ def recognizeAbs(
|
|
|
81
81
|
| `input` | str | 是 | | 输入源,支持 `"screen"`、图片文件路径、URL 或 imageId |
|
|
82
82
|
| `x`, `y` | int | 否 | 0 | 裁剪区域左上角坐标 |
|
|
83
83
|
| `ex`, `ey` | int | 否 | 0 | 裁剪区域右下角坐标;`ex` 或 `ey` 为 0 时分别使用图像宽度或高度 |
|
|
84
|
-
| `confidenceThreshold` | float
|
|
84
|
+
| `confidenceThreshold` | float | 否 | 0.8 | 相似度下限;`<=0` 时按 `0.8`;低于阈值的字符会被过滤;`>0.95` 时要求像素完全一致 |
|
|
85
85
|
|
|
86
86
|
**返回值:**`List[OCRChar]`。按行从上到下、同一行从左到右排列。颜色按字库各字自带的前景色/偏色匹配,无需额外传色。
|
|
87
87
|
|
|
@@ -117,7 +117,7 @@ def findTextAbs(
|
|
|
117
117
|
| `x`, `y` | int | 否 | 0 | 裁剪区域左上角坐标 |
|
|
118
118
|
| `ex`, `ey` | int | 否 | 0 | 裁剪区域右下角坐标;`ex` 或 `ey` 为 0 时分别使用图像宽度或高度 |
|
|
119
119
|
| `confidenceThreshold` | float | 否 | 0.8 | 单字符识别相似度下限;语义同 `recognizeAbs` |
|
|
120
|
-
| `exactMatch` | bool | 否 | false
|
|
120
|
+
| `exactMatch` | bool | 否 | false | `false` 为行内子串包含匹配;`true` 要求某一整行文本完全等于目标字符串 |
|
|
121
121
|
|
|
122
122
|
**返回值:**命中结果数组。每个目标最多返回一次命中(最先匹配到的行);每项的 `text` 是目标字符串。
|
|
123
123
|
|
package/docs/apipython/node.md
CHANGED
|
@@ -37,6 +37,13 @@ class NodeInfo:
|
|
|
37
37
|
def clickCenter(self) -> bool: ...
|
|
38
38
|
def clickRandom(self) -> bool: ...
|
|
39
39
|
def hittable(self) -> bool: ...
|
|
40
|
+
def tap(self) -> bool: ...
|
|
41
|
+
def doubleTap(self) -> bool: ...
|
|
42
|
+
def press(self, duration: int = 500) -> bool: ...
|
|
43
|
+
def scrollToVisible(self) -> bool: ...
|
|
44
|
+
def clearInput(self) -> bool: ...
|
|
45
|
+
def input(self, text: str) -> bool: ...
|
|
46
|
+
def setValue(self, text: str) -> bool: ...
|
|
40
47
|
def parent(self) -> Optional["NodeInfo"]: ...
|
|
41
48
|
def child(self, index: int) -> Optional["NodeInfo"]: ...
|
|
42
49
|
def allChildren(self) -> List["NodeInfo"]: ...
|
|
@@ -253,16 +260,80 @@ xpath_elements = selector.xpath("//*[@title='快点JS']").getNodeInfo(3000)
|
|
|
253
260
|
### 点击操作
|
|
254
261
|
|
|
255
262
|
```python
|
|
256
|
-
#
|
|
263
|
+
# 点击节点中心(坐标点击)
|
|
257
264
|
def clickCenter() -> bool
|
|
258
265
|
|
|
259
|
-
#
|
|
266
|
+
# 随机点击节点区域(坐标点击)
|
|
260
267
|
def clickRandom() -> bool
|
|
261
268
|
|
|
262
269
|
# 节点是否可接收事件(用于判断是否显示在屏幕上)
|
|
263
270
|
def hittable() -> bool
|
|
271
|
+
|
|
272
|
+
# 无障碍点击
|
|
273
|
+
def tap() -> bool
|
|
274
|
+
|
|
275
|
+
# 无障碍双击
|
|
276
|
+
def doubleTap() -> bool
|
|
277
|
+
|
|
278
|
+
# 无障碍长按,duration 单位毫秒,默认 500
|
|
279
|
+
def press(duration: int = 500) -> bool
|
|
280
|
+
|
|
281
|
+
# 将节点滚动到可见区域
|
|
282
|
+
def scrollToVisible() -> bool
|
|
283
|
+
|
|
284
|
+
# 清空输入
|
|
285
|
+
def clearInput() -> bool
|
|
286
|
+
|
|
287
|
+
# 追加输入
|
|
288
|
+
def input(text: str) -> bool
|
|
289
|
+
|
|
290
|
+
# 设置节点的值
|
|
291
|
+
def setValue(text: str) -> bool
|
|
264
292
|
```
|
|
265
293
|
|
|
294
|
+
#### tap / doubleTap / press - 无障碍手势
|
|
295
|
+
|
|
296
|
+
通过无障碍 API 直接操作节点,不依赖坐标点击。
|
|
297
|
+
|
|
298
|
+
| 方法 | 参数 | 说明 |
|
|
299
|
+
| --- | --- | --- |
|
|
300
|
+
| `tap()` | 无 | 无障碍单击 |
|
|
301
|
+
| `doubleTap()` | 无 | 无障碍双击 |
|
|
302
|
+
| `press(duration=500)` | `duration`:长按持续时间,单位毫秒,默认 500 | 无障碍长按 |
|
|
303
|
+
|
|
304
|
+
**示例:**
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
from kuaijs import node
|
|
308
|
+
|
|
309
|
+
selector = node.createNodeSelector()
|
|
310
|
+
|
|
311
|
+
btn = selector.label("确定").type("XCUIElementTypeButton").getOneNodeInfo(3000)
|
|
312
|
+
if btn:
|
|
313
|
+
# 无障碍单击
|
|
314
|
+
btn.tap()
|
|
315
|
+
|
|
316
|
+
# 无障碍双击
|
|
317
|
+
btn.doubleTap()
|
|
318
|
+
|
|
319
|
+
# 无障碍长按 800ms
|
|
320
|
+
btn.press(800)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
#### setValue - 设置节点的值
|
|
324
|
+
|
|
325
|
+
按控件类型自动处理,常用支持如下:
|
|
326
|
+
|
|
327
|
+
| 控件类型 | 传参示例 | 说明 |
|
|
328
|
+
| --- | --- | --- |
|
|
329
|
+
| `XCUIElementTypePickerWheel` | `"1小时"` | 滚轮选到对应选项文案 |
|
|
330
|
+
| `XCUIElementTypeTextField` | `"hello"` | 先聚焦再输入文本 |
|
|
331
|
+
| `XCUIElementTypeSecureTextField` | `"123456"` | 同上 |
|
|
332
|
+
| `XCUIElementTypeTextView` | `"多行内容"` | 同上 |
|
|
333
|
+
| `XCUIElementTypeSearchField` | `"关键词"` | 同上 |
|
|
334
|
+
|
|
335
|
+
文本类控件不会先清空已有内容;需要清空时先调用 `clearInput()`。
|
|
336
|
+
|
|
266
337
|
**示例:**
|
|
267
338
|
|
|
268
339
|
```python
|
|
@@ -276,12 +347,23 @@ confirm_btn = selector.label("确定").type("XCUIElementTypeButton").getOneNodeI
|
|
|
276
347
|
if confirm_btn:
|
|
277
348
|
print(f"是否可接收事件: {confirm_btn.hittable()}")
|
|
278
349
|
|
|
279
|
-
|
|
350
|
+
confirm_btn.scrollToVisible()
|
|
351
|
+
# 优先使用无障碍点击;也可用 clickCenter / clickRandom 做坐标点击
|
|
352
|
+
clicked = confirm_btn.tap()
|
|
280
353
|
if clicked:
|
|
281
354
|
print("成功点击确定按钮")
|
|
282
355
|
|
|
283
|
-
#
|
|
356
|
+
# 随机坐标点击避免检测
|
|
284
357
|
confirm_btn.clickRandom()
|
|
358
|
+
|
|
359
|
+
field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000)
|
|
360
|
+
if field:
|
|
361
|
+
field.clearInput()
|
|
362
|
+
field.setValue("hello")
|
|
363
|
+
|
|
364
|
+
wheel = selector.type("XCUIElementTypePickerWheel").getOneNodeInfo(3000)
|
|
365
|
+
if wheel:
|
|
366
|
+
wheel.setValue("1小时")
|
|
285
367
|
```
|
|
286
368
|
|
|
287
369
|
### 节点导航
|