@anytestforpm/ocr 1.2.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/README.md +56 -0
- package/ocr.js +183 -0
- package/package.json +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Install
|
|
2
|
+
npm i @anytestforpm/ocr
|
|
3
|
+
# Usage Example
|
|
4
|
+
1.初始化OCR設定,取得后台設定檔
|
|
5
|
+
```javascript
|
|
6
|
+
import { initOCR } from '@anytestforpm/ocr';
|
|
7
|
+
|
|
8
|
+
mounted() {
|
|
9
|
+
//init ocr config , region support VN IN ID BR
|
|
10
|
+
if (process.env.NODE_ENV === 'production') {
|
|
11
|
+
initOCR('VN','https://your-api-domain');
|
|
12
|
+
} else {
|
|
13
|
+
initOCR('VN','https://your-api-domain');
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
```
|
|
17
|
+
2.執行OCR圖片辨識
|
|
18
|
+
```javascript
|
|
19
|
+
import { recognizeOCR, RESULT_TYPE } from '@anytestforpm/ocr';
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
let ocrResData = await recognizeOCR(imgUrl);
|
|
23
|
+
//取得后台設定檔失敗
|
|
24
|
+
if (ocrResData.type === RESULT_TYPE.CONFIG_INVALID) {
|
|
25
|
+
//do something
|
|
26
|
+
}
|
|
27
|
+
//圖片辨識功能已停用
|
|
28
|
+
if (ocrResData.type === RESULT_TYPE.CONFIG_DISABLED) {
|
|
29
|
+
//do something
|
|
30
|
+
}
|
|
31
|
+
//驗證成功
|
|
32
|
+
if (ocrResData.type === RESULT_TYPE.KEYWORDS_SUCCESS) {
|
|
33
|
+
//do something
|
|
34
|
+
}
|
|
35
|
+
//驗證不合格 - 關鍵字匹配不合格
|
|
36
|
+
if (ocrResData.type === RESULT_TYPE.KEYWORDS_NOT_FOUND) {
|
|
37
|
+
//do something
|
|
38
|
+
}
|
|
39
|
+
//驗證不合格 - 不合法的關鍵字
|
|
40
|
+
if (ocrResData.type === RESULT_TYPE.KEYWORDS_INVALID) {
|
|
41
|
+
//do something
|
|
42
|
+
}
|
|
43
|
+
//驗證超時
|
|
44
|
+
if (ocrResData.type === RESULT_TYPE.KEYWORDS_TIMEOUT) {
|
|
45
|
+
//do something
|
|
46
|
+
}
|
|
47
|
+
} catch (execption) {
|
|
48
|
+
//do something
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
3.入參imgUrl
|
|
53
|
+
let ocrResData = await recognizeOCR(imgUrl);
|
|
54
|
+
mixins.js
|
|
55
|
+

|
|
56
|
+
|
package/ocr.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
|
|
2
|
+
import { createWorker } from 'tesseract.js';
|
|
3
|
+
import axios from 'axios'
|
|
4
|
+
var md5 = require('md5');
|
|
5
|
+
|
|
6
|
+
var configData = null; //configuration file returned by API
|
|
7
|
+
|
|
8
|
+
const OCR_LANGUAGE_MAP = {
|
|
9
|
+
VN: "vie",
|
|
10
|
+
ID: "ind",
|
|
11
|
+
IN: "hin",
|
|
12
|
+
BR: "por",
|
|
13
|
+
EN: "eng"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const setResponseData = (val) => {
|
|
17
|
+
return {
|
|
18
|
+
type: val
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const RESULT_TYPE = {
|
|
23
|
+
KEYWORDS_SUCCESS: "SUCCESS",
|
|
24
|
+
KEYWORDS_NOT_FOUND: "NOT_FOUND",
|
|
25
|
+
KEYWORDS_INVALID: "INVALID",
|
|
26
|
+
KEYWORDS_TIMEOUT: "TIMEOUT",
|
|
27
|
+
KEYWORDS_EXCEPTION: "EXCEPTION",
|
|
28
|
+
CONFIG_INVALID: "CONFIG_INVALID",
|
|
29
|
+
CONFIG_DISABLED: "CONFIG_DISABLED",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @description for testing
|
|
34
|
+
* @param {String} val
|
|
35
|
+
*/
|
|
36
|
+
export const hello = (val) => {
|
|
37
|
+
return 'Hello,' + val;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @description initialization ocr config
|
|
42
|
+
* @param {String} region area of config
|
|
43
|
+
*/
|
|
44
|
+
export const initOCR = (region,apiHost) => {
|
|
45
|
+
try {
|
|
46
|
+
//sign
|
|
47
|
+
let timestamp = Math.fround(Date.now()/1000);
|
|
48
|
+
let hashString = md5(region+"."+timestamp).toUpperCase();
|
|
49
|
+
|
|
50
|
+
//get config
|
|
51
|
+
configData = null;
|
|
52
|
+
axios({
|
|
53
|
+
url: apiHost,
|
|
54
|
+
method: "post",
|
|
55
|
+
timeout: 60000,
|
|
56
|
+
responseType: "json",
|
|
57
|
+
data: {
|
|
58
|
+
"region": region,
|
|
59
|
+
"timestamp": timestamp,
|
|
60
|
+
"sign": hashString
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
.then((res) => {
|
|
64
|
+
if (res.status === 200 && res.data.config.enable) {
|
|
65
|
+
configData = res.data;
|
|
66
|
+
console.log("Initialization successful");
|
|
67
|
+
}else if (res.status === 200 && !res.data.config.enable) {
|
|
68
|
+
configData = res.data;
|
|
69
|
+
console.log("OCR service disabled");
|
|
70
|
+
}else {
|
|
71
|
+
console.log("Initialization failed");
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.catch((error) => {
|
|
75
|
+
console.error(error)
|
|
76
|
+
});
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('exception: ', error);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @description start ocr recognize
|
|
85
|
+
* @param {String} ImageUrl image url
|
|
86
|
+
*/
|
|
87
|
+
export const recognizeOCR = async (ImageUrl) => {
|
|
88
|
+
|
|
89
|
+
//初始化失敗
|
|
90
|
+
if (!configData) {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
console.error(RESULT_TYPE.CONFIG_INVALID);
|
|
93
|
+
resolve(setResponseData(RESULT_TYPE.CONFIG_INVALID));
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//后台停用辨識圖片功能
|
|
97
|
+
if (!configData.config.enable) {
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
console.error(RESULT_TYPE.CONFIG_DISABLED);
|
|
100
|
+
resolve(setResponseData(RESULT_TYPE.CONFIG_DISABLED));
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let ocr_setTimeout = null;
|
|
105
|
+
let startTime = new Date();
|
|
106
|
+
let worker = await createWorker(
|
|
107
|
+
{
|
|
108
|
+
logger: msg => {
|
|
109
|
+
console.log(new Date() - startTime, msg);
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
//OCR辨識過程中發生超時
|
|
115
|
+
const timeoutPromise = new Promise((resolve, reject) => {
|
|
116
|
+
ocr_setTimeout = setTimeout(() => {
|
|
117
|
+
console.error(RESULT_TYPE.KEYWORDS_TIMEOUT);
|
|
118
|
+
resolve(setResponseData(RESULT_TYPE.KEYWORDS_TIMEOUT));
|
|
119
|
+
}, configData.config.timeout_in_seconds * 1000); //设置超时时间
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
//OCR辨識
|
|
123
|
+
const ocrPromise = new Promise(async (resolve, reject) => {
|
|
124
|
+
try {
|
|
125
|
+
await worker.loadLanguage(OCR_LANGUAGE_MAP[configData.region]);
|
|
126
|
+
await worker.initialize(OCR_LANGUAGE_MAP[configData.region]);
|
|
127
|
+
|
|
128
|
+
//OCR辨識結果的內文
|
|
129
|
+
const result = await worker.recognize(ImageUrl);
|
|
130
|
+
const resText = String(result.data.text);
|
|
131
|
+
console.log("OCR Text >>> ", resText);
|
|
132
|
+
|
|
133
|
+
//比對不合法的關鍵字
|
|
134
|
+
let invalidKeyWords = configData.keywords.invalid.filter((item) => resText.search(item) >= 0);
|
|
135
|
+
console.log("search invalid keywords result >>> ", invalidKeyWords);
|
|
136
|
+
if (invalidKeyWords.length != 0) {
|
|
137
|
+
resolve(setResponseData(RESULT_TYPE.KEYWORDS_INVALID));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//比對合法的關鍵字
|
|
142
|
+
let validKeyWords = configData.keywords.valid.filter((item) => resText.search(item) >= 0);
|
|
143
|
+
console.log("search valid keywords result >>> ", validKeyWords);
|
|
144
|
+
if (validKeyWords.length >= configData.config.verify_in_counts) {
|
|
145
|
+
resolve(setResponseData(RESULT_TYPE.KEYWORDS_SUCCESS));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//比對電話卡數字長度
|
|
150
|
+
if (configData.config.phone_number_in_continuous) {
|
|
151
|
+
let phoneCardLength = 0;
|
|
152
|
+
for (let val of resText.split("")) {
|
|
153
|
+
if (val === "\u0020") continue;
|
|
154
|
+
!isNaN(parseInt(val)) ? phoneCardLength++ : phoneCardLength = 0;
|
|
155
|
+
if (phoneCardLength >= configData.config.phone_number_in_continuous) break;
|
|
156
|
+
}
|
|
157
|
+
console.log("search phoneCard max Length result >>> ", phoneCardLength);
|
|
158
|
+
if (phoneCardLength >= configData.config.phone_number_in_continuous) {
|
|
159
|
+
resolve(setResponseData(RESULT_TYPE.KEYWORDS_SUCCESS));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
//驗證失敗 沒有找到任何匹配的條件
|
|
166
|
+
console.log("verification failed , keywords not found");
|
|
167
|
+
resolve(setResponseData(RESULT_TYPE.KEYWORDS_NOT_FOUND));
|
|
168
|
+
|
|
169
|
+
} catch (error) {
|
|
170
|
+
reject(setResponseData(RESULT_TYPE.KEYWORDS_EXCEPTION));
|
|
171
|
+
console.error(error);
|
|
172
|
+
} finally {
|
|
173
|
+
|
|
174
|
+
clearTimeout(ocr_setTimeout);
|
|
175
|
+
await worker.terminate();
|
|
176
|
+
worker = null;
|
|
177
|
+
//URL.revokeObjectURL(imagePath);
|
|
178
|
+
console.log('free up memory');
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return Promise.race([ocrPromise, timeoutPromise]);
|
|
183
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anytestforpm/ocr",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "ocr.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"axios": "^0.19.0",
|
|
14
|
+
"md5": "^2.3.0",
|
|
15
|
+
"tesseract.js": "^4.0.2"
|
|
16
|
+
}
|
|
17
|
+
}
|