@areb0s/ocr-common 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.
Files changed (55) hide show
  1. package/build/Ocr.d.ts +15 -0
  2. package/build/Ocr.js +24 -0
  3. package/build/Ocr.js.map +1 -0
  4. package/build/backend/FileUtilsBase.d.ts +3 -0
  5. package/build/backend/FileUtilsBase.js +6 -0
  6. package/build/backend/FileUtilsBase.js.map +1 -0
  7. package/build/backend/ImageRawBase.d.ts +8 -0
  8. package/build/backend/ImageRawBase.js +14 -0
  9. package/build/backend/ImageRawBase.js.map +1 -0
  10. package/build/backend/backend.d.ts +14 -0
  11. package/build/backend/backend.js +14 -0
  12. package/build/backend/backend.js.map +1 -0
  13. package/build/backend/index.d.ts +3 -0
  14. package/build/backend/index.js +4 -0
  15. package/build/backend/index.js.map +1 -0
  16. package/build/backend/splitIntoLineImages.d.ts +2 -0
  17. package/build/backend/splitIntoLineImages.js +231 -0
  18. package/build/backend/splitIntoLineImages.js.map +1 -0
  19. package/build/index.d.ts +6 -0
  20. package/build/index.js +6 -0
  21. package/build/index.js.map +1 -0
  22. package/build/models/Detection.d.ts +13 -0
  23. package/build/models/Detection.js +82 -0
  24. package/build/models/Detection.js.map +1 -0
  25. package/build/models/ModelBase.d.ts +14 -0
  26. package/build/models/ModelBase.js +53 -0
  27. package/build/models/ModelBase.js.map +1 -0
  28. package/build/models/Recognition.d.ts +12 -0
  29. package/build/models/Recognition.js +190 -0
  30. package/build/models/Recognition.js.map +1 -0
  31. package/build/models/index.d.ts +2 -0
  32. package/build/models/index.js +3 -0
  33. package/build/models/index.js.map +1 -0
  34. package/build/types/index.d.ts +1 -0
  35. package/build/types/index.js +2 -0
  36. package/build/types/index.js.map +1 -0
  37. package/build/types/types.d.ts +67 -0
  38. package/build/types/types.js +5 -0
  39. package/build/types/types.js.map +1 -0
  40. package/package.json +34 -0
  41. package/src/Ocr.ts +34 -0
  42. package/src/backend/FileUtilsBase.ts +5 -0
  43. package/src/backend/ImageRawBase.ts +17 -0
  44. package/src/backend/backend.ts +29 -0
  45. package/src/backend/index.ts +3 -0
  46. package/src/backend/splitIntoLineImages.ts +296 -0
  47. package/src/index.ts +8 -0
  48. package/src/models/Detection.ts +96 -0
  49. package/src/models/ModelBase.ts +74 -0
  50. package/src/models/Recognition.ts +217 -0
  51. package/src/models/index.ts +2 -0
  52. package/src/types/global.d.ts +7 -0
  53. package/src/types/index.ts +1 -0
  54. package/src/types/types.ts +90 -0
  55. package/tsconfig.json +10 -0
@@ -0,0 +1,190 @@
1
+ import invariant from 'tiny-invariant';
2
+ import { FileUtils, InferenceSession, defaultModels } from '../backend/index.js';
3
+ import { ModelBase } from './ModelBase.js';
4
+ export class Recognition extends ModelBase {
5
+ #dictionary;
6
+ static async create({ models, onnxOptions = {}, ...restOptions }) {
7
+ const recognitionPath = models?.recognitionPath || defaultModels?.recognitionPath;
8
+ invariant(recognitionPath, 'recognitionPath is required');
9
+ const dictionaryPath = models?.dictionaryPath || defaultModels?.dictionaryPath;
10
+ invariant(dictionaryPath, 'dictionaryPath is required');
11
+ const model = await InferenceSession.create(recognitionPath, onnxOptions);
12
+ const dictionaryText = await FileUtils.read(dictionaryPath);
13
+ const dictionary = [...dictionaryText.split('\n'), ' '];
14
+ return new Recognition({ model, options: restOptions }, dictionary);
15
+ }
16
+ constructor(options, dictionary) {
17
+ super(options);
18
+ this.#dictionary = dictionary;
19
+ }
20
+ async run(lineImages, { onnxOptions = {} } = {}) {
21
+ const modelDatas = await Promise.all(
22
+ // Detect text from each line image
23
+ lineImages.map(async (lineImage, index) => {
24
+ // Resize Image to 48px height
25
+ // - height must <= 48
26
+ // - height: 48 is more accurate then 40, but same as 30
27
+ const image = await lineImage.image.resize({
28
+ height: 48,
29
+ });
30
+ this.debugImage(lineImage.image, `out9-line-${index}.jpg`);
31
+ this.debugImage(image, `out9-line-${index}-resized.jpg`);
32
+ // transform image data to model data
33
+ const modelData = this.imageToInput(image, {
34
+ // mean: [0.5, 0.5, 0.5],
35
+ // std: [0.5, 0.5, 0.5],
36
+ });
37
+ return modelData;
38
+ }));
39
+ const allLines = [];
40
+ // console.time('Recognition')
41
+ for (const modelData of modelDatas) {
42
+ // Run model for each line image
43
+ const output = await this.runModel({ modelData, onnxOptions });
44
+ // use Dictoinary to decode output to text
45
+ const lines = await this.decodeText(output);
46
+ allLines.unshift(...lines);
47
+ }
48
+ // console.timeEnd('Recognition')
49
+ const result = calculateBox({ lines: allLines, lineImages });
50
+ return result;
51
+ }
52
+ decodeText(output) {
53
+ const data = output;
54
+ const predLen = data.dims[2];
55
+ const line = [];
56
+ let ml = data.dims[0] - 1;
57
+ for (let l = 0; l < data.data.length; l += predLen * data.dims[1]) {
58
+ const predsIdx = [];
59
+ const predsProb = [];
60
+ for (let i = l; i < l + predLen * data.dims[1]; i += predLen) {
61
+ const tmpArr = data.data.slice(i, i + predLen);
62
+ const tmpMax = tmpArr.reduce((a, b) => Math.max(a, b), Number.NEGATIVE_INFINITY);
63
+ const tmpIdx = tmpArr.indexOf(tmpMax);
64
+ predsProb.push(tmpMax);
65
+ predsIdx.push(tmpIdx);
66
+ }
67
+ line[ml] = decode(this.#dictionary, predsIdx, predsProb, true);
68
+ ml--;
69
+ }
70
+ return line;
71
+ }
72
+ }
73
+ function decode(dictionary, textIndex, textProb, isRemoveDuplicate) {
74
+ const ignoredTokens = [0];
75
+ const charList = [];
76
+ const confList = [];
77
+ for (let idx = 0; idx < textIndex.length; idx++) {
78
+ if (textIndex[idx] in ignoredTokens) {
79
+ continue;
80
+ }
81
+ if (isRemoveDuplicate) {
82
+ if (idx > 0 && textIndex[idx - 1] === textIndex[idx]) {
83
+ continue;
84
+ }
85
+ }
86
+ charList.push(dictionary[textIndex[idx] - 1]);
87
+ if (textProb) {
88
+ confList.push(textProb[idx]);
89
+ }
90
+ else {
91
+ confList.push(1);
92
+ }
93
+ }
94
+ let text = '';
95
+ let mean = 0;
96
+ if (charList.length) {
97
+ text = charList.join('');
98
+ let sum = 0;
99
+ confList.forEach((item) => {
100
+ sum += item;
101
+ });
102
+ mean = sum / confList.length;
103
+ }
104
+ return { text, mean };
105
+ }
106
+ function calculateBox({ lines, lineImages, }) {
107
+ let mainLine = lines;
108
+ const box = lineImages;
109
+ for (const i in mainLine) {
110
+ const b = box[mainLine.length - Number(i) - 1].box;
111
+ for (const p of b) {
112
+ p[0] = p[0];
113
+ p[1] = p[1];
114
+ }
115
+ mainLine[i]['box'] = b;
116
+ }
117
+ mainLine = mainLine.filter((x) => x.mean >= 0.5);
118
+ mainLine = afAfRec(mainLine);
119
+ return mainLine;
120
+ }
121
+ function afAfRec(lines) {
122
+ const outputLines = [];
123
+ const indexes = new Map();
124
+ for (const index in lines) {
125
+ const box = lines[index].box;
126
+ indexes.set(box, Number(index));
127
+ }
128
+ const groupedBoxes = groupBoxesByMidlineDifference([...indexes.keys()]);
129
+ for (const boxes of groupedBoxes) {
130
+ const texts = [];
131
+ let mean = 0;
132
+ for (const box of boxes) {
133
+ const index = indexes.get(box);
134
+ if (index === undefined) {
135
+ continue;
136
+ }
137
+ const line = lines[index];
138
+ texts.push(line.text);
139
+ mean += line.mean;
140
+ }
141
+ let outputBox = undefined;
142
+ if (boxes.at(0) && boxes.at(-1)) {
143
+ outputBox = [boxes.at(0)[0], boxes.at(-1)[1], boxes.at(-1)[2], boxes.at(0)[3]];
144
+ }
145
+ outputLines.push({
146
+ mean: mean / boxes.length,
147
+ text: texts.join(' '),
148
+ box: outputBox,
149
+ });
150
+ }
151
+ return outputLines;
152
+ }
153
+ function calculateAverageHeight(boxes) {
154
+ let totalHeight = 0;
155
+ for (const box of boxes) {
156
+ const [[, y1], , [, y2]] = box;
157
+ const height = y2 - y1;
158
+ totalHeight += height;
159
+ }
160
+ return totalHeight / boxes.length;
161
+ }
162
+ function groupBoxesByMidlineDifference(boxes) {
163
+ const averageHeight = calculateAverageHeight(boxes);
164
+ const result = [];
165
+ for (const box of boxes) {
166
+ const [[, y1], , [, y2]] = box;
167
+ const midline = (y1 + y2) / 2;
168
+ const group = result.find((b) => {
169
+ const [[, groupY1], , [, groupY2]] = b[0];
170
+ const groupMidline = (groupY1 + groupY2) / 2;
171
+ return Math.abs(groupMidline - midline) < averageHeight / 2;
172
+ });
173
+ if (group) {
174
+ group.push(box);
175
+ }
176
+ else {
177
+ result.push([box]);
178
+ }
179
+ }
180
+ for (const group of result) {
181
+ group.sort((a, b) => {
182
+ const [ltA] = a;
183
+ const [ltB] = b;
184
+ return ltA[0] - ltB[0];
185
+ });
186
+ }
187
+ result.sort((a, b) => a[0][0][1] - b[0][0][1]);
188
+ return result;
189
+ }
190
+ //# sourceMappingURL=Recognition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Recognition.js","sourceRoot":"","sources":["../../src/models/Recognition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './Detection.js';
2
+ export * from './Recognition.js';
@@ -0,0 +1,3 @@
1
+ export * from './Detection.js';
2
+ export * from './Recognition.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
@@ -0,0 +1 @@
1
+ export * from './types.js';
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
@@ -0,0 +1,67 @@
1
+ import { InferenceSession } from 'onnxruntime-common';
2
+ import { ImageRawBase as ImageRaw } from '../backend/ImageRawBase.js';
3
+ import type { splitIntoLineImages } from '../backend/splitIntoLineImages.js';
4
+ export { FileUtilsBase as FileUtils } from '../backend/FileUtilsBase.js';
5
+ export { ImageRaw, InferenceSession };
6
+ export type SplitIntoLineImages = typeof splitIntoLineImages;
7
+ export type ReshapeOptions = {
8
+ mean?: number[];
9
+ std?: number[];
10
+ };
11
+ export type ImageRawData = {
12
+ data: Uint8Array | Uint8ClampedArray;
13
+ width: number;
14
+ height: number;
15
+ };
16
+ /**
17
+ * Browser-specific image input types
18
+ * Supports various browser image sources that can be converted to ImageRawData
19
+ */
20
+ export type BrowserImageInput = string | ImageRawData | ImageBitmap | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement;
21
+ export type ModelData = {
22
+ data: number[] | Uint8Array;
23
+ width: number;
24
+ height: number;
25
+ };
26
+ export type Size = {
27
+ width: number;
28
+ height: number;
29
+ };
30
+ export type SizeOption = {
31
+ width?: number;
32
+ height?: number;
33
+ fit?: 'contain' | 'cover' | 'fill' | 'inside' | 'outside';
34
+ };
35
+ export type LineImage = {
36
+ image: ImageRaw;
37
+ box: number[][];
38
+ };
39
+ export type Region = {
40
+ left: number;
41
+ top: number;
42
+ width: number;
43
+ height: number;
44
+ };
45
+ export type Line = {
46
+ text: string;
47
+ mean: number;
48
+ box?: number[][];
49
+ };
50
+ export type Dictionary = string[];
51
+ export type Point = [x: number, y: number];
52
+ export interface ModelBaseConstructorArg {
53
+ model: InferenceSession;
54
+ options: ModelBaseOptions;
55
+ }
56
+ export interface ModelBaseOptions {
57
+ isDebug?: boolean;
58
+ debugOutputDir?: string;
59
+ }
60
+ export interface ModelCreateOptions extends ModelBaseOptions {
61
+ models?: {
62
+ detectionPath: string;
63
+ recognitionPath: string;
64
+ dictionaryPath: string;
65
+ };
66
+ onnxOptions?: InferenceSession.SessionOptions;
67
+ }
@@ -0,0 +1,5 @@
1
+ import { InferenceSession } from 'onnxruntime-common';
2
+ import { ImageRawBase as ImageRaw } from '../backend/ImageRawBase.js';
3
+ export { FileUtilsBase as FileUtils } from '../backend/FileUtilsBase.js';
4
+ export { ImageRaw, InferenceSession };
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,YAAY,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAGvE,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@areb0s/ocr-common",
3
+ "description": "Fork of @gutenye/ocr-common with ImageBitmap support. Shared OCR library for Browser/Node based on PaddleOCR and ONNX runtime.",
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/areb0s/ocr.git",
10
+ "directory": "packages/common"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "bun": "./src/index.ts",
15
+ "react-native": "./src/index.ts",
16
+ "default": "./build/index.js"
17
+ },
18
+ "./splitIntoLineImages": {
19
+ "bun": "./src/backend/splitIntoLineImages.ts",
20
+ "react-native": "./src/backend/splitIntoLineImages.ts",
21
+ "default": "./build/backend/splitIntoLineImages.js"
22
+ }
23
+ },
24
+ "files": ["src", "build", "tsconfig.json", "!**/__tests__"],
25
+ "scripts": {
26
+ "build": "npx tsc --project tsconfig.build.json && npx tsc-alias --project tsconfig.build.json",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "dependencies": {
30
+ "tiny-invariant": "^1.3.3",
31
+ "@techstark/opencv-js": "^4.9.0-release.3",
32
+ "js-clipper": "^1.0.1"
33
+ }
34
+ }
package/src/Ocr.ts ADDED
@@ -0,0 +1,34 @@
1
+ import type { ImageRawData, BrowserImageInput, ModelCreateOptions } from '#common/types'
2
+ import { Detection, Recognition } from './models'
3
+
4
+ export class Ocr {
5
+ static async create(options: ModelCreateOptions = {}) {
6
+ const detection = await Detection.create(options)
7
+ const recognition = await Recognition.create(options)
8
+ return new Ocr({ detection, recognition })
9
+ }
10
+
11
+ #detection: Detection
12
+ #recognition: Recognition
13
+
14
+ constructor({
15
+ detection,
16
+ recognition,
17
+ }: {
18
+ detection: Detection
19
+ recognition: Recognition
20
+ }) {
21
+ this.#detection = detection
22
+ this.#recognition = recognition
23
+ }
24
+
25
+ async detect(image: string | ImageRawData | BrowserImageInput, options = {}) {
26
+ const { lineImages, resizedImageWidth, resizedImageHeight } = await this.#detection.run(image, options)
27
+ const texts = await this.#recognition.run(lineImages, options)
28
+ return {
29
+ texts,
30
+ resizedImageWidth,
31
+ resizedImageHeight,
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,5 @@
1
+ export class FileUtilsBase {
2
+ static async read(path: string): Promise<string> {
3
+ throw new Error('Not implemented')
4
+ }
5
+ }
@@ -0,0 +1,17 @@
1
+ import type { ImageRawData } from '#common/types'
2
+
3
+ export class ImageRawBase {
4
+ data: ImageRawData['data']
5
+ width: ImageRawData['width']
6
+ height: ImageRawData['height']
7
+
8
+ constructor({ data, width, height }: ImageRawData) {
9
+ this.data = data
10
+ this.width = width
11
+ this.height = height
12
+ }
13
+
14
+ getImageRawData(): ImageRawData {
15
+ return { data: this.data, width: this.width, height: this.height }
16
+ }
17
+ }
@@ -0,0 +1,29 @@
1
+ import type {
2
+ FileUtils as FileUtilsType,
3
+ ImageRaw as ImageRawType,
4
+ InferenceSession as InferenceSessionType,
5
+ ModelCreateOptions as ModelCreateOptionsType,
6
+ SplitIntoLineImages as SplitIntoLineImagesType,
7
+ } from '#common/types'
8
+
9
+ let FileUtils: FileUtilsType | any = undefined as unknown as FileUtilsType
10
+ let ImageRaw: ImageRawType | any = undefined as unknown as ImageRawType
11
+ let InferenceSession: InferenceSessionType | any = undefined as unknown as InferenceSessionType
12
+ let splitIntoLineImages: SplitIntoLineImagesType = undefined as unknown as SplitIntoLineImagesType
13
+ let defaultModels: ModelCreateOptionsType['models'] = undefined as unknown as ModelCreateOptionsType['models']
14
+
15
+ export function registerBackend(backend: {
16
+ FileUtils: FileUtilsType
17
+ ImageRaw: ImageRawType | any
18
+ InferenceSession: InferenceSessionType | any
19
+ splitIntoLineImages: SplitIntoLineImagesType
20
+ defaultModels: ModelCreateOptionsType['models']
21
+ }) {
22
+ FileUtils = backend.FileUtils
23
+ ImageRaw = backend.ImageRaw
24
+ InferenceSession = backend.InferenceSession
25
+ splitIntoLineImages = backend.splitIntoLineImages
26
+ defaultModels = backend.defaultModels
27
+ }
28
+
29
+ export { FileUtils, ImageRaw, InferenceSession, splitIntoLineImages, defaultModels }
@@ -0,0 +1,3 @@
1
+ export * from './backend'
2
+ export * from './FileUtilsBase'
3
+ export * from './ImageRawBase'