image-barcode-identifier 0.0.0-stage → 0.1.1
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 +123 -2
- package/dist/client.d.ts +13 -0
- package/dist/client.js +56 -0
- package/dist/client.js.map +1 -0
- package/dist/code128.d.ts +30 -0
- package/dist/code128.js +338 -0
- package/dist/code128.js.map +1 -0
- package/dist/cv.d.ts +8 -0
- package/dist/cv.js +38 -0
- package/dist/cv.js.map +1 -0
- package/dist/geometry.d.ts +46 -0
- package/dist/geometry.js +244 -0
- package/dist/geometry.js.map +1 -0
- package/dist/image.d.ts +10 -0
- package/dist/image.js +74 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/ops.d.ts +22 -0
- package/dist/ops.js +203 -0
- package/dist/ops.js.map +1 -0
- package/dist/pipeline.d.ts +4 -0
- package/dist/pipeline.js +234 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/protocol.d.ts +22 -0
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +24 -0
- package/dist/worker.js.map +1 -0
- package/dist/zxing.d.ts +16 -0
- package/dist/zxing.js +100 -0
- package/dist/zxing.js.map +1 -0
- package/dist/zxingWasm.generated.d.ts +1 -0
- package/dist/zxingWasm.generated.js +3 -0
- package/dist/zxingWasm.generated.js.map +1 -0
- package/package.json +49 -4
package/README.md
CHANGED
|
@@ -1,3 +1,124 @@
|
|
|
1
|
-
#
|
|
1
|
+
# image-barcode-identifier
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Reads barcodes from photos in the browser (or Node): you give it an image, it gives you the value.
|
|
4
|
+
|
|
5
|
+
It is built for difficult labels - blur, skew, perspective, uneven light, long thin Code 128 - and is tested against
|
|
6
|
+
photos of real labels. Everything ZXing reads works (Code 128/39/93, EAN/UPC, ITF, QR, DataMatrix, PDF417, Aztec, ...) plus a
|
|
7
|
+
tolerant, checksum-validated Code 128 decoder, barcode localisation, perspective rectification, tiles and a rotation sweep.
|
|
8
|
+
|
|
9
|
+
Nothing leaves the device. No server, no CDN: the ZXing WASM is embedded in the package.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install image-barcode-identifier
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Use
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { readBarcode } from 'image-barcode-identifier';
|
|
21
|
+
|
|
22
|
+
const value = await readBarcode(photo); // photo: File | Blob | ImageBitmap | <img> | <canvas> | ImageData | bytes
|
|
23
|
+
// "BCMSY03E38AA4FD00AA41", or null when there is no barcode
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Details (format, which stage found it, corner positions) and several barcodes per image:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { readBarcodes } from 'image-barcode-identifier';
|
|
30
|
+
|
|
31
|
+
const results = await readBarcodes(photo, { all: true, timeoutMs: 8000 });
|
|
32
|
+
// [{ text, format, strategy, position }] - [] when nothing was found
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Keep the UI responsive: use a Web Worker
|
|
36
|
+
|
|
37
|
+
Decoding is CPU heavy (a fraction of a second to a few seconds on a phone). On the main thread it freezes the
|
|
38
|
+
page, so in a UI run it in a worker. Two small steps:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
// barcode.worker.ts (a file in your app)
|
|
42
|
+
import 'image-barcode-identifier/worker';
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { createWorkerReader } from 'image-barcode-identifier/client';
|
|
47
|
+
|
|
48
|
+
const reader = createWorkerReader(new Worker(new URL('./barcode.worker.ts', import.meta.url), { type: 'module' }));
|
|
49
|
+
void reader.warmup(); // optional: load the engine in the background before the first photo
|
|
50
|
+
|
|
51
|
+
const value = await reader.readBarcode(photo, { timeoutMs: 8000 });
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`reader.terminate()` stops the worker and frees its memory (the engine uses a lot of it).
|
|
55
|
+
|
|
56
|
+
### Vite
|
|
57
|
+
|
|
58
|
+
Add this to `vite.config.ts`, otherwise `npm run dev` discovers the packages when you first read a barcode and reloads
|
|
59
|
+
the whole page (production builds are not affected):
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
export default defineConfig({
|
|
63
|
+
worker: { format: 'es' },
|
|
64
|
+
optimizeDeps: {
|
|
65
|
+
include: [
|
|
66
|
+
'image-barcode-identifier',
|
|
67
|
+
'image-barcode-identifier/client',
|
|
68
|
+
'image-barcode-identifier/worker',
|
|
69
|
+
'@techstark/opencv-js',
|
|
70
|
+
'zxing-wasm/reader',
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If you set `build.rollupOptions.output.manualChunks`, keep `@techstark/opencv-js` out of your eager vendor chunk.
|
|
77
|
+
It is ~13 MB (about 4 MB gzipped) and is only downloaded when the first image is read.
|
|
78
|
+
|
|
79
|
+
### Webpack / other bundlers
|
|
80
|
+
|
|
81
|
+
Anything that supports `new Worker(new URL('./x.js', import.meta.url))` and dynamic `import()` works (webpack 5,
|
|
82
|
+
Parcel, Rollup + plugins).
|
|
83
|
+
|
|
84
|
+
## Options
|
|
85
|
+
|
|
86
|
+
| option | default | meaning |
|
|
87
|
+
| ----------- | ------- | -------------------------------------------------------------------------------------------- |
|
|
88
|
+
| `all` | false | find every barcode instead of stopping at the first |
|
|
89
|
+
| `thorough` | false | run the rotation sweep even when something was found |
|
|
90
|
+
| `timeoutMs` | none | stop searching and return what was found so far (checked between attempts). Set one for a UI |
|
|
91
|
+
| `maxEdge` | 4096 | downscale so the longest edge is at most this. Normal phone photos are left untouched |
|
|
92
|
+
|
|
93
|
+
## Node
|
|
94
|
+
|
|
95
|
+
Node has no image decoder, so pass raw RGBA pixels (from `sharp`, `pngjs`, `jpeg-js`, ...):
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { readBarcode } from 'image-barcode-identifier';
|
|
99
|
+
const value = await readBarcode({ data: rgba, width, height });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Notes
|
|
103
|
+
|
|
104
|
+
- Results for a given image can depend on its resolution. Prefer sending the full-resolution photo to downscaling it.
|
|
105
|
+
- A checksum-valid Code 128 read of a very blurry label can still be wrong; the reader keeps the lowest-error candidate
|
|
106
|
+
across several row bands, strips and widths, which fixed every misread seen so far. Validate values against your own
|
|
107
|
+
format (for example a fixed prefix and length) if a wrong read would be costly.
|
|
108
|
+
- `zxing-wasm` and `@techstark/opencv-js` are pinned to exact versions on purpose: the embedded WASM binary must match
|
|
109
|
+
the JS that loads it.
|
|
110
|
+
|
|
111
|
+
## Develop
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm install
|
|
115
|
+
npm test # reference barcode images + two real label photos, in Node
|
|
116
|
+
npm run build # embeds the wasm, compiles to dist/
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Publish
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npm login
|
|
123
|
+
npm publish # prepublishOnly runs the typecheck, build and tests first
|
|
124
|
+
```
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BarcodeResult, ImageInput, ReadOptions } from './types.js';
|
|
2
|
+
export type { BarcodeResult, ImageInput, Point, RawImage, ReadOptions } from './types.js';
|
|
3
|
+
export interface WorkerReader {
|
|
4
|
+
/** Resolves with [] when nothing was found; rejects when decoding itself failed. */
|
|
5
|
+
readBarcodes(image: ImageInput, options?: ReadOptions): Promise<BarcodeResult[]>;
|
|
6
|
+
/** The value of the first barcode found, or `null`. */
|
|
7
|
+
readBarcode(image: ImageInput, options?: ReadOptions): Promise<string | null>;
|
|
8
|
+
/** Start loading OpenCV + ZXing in the worker so the first read is fast. */
|
|
9
|
+
warmup(): Promise<void>;
|
|
10
|
+
/** Terminate the worker (frees its memory) and reject everything in flight. */
|
|
11
|
+
terminate(): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createWorkerReader(worker: Worker): WorkerReader;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export function createWorkerReader(worker) {
|
|
2
|
+
let nextId = 1;
|
|
3
|
+
const pending = new Map();
|
|
4
|
+
worker.onmessage = ({ data }) => {
|
|
5
|
+
const entry = pending.get(data.id);
|
|
6
|
+
if (!entry)
|
|
7
|
+
return;
|
|
8
|
+
pending.delete(data.id);
|
|
9
|
+
if (data.type === 'error')
|
|
10
|
+
entry.reject(new Error(data.message));
|
|
11
|
+
else
|
|
12
|
+
entry.resolve(data);
|
|
13
|
+
};
|
|
14
|
+
worker.onerror = (event) => {
|
|
15
|
+
const error = new Error(event.message || 'Barcode worker failed to load');
|
|
16
|
+
for (const entry of pending.values())
|
|
17
|
+
entry.reject(error);
|
|
18
|
+
pending.clear();
|
|
19
|
+
};
|
|
20
|
+
const send = (request, transfer = []) => new Promise((resolve, reject) => {
|
|
21
|
+
pending.set(request.id, { resolve, reject });
|
|
22
|
+
worker.postMessage(request, transfer);
|
|
23
|
+
});
|
|
24
|
+
// Canvases and <img> elements can't be posted to a worker; bitmaps can, and are transferred (no copy).
|
|
25
|
+
const postable = async (image) => {
|
|
26
|
+
const isElement = (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
|
|
27
|
+
(typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
|
|
28
|
+
(typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas);
|
|
29
|
+
const value = isElement ? await createImageBitmap(image) : image;
|
|
30
|
+
const transfer = typeof ImageBitmap !== 'undefined' && value instanceof ImageBitmap ? [value] : [];
|
|
31
|
+
return { image: value, transfer };
|
|
32
|
+
};
|
|
33
|
+
const readBarcodes = async (image, options) => {
|
|
34
|
+
const { image: value, transfer } = await postable(image);
|
|
35
|
+
const res = await send({ id: nextId++, type: 'read', image: value, options }, transfer);
|
|
36
|
+
return res.type === 'read' ? res.results : [];
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
readBarcodes,
|
|
40
|
+
async readBarcode(image, options) {
|
|
41
|
+
const [first] = await readBarcodes(image, { ...options, all: false });
|
|
42
|
+
return first ? first.text : null;
|
|
43
|
+
},
|
|
44
|
+
async warmup() {
|
|
45
|
+
await send({ id: nextId++, type: 'warmup' });
|
|
46
|
+
},
|
|
47
|
+
terminate() {
|
|
48
|
+
worker.terminate();
|
|
49
|
+
const error = new Error('Barcode worker terminated');
|
|
50
|
+
for (const entry of pending.values())
|
|
51
|
+
entry.reject(error);
|
|
52
|
+
pending.clear();
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Gray } from './ops.js';
|
|
2
|
+
/** A decode with at most this mean error is trusted without checking the remaining row bands. */
|
|
3
|
+
export declare const CONFIDENT_ERROR = 0.04;
|
|
4
|
+
/**
|
|
5
|
+
* A checksum-valid decode with a larger mean error is rejected outright: correct reads of very blurry photos
|
|
6
|
+
* measured up to about 0.10, while misreads of a wrong region or heavy blur measured 0.125 and more. Returning
|
|
7
|
+
* nothing is better than returning a wrong barcode value.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MAX_ERROR = 0.11;
|
|
10
|
+
export interface Decoded {
|
|
11
|
+
text: string;
|
|
12
|
+
/** Mean per-module squared error (lower is better). */
|
|
13
|
+
error: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decode a Code 128 barcode from a 1D intensity profile (dark bars on light ground, left-to-right).
|
|
17
|
+
* Returns the best checksum-valid decode or null.
|
|
18
|
+
*/
|
|
19
|
+
export declare function decodeProfile(profile: Float64Array): Decoded | null;
|
|
20
|
+
/**
|
|
21
|
+
* strip: grayscale image of an upright barcode (bars vertical), with quiet zones. Tries several row bands and
|
|
22
|
+
* both reading directions.
|
|
23
|
+
*
|
|
24
|
+
* The checksum alone is a weak check (about 1 in 103 random misreads passes it) and different row bands of the
|
|
25
|
+
* same strip can disagree: on real photos a band over a smudge or the caption can produce a checksum-valid but
|
|
26
|
+
* wrong text. The match error tells them apart (correct decodes measured 0.03-0.05, wrong ones 0.07-0.09), so
|
|
27
|
+
* the lowest-error decode over all bands wins. Bands are only skipped once a decode is confident
|
|
28
|
+
* (error <= CONFIDENT_ERROR).
|
|
29
|
+
*/
|
|
30
|
+
export declare function decodeRectified(strip: Gray): Decoded | null;
|
package/dist/code128.js
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
const CODE128_PATTERNS = [
|
|
2
|
+
'11011001100', '11001101100', '11001100110', '10010011000', '10010001100', '10001001100',
|
|
3
|
+
'10011001000', '10011000100', '10001100100', '11001001000', '11001000100', '11000100100',
|
|
4
|
+
'10110011100', '10011011100', '10011001110', '10111001100', '10011101100', '10011100110',
|
|
5
|
+
'11001110010', '11001011100', '11001001110', '11011100100', '11001110100', '11101101110',
|
|
6
|
+
'11101001100', '11100101100', '11100100110', '11101100100', '11100110100', '11100110010',
|
|
7
|
+
'11011011000', '11011000110', '11000110110', '10100011000', '10001011000', '10001000110',
|
|
8
|
+
'10110001000', '10001101000', '10001100010', '11010001000', '11000101000', '11000100010',
|
|
9
|
+
'10110111000', '10110001110', '10001101110', '10111011000', '10111000110', '10001110110',
|
|
10
|
+
'11101110110', '11010001110', '11000101110', '11011101000', '11011100010', '11011101110',
|
|
11
|
+
'11101011000', '11101000110', '11100010110', '11101101000', '11101100010', '11100011010',
|
|
12
|
+
'11101111010', '11001000010', '11110001010', '10100110000', '10100001100', '10010110000',
|
|
13
|
+
'10010000110', '10000101100', '10000100110', '10110010000', '10110000100', '10011010000',
|
|
14
|
+
'10011000010', '10000110100', '10000110010', '11000010010', '11001010000', '11110111010',
|
|
15
|
+
'11000010100', '10001111010', '10100111100', '10010111100', '10010011110', '10111100100',
|
|
16
|
+
'10011110100', '10011110010', '11110100100', '11110010100', '11110010010', '11011011110',
|
|
17
|
+
'11011110110', '11110110110', '10101111000', '10100011110', '10001011110', '10111101000',
|
|
18
|
+
'10111100010', '11110101000', '11110100010', '10111011110', '10111101110', '11101011110',
|
|
19
|
+
'11110101110', '11010000100', '11010010000', '11010011100',
|
|
20
|
+
];
|
|
21
|
+
const STOP_PATTERN = '1100011101011'; // 13 modules incl. final termination bar
|
|
22
|
+
const P = new Float64Array(CODE128_PATTERNS.length * 11); // (106, 11) flattened
|
|
23
|
+
CODE128_PATTERNS.forEach((p, v) => {
|
|
24
|
+
for (let i = 0; i < 11; i++)
|
|
25
|
+
P[v * 11 + i] = p.charCodeAt(i) - 48;
|
|
26
|
+
});
|
|
27
|
+
const STOP = Float64Array.from(STOP_PATTERN, (c) => c.charCodeAt(0) - 48);
|
|
28
|
+
const N_PATTERNS = CODE128_PATTERNS.length;
|
|
29
|
+
const START_A = 103;
|
|
30
|
+
const START_B = 104;
|
|
31
|
+
const START_C = 105;
|
|
32
|
+
/** A decode with at most this mean error is trusted without checking the remaining row bands. */
|
|
33
|
+
export const CONFIDENT_ERROR = 0.04;
|
|
34
|
+
/**
|
|
35
|
+
* A checksum-valid decode with a larger mean error is rejected outright: correct reads of very blurry photos
|
|
36
|
+
* measured up to about 0.10, while misreads of a wrong region or heavy blur measured 0.125 and more. Returning
|
|
37
|
+
* nothing is better than returning a wrong barcode value.
|
|
38
|
+
*/
|
|
39
|
+
export const MAX_ERROR = 0.11;
|
|
40
|
+
/** values: start, data... (without checksum). */
|
|
41
|
+
function translate(values) {
|
|
42
|
+
let mode = values[0] === START_A ? 'A' : values[0] === START_B ? 'B' : 'C';
|
|
43
|
+
let out = '';
|
|
44
|
+
let shiftOnce = false;
|
|
45
|
+
for (let k = 1; k < values.length; k++) {
|
|
46
|
+
const v = values[k];
|
|
47
|
+
let cur = mode;
|
|
48
|
+
if (shiftOnce) {
|
|
49
|
+
cur = mode === 'A' ? 'B' : 'A';
|
|
50
|
+
shiftOnce = false;
|
|
51
|
+
}
|
|
52
|
+
if (cur === 'C') {
|
|
53
|
+
if (v < 100)
|
|
54
|
+
out += String(v).padStart(2, '0');
|
|
55
|
+
else if (v === 100)
|
|
56
|
+
mode = 'B';
|
|
57
|
+
else if (v === 101)
|
|
58
|
+
mode = 'A';
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (v < 96) {
|
|
62
|
+
if (cur === 'A')
|
|
63
|
+
out += String.fromCharCode(v < 64 ? 32 + v : v - 64);
|
|
64
|
+
else
|
|
65
|
+
out += String.fromCharCode(32 + v);
|
|
66
|
+
}
|
|
67
|
+
else if (v === 98)
|
|
68
|
+
shiftOnce = true;
|
|
69
|
+
else if (v === 99)
|
|
70
|
+
mode = 'C';
|
|
71
|
+
else if (v === 100 && cur === 'A')
|
|
72
|
+
mode = 'B';
|
|
73
|
+
else if (v === 101 && cur === 'B')
|
|
74
|
+
mode = 'A';
|
|
75
|
+
// FNC1-4 are ignored
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function sampler(darkness) {
|
|
80
|
+
const n = darkness.length;
|
|
81
|
+
const cum = new Float64Array(n + 1);
|
|
82
|
+
for (let i = 0; i < n; i++)
|
|
83
|
+
cum[i + 1] = cum[i] + darkness[i];
|
|
84
|
+
const interp = (x) => {
|
|
85
|
+
const i = Math.floor(x);
|
|
86
|
+
return i >= n ? cum[n] : cum[i] + (x - i) * darkness[i];
|
|
87
|
+
};
|
|
88
|
+
return (a, b) => {
|
|
89
|
+
a = Math.min(Math.max(a, 0), n);
|
|
90
|
+
b = Math.min(Math.max(b, 0), n);
|
|
91
|
+
return (interp(b) - interp(a)) / Math.max(b - a, 1e-6);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function linspace(a, b, n) {
|
|
95
|
+
return Array.from({ length: n }, (_, i) => a + ((b - a) * i) / (n - 1));
|
|
96
|
+
}
|
|
97
|
+
/** Decode `nChars` symbol characters (start..checksum) followed by the stop pattern. */
|
|
98
|
+
function tryDecode(avg, start, m, nChars) {
|
|
99
|
+
const shifts = linspace(-0.45 * m, 0.45 * m, 10);
|
|
100
|
+
const samples = new Float64Array(11);
|
|
101
|
+
let pos = start;
|
|
102
|
+
const values = [];
|
|
103
|
+
let totalErr = 0;
|
|
104
|
+
for (let c = 0; c < nChars; c++) {
|
|
105
|
+
let bestErr = Infinity;
|
|
106
|
+
let bestS = 0;
|
|
107
|
+
let bestV = 0;
|
|
108
|
+
for (let s = 0; s < shifts.length; s++) {
|
|
109
|
+
for (let i = 0; i < 11; i++) {
|
|
110
|
+
const center = pos + shifts[s] + (i + 0.5) * m;
|
|
111
|
+
samples[i] = avg(center - 0.3 * m, center + 0.3 * m);
|
|
112
|
+
}
|
|
113
|
+
for (let v = 0; v < N_PATTERNS; v++) {
|
|
114
|
+
let err = 0;
|
|
115
|
+
for (let i = 0; i < 11; i++) {
|
|
116
|
+
const d = samples[i] - P[v * 11 + i];
|
|
117
|
+
err += d * d;
|
|
118
|
+
}
|
|
119
|
+
if (err < bestErr) {
|
|
120
|
+
bestErr = err;
|
|
121
|
+
bestS = s;
|
|
122
|
+
bestV = v;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const e = bestErr / 11;
|
|
127
|
+
if (e > 0.2)
|
|
128
|
+
return null;
|
|
129
|
+
if (c === 0 && bestV !== START_A && bestV !== START_B && bestV !== START_C)
|
|
130
|
+
return null;
|
|
131
|
+
totalErr += e;
|
|
132
|
+
values.push(bestV);
|
|
133
|
+
pos += shifts[bestS] + 11 * m;
|
|
134
|
+
}
|
|
135
|
+
// stop pattern
|
|
136
|
+
let stopErr = Infinity;
|
|
137
|
+
const stopSamples = new Float64Array(13);
|
|
138
|
+
for (const shift of shifts) {
|
|
139
|
+
for (let i = 0; i < 13; i++) {
|
|
140
|
+
const center = pos + shift + (i + 0.5) * m;
|
|
141
|
+
stopSamples[i] = avg(center - 0.3 * m, center + 0.3 * m);
|
|
142
|
+
}
|
|
143
|
+
let err = 0;
|
|
144
|
+
for (let i = 0; i < 13; i++) {
|
|
145
|
+
const d = stopSamples[i] - STOP[i];
|
|
146
|
+
err += d * d;
|
|
147
|
+
}
|
|
148
|
+
if (err < stopErr)
|
|
149
|
+
stopErr = err;
|
|
150
|
+
}
|
|
151
|
+
if (stopErr / 13 > 0.2)
|
|
152
|
+
return null;
|
|
153
|
+
// checksum
|
|
154
|
+
const data = values.slice(0, -1);
|
|
155
|
+
const check = values[values.length - 1];
|
|
156
|
+
let sum = data[0];
|
|
157
|
+
for (let i = 1; i < data.length; i++)
|
|
158
|
+
sum += i * data[i];
|
|
159
|
+
if (sum % 103 !== check)
|
|
160
|
+
return null;
|
|
161
|
+
const text = translate(data);
|
|
162
|
+
if (!text)
|
|
163
|
+
return null;
|
|
164
|
+
return { text, error: totalErr / nChars };
|
|
165
|
+
}
|
|
166
|
+
/** Cheap prefilter: does the first 11 modules look like a Start A/B/C pattern? */
|
|
167
|
+
function startCharOk(avg, start, m) {
|
|
168
|
+
const shifts = linspace(-0.45 * m, 0.45 * m, 7);
|
|
169
|
+
const samples = new Float64Array(11);
|
|
170
|
+
for (const shift of shifts) {
|
|
171
|
+
for (let i = 0; i < 11; i++) {
|
|
172
|
+
const center = start + shift + (i + 0.5) * m;
|
|
173
|
+
samples[i] = avg(center - 0.3 * m, center + 0.3 * m);
|
|
174
|
+
}
|
|
175
|
+
for (let v = START_A; v <= START_C; v++) {
|
|
176
|
+
let err = 0;
|
|
177
|
+
for (let i = 0; i < 11; i++) {
|
|
178
|
+
const d = samples[i] - P[v * 11 + i];
|
|
179
|
+
err += d * d;
|
|
180
|
+
}
|
|
181
|
+
if (err / 11 < 0.25)
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
function percentile(values, q) {
|
|
188
|
+
const sorted = Float64Array.from(values).sort();
|
|
189
|
+
const idx = (q / 100) * (sorted.length - 1);
|
|
190
|
+
const lo = Math.floor(idx);
|
|
191
|
+
const hi = Math.min(lo + 1, sorted.length - 1);
|
|
192
|
+
return sorted[lo] + (sorted[hi] - sorted[lo]) * (idx - lo);
|
|
193
|
+
}
|
|
194
|
+
/** Sliding max/min over a window of width k (odd), window truncated at the borders. */
|
|
195
|
+
function slidingExtreme(row, k, pickMax) {
|
|
196
|
+
const n = row.length;
|
|
197
|
+
const r = k >> 1;
|
|
198
|
+
const out = new Float64Array(n);
|
|
199
|
+
for (let i = 0; i < n; i++) {
|
|
200
|
+
let best = row[i];
|
|
201
|
+
for (let j = Math.max(0, i - r); j <= Math.min(n - 1, i + r); j++) {
|
|
202
|
+
if (pickMax ? row[j] > best : row[j] < best)
|
|
203
|
+
best = row[j];
|
|
204
|
+
}
|
|
205
|
+
out[i] = best;
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
/** Normalised box blur with BORDER_REFLECT_101 (like cv2.blur on a single row). */
|
|
210
|
+
function boxBlur(row, k) {
|
|
211
|
+
const n = row.length;
|
|
212
|
+
const r = k >> 1;
|
|
213
|
+
const reflect = (i) => {
|
|
214
|
+
if (n === 1)
|
|
215
|
+
return 0;
|
|
216
|
+
while (i < 0 || i >= n)
|
|
217
|
+
i = i < 0 ? -i : 2 * (n - 1) - i;
|
|
218
|
+
return i;
|
|
219
|
+
};
|
|
220
|
+
const out = new Float64Array(n);
|
|
221
|
+
let acc = 0;
|
|
222
|
+
for (let j = -r; j <= r; j++)
|
|
223
|
+
acc += row[reflect(j)];
|
|
224
|
+
out[0] = acc / k;
|
|
225
|
+
for (let i = 1; i < n; i++) {
|
|
226
|
+
acc += row[reflect(i + r)] - row[reflect(i - 1 - r)];
|
|
227
|
+
out[i] = acc / k;
|
|
228
|
+
}
|
|
229
|
+
return out;
|
|
230
|
+
}
|
|
231
|
+
const clip01 = (x) => (x < 0 ? 0 : x > 1 ? 1 : x);
|
|
232
|
+
/** 0..1 darkness: one with global normalisation, one with local (uneven lighting). */
|
|
233
|
+
function* darknessMaps(p) {
|
|
234
|
+
const n = p.length;
|
|
235
|
+
const lo = percentile(p, 2);
|
|
236
|
+
const hi = percentile(p, 98);
|
|
237
|
+
if (hi - lo >= 25) {
|
|
238
|
+
const out = new Float64Array(n);
|
|
239
|
+
for (let i = 0; i < n; i++)
|
|
240
|
+
out[i] = clip01((hi - p[i]) / (hi - lo));
|
|
241
|
+
yield out;
|
|
242
|
+
}
|
|
243
|
+
const k = Math.max(31, Math.floor(n / 6) | 1);
|
|
244
|
+
const mx = boxBlur(slidingExtreme(p, k, true), k);
|
|
245
|
+
const mn = boxBlur(slidingExtreme(p, k, false), k);
|
|
246
|
+
const out = new Float64Array(n);
|
|
247
|
+
for (let i = 0; i < n; i++)
|
|
248
|
+
out[i] = clip01((mx[i] - p[i]) / Math.max(mx[i] - mn[i], 25));
|
|
249
|
+
yield out;
|
|
250
|
+
}
|
|
251
|
+
function decodeDark(dark) {
|
|
252
|
+
let count = 0;
|
|
253
|
+
let first = -1;
|
|
254
|
+
let last = -1;
|
|
255
|
+
for (let i = 0; i < dark.length; i++) {
|
|
256
|
+
if (dark[i] > 0.5) {
|
|
257
|
+
count++;
|
|
258
|
+
if (first < 0)
|
|
259
|
+
first = i;
|
|
260
|
+
last = i;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (count < 50)
|
|
264
|
+
return null;
|
|
265
|
+
const start = first;
|
|
266
|
+
const width = last + 1 - first;
|
|
267
|
+
const avg = sampler(dark);
|
|
268
|
+
let best = null;
|
|
269
|
+
for (let nChars = 3; nChars < 80; nChars++) {
|
|
270
|
+
// start + data + checksum
|
|
271
|
+
const m = width / (11 * nChars + 13);
|
|
272
|
+
if (m < 1.2)
|
|
273
|
+
break;
|
|
274
|
+
if (!startCharOk(avg, start, m))
|
|
275
|
+
continue;
|
|
276
|
+
for (const dm of [1.0, 0.99, 1.01, 0.98, 1.02]) {
|
|
277
|
+
for (const ds of [0.0, -0.3 * m, 0.3 * m]) {
|
|
278
|
+
const res = tryDecode(avg, start + ds, m * dm, nChars);
|
|
279
|
+
if (res && (best === null || res.error < best.error))
|
|
280
|
+
best = res;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (best)
|
|
284
|
+
return best;
|
|
285
|
+
}
|
|
286
|
+
return best;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Decode a Code 128 barcode from a 1D intensity profile (dark bars on light ground, left-to-right).
|
|
290
|
+
* Returns the best checksum-valid decode or null.
|
|
291
|
+
*/
|
|
292
|
+
export function decodeProfile(profile) {
|
|
293
|
+
for (const dark of darknessMaps(profile)) {
|
|
294
|
+
const res = decodeDark(dark);
|
|
295
|
+
if (res)
|
|
296
|
+
return res;
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* strip: grayscale image of an upright barcode (bars vertical), with quiet zones. Tries several row bands and
|
|
302
|
+
* both reading directions.
|
|
303
|
+
*
|
|
304
|
+
* The checksum alone is a weak check (about 1 in 103 random misreads passes it) and different row bands of the
|
|
305
|
+
* same strip can disagree: on real photos a band over a smudge or the caption can produce a checksum-valid but
|
|
306
|
+
* wrong text. The match error tells them apart (correct decodes measured 0.03-0.05, wrong ones 0.07-0.09), so
|
|
307
|
+
* the lowest-error decode over all bands wins. Bands are only skipped once a decode is confident
|
|
308
|
+
* (error <= CONFIDENT_ERROR).
|
|
309
|
+
*/
|
|
310
|
+
export function decodeRectified(strip) {
|
|
311
|
+
const { width: w, height: h, data } = strip;
|
|
312
|
+
const bands = [[0.2, 0.8], [0.1, 0.4], [0.3, 0.6], [0.5, 0.9], [0.0, 1.0]];
|
|
313
|
+
let best = null;
|
|
314
|
+
for (const [a, b] of bands) {
|
|
315
|
+
const r0 = Math.trunc(h * a);
|
|
316
|
+
const r1 = Math.max(Math.trunc(h * b), r0 + 1);
|
|
317
|
+
const profile = new Float64Array(w);
|
|
318
|
+
for (let y = r0; y < r1; y++) {
|
|
319
|
+
const row = y * w;
|
|
320
|
+
for (let x = 0; x < w; x++)
|
|
321
|
+
profile[x] += data[row + x];
|
|
322
|
+
}
|
|
323
|
+
for (let x = 0; x < w; x++)
|
|
324
|
+
profile[x] /= r1 - r0;
|
|
325
|
+
const reversed = Float64Array.from(profile).reverse();
|
|
326
|
+
const inverted = profile.map((v) => 255 - v);
|
|
327
|
+
const invertedReversed = reversed.map((v) => 255 - v);
|
|
328
|
+
for (const prof of [profile, reversed, inverted, invertedReversed]) {
|
|
329
|
+
const res = decodeProfile(prof);
|
|
330
|
+
if (res && (best === null || res.error < best.error))
|
|
331
|
+
best = res;
|
|
332
|
+
}
|
|
333
|
+
if (best && best.error <= CONFIDENT_ERROR)
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
return best;
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=code128.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code128.js","sourceRoot":"","sources":["../src/code128.ts"],"names":[],"mappings":"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"}
|
package/dist/cv.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function setOpencvLoader(loader: (() => Promise<unknown>) | undefined): void;
|
|
2
|
+
/** The loaded OpenCV.js module. Only valid after `loadCv()` resolved. */
|
|
3
|
+
export declare function getCv(): any;
|
|
4
|
+
/**
|
|
5
|
+
* Loads OpenCV.js once. The module is ~13 MB of JS with the WASM inlined, so it is imported lazily and only
|
|
6
|
+
* when the first image is processed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadCv(): Promise<void>;
|
package/dist/cv.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
let cvInstance;
|
|
3
|
+
let cvPromise;
|
|
4
|
+
let opencvLoader;
|
|
5
|
+
export function setOpencvLoader(loader) {
|
|
6
|
+
opencvLoader = loader;
|
|
7
|
+
}
|
|
8
|
+
/** The loaded OpenCV.js module. Only valid after `loadCv()` resolved. */
|
|
9
|
+
export function getCv() {
|
|
10
|
+
if (!cvInstance)
|
|
11
|
+
throw new Error('OpenCV is not loaded yet; await loadCv() first');
|
|
12
|
+
return cvInstance;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Loads OpenCV.js once. The module is ~13 MB of JS with the WASM inlined, so it is imported lazily and only
|
|
16
|
+
* when the first image is processed.
|
|
17
|
+
*/
|
|
18
|
+
export function loadCv() {
|
|
19
|
+
if (!cvPromise) {
|
|
20
|
+
cvPromise = (async () => {
|
|
21
|
+
const mod = await (opencvLoader ? opencvLoader() : import('@techstark/opencv-js'));
|
|
22
|
+
let cv = mod && mod.default ? mod.default : mod;
|
|
23
|
+
// Depending on the build, the export is a Promise, an already initialised module, or a module that
|
|
24
|
+
// signals readiness through a callback. Never return `cv` from this async function: the Emscripten
|
|
25
|
+
// module is a thenable and would be awaited recursively.
|
|
26
|
+
if (cv instanceof Promise)
|
|
27
|
+
cv = await cv;
|
|
28
|
+
else if (!cv.Mat)
|
|
29
|
+
await new Promise((resolve) => { cv.onRuntimeInitialized = () => resolve(); });
|
|
30
|
+
cvInstance = cv;
|
|
31
|
+
})();
|
|
32
|
+
cvPromise.catch(() => {
|
|
33
|
+
cvPromise = undefined; // a failed load (offline, blocked chunk) must not be cached
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return cvPromise;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=cv.js.map
|
package/dist/cv.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cv.js","sourceRoot":"","sources":["../src/cv.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,IAAI,UAAe,CAAC;AACpB,IAAI,SAAoC,CAAC;AACzC,IAAI,YAAkD,CAAC;AAEvD,MAAM,UAAU,eAAe,CAAC,MAA4C;IAC1E,YAAY,GAAG,MAAM,CAAC;AACxB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,KAAK;IACnB,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACnF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM;IACpB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,CAAC,KAAK,IAAI,EAAE;YACtB,MAAM,GAAG,GAAQ,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC;YACxF,IAAI,EAAE,GAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;YACrD,mGAAmG;YACnG,mGAAmG;YACnG,yDAAyD;YACzD,IAAI,EAAE,YAAY,OAAO;gBAAE,EAAE,GAAG,MAAM,EAAE,CAAC;iBACpC,IAAI,CAAC,EAAE,CAAC,GAAG;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,oBAAoB,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACvG,UAAU,GAAG,EAAE,CAAC;QAClB,CAAC,CAAC,EAAE,CAAC;QACL,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE;YACnB,SAAS,GAAG,SAAS,CAAC,CAAC,4DAA4D;QACrF,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|