ppu-ocv 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -59
- package/canvas-factory.js +1 -1
- package/canvas-processor.d.ts +18 -0
- package/canvas-processor.js +1 -0
- package/canvas-toolkit.base.d.ts +5 -2
- package/deskew.d.ts +68 -0
- package/deskew.js +1 -0
- package/image-processor.d.ts +0 -8
- package/image-processor.js +1 -1
- package/index.canvas-web.d.ts +6 -0
- package/index.canvas-web.js +1 -0
- package/index.canvas.d.ts +8 -0
- package/index.canvas.js +1 -0
- package/index.d.ts +3 -1
- package/index.js +1 -1
- package/index.web.d.ts +3 -1
- package/index.web.js +1 -1
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -32,6 +32,8 @@ OpenCV is powerful but can be cumbersome to use directly. This library provides:
|
|
|
32
32
|
3. **Development Speed**: Add image processing to your app in minutes, not hours
|
|
33
33
|
4. **Extensibility**: Custom operations for your specific needs without library modifications
|
|
34
34
|
5. **TypeScript Integration**: Full IntelliSense support with parameter validation
|
|
35
|
+
6. **Web Support**: Supports running directly in the browser
|
|
36
|
+
7. **Loosely Coupled**: Canvas utilities are fully decoupled from OpenCV. Usable in Browser Extensions, Service Workers, and other constrained environments where OpenCV cannot be initialised
|
|
35
37
|
|
|
36
38
|
## Installation
|
|
37
39
|
|
|
@@ -45,40 +47,43 @@ bun add ppu-ocv
|
|
|
45
47
|
|
|
46
48
|
## Usage (Node.js / Bun)
|
|
47
49
|
|
|
48
|
-
Note that
|
|
50
|
+
Note that operation order matters — you should have at least basic familiarity with OpenCV. See the operations table below.
|
|
49
51
|
|
|
50
52
|
```ts
|
|
51
|
-
import { ImageProcessor } from "ppu-ocv";
|
|
53
|
+
import { CanvasProcessor, ImageProcessor } from "ppu-ocv";
|
|
52
54
|
|
|
53
55
|
const file = Bun.file("./assets/receipt.jpg");
|
|
54
56
|
const image = await file.arrayBuffer();
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
await
|
|
58
|
+
await ImageProcessor.initRuntime(); // init opencv
|
|
59
|
+
const canvas = await CanvasProcessor.prepareCanvas(image);
|
|
58
60
|
|
|
59
61
|
const processor = new ImageProcessor(canvas);
|
|
60
|
-
processor
|
|
62
|
+
processor
|
|
63
|
+
.grayscale()
|
|
64
|
+
.blur({ size: [5, 5] })
|
|
65
|
+
.threshold();
|
|
61
66
|
|
|
62
67
|
const resultCanvas = processor.toCanvas();
|
|
63
68
|
processor.destroy();
|
|
64
69
|
```
|
|
65
70
|
|
|
66
|
-
Or
|
|
71
|
+
Or use the `execute` API directly:
|
|
67
72
|
|
|
68
73
|
```ts
|
|
69
|
-
import { CanvasToolkit, ImageProcessor, cv } from "ppu-ocv";
|
|
74
|
+
import { CanvasProcessor, CanvasToolkit, ImageProcessor, cv } from "ppu-ocv";
|
|
70
75
|
|
|
71
76
|
const file = Bun.file("./assets/receipt.jpg");
|
|
72
77
|
const image = await file.arrayBuffer();
|
|
73
78
|
|
|
74
79
|
const canvasToolkit = CanvasToolkit.getInstance();
|
|
75
|
-
const canvas = await ImageProcessor.prepareCanvas(image);
|
|
76
80
|
await ImageProcessor.initRuntime();
|
|
81
|
+
const canvas = await CanvasProcessor.prepareCanvas(image);
|
|
77
82
|
|
|
78
83
|
const processor = new ImageProcessor(canvas);
|
|
79
84
|
const grayscaleImg = processor.execute("grayscale").toCanvas();
|
|
80
85
|
|
|
81
|
-
//
|
|
86
|
+
// The pipeline continues from the grayscaled image
|
|
82
87
|
const thresholdImg = processor
|
|
83
88
|
.execute("blur")
|
|
84
89
|
.execute("threshold", {
|
|
@@ -95,25 +100,57 @@ await canvasToolkit.saveImage({
|
|
|
95
100
|
|
|
96
101
|
For more advanced usage, see: [Example usage of ppu-ocv](./examples)
|
|
97
102
|
|
|
103
|
+
## Canvas-only usage (no OpenCV)
|
|
104
|
+
|
|
105
|
+
Starting from v3.0.0, canvas utilities are fully decoupled from OpenCV. If you only need canvas I/O (e.g. loading/saving images, cropping, drawing) without any image processing, import from `ppu-ocv/canvas` (Node) or `ppu-ocv/canvas-web` (browser). OpenCV is **never imported or initialised** by these entry points, making them safe for use in Browser Extensions, Service Workers, and edge runtimes.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
// Node.js — zero OpenCV dependency
|
|
109
|
+
import { CanvasProcessor, CanvasToolkit } from "ppu-ocv/canvas";
|
|
110
|
+
|
|
111
|
+
const file = Bun.file("./assets/image.jpg");
|
|
112
|
+
const canvas = await CanvasProcessor.prepareCanvas(await file.arrayBuffer());
|
|
113
|
+
|
|
114
|
+
const toolkit = CanvasToolkit.getInstance();
|
|
115
|
+
const cropped = toolkit.crop({
|
|
116
|
+
canvas,
|
|
117
|
+
bbox: { x0: 0, y0: 0, x1: 100, y1: 100 },
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const buffer = await CanvasProcessor.prepareBuffer(cropped);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
// Browser Extension background script — zero OpenCV dependency
|
|
125
|
+
import { CanvasProcessor, CanvasToolkit } from "ppu-ocv/canvas-web";
|
|
126
|
+
|
|
127
|
+
const response = await fetch("/image.jpg");
|
|
128
|
+
const canvas = await CanvasProcessor.prepareCanvas(
|
|
129
|
+
await response.arrayBuffer(),
|
|
130
|
+
);
|
|
131
|
+
```
|
|
132
|
+
|
|
98
133
|
## Web / Browser Support
|
|
99
134
|
|
|
100
|
-
|
|
135
|
+
Import from `ppu-ocv/web` to use the browser-native canvas APIs (`HTMLCanvasElement` / `OffscreenCanvas`) instead of `@napi-rs/canvas`.
|
|
101
136
|
|
|
102
137
|
### With a bundler (Vite, webpack, etc.)
|
|
103
138
|
|
|
104
139
|
```ts
|
|
105
|
-
import { ImageProcessor, cv } from "ppu-ocv/web";
|
|
140
|
+
import { CanvasProcessor, ImageProcessor, cv } from "ppu-ocv/web";
|
|
106
141
|
|
|
107
142
|
await ImageProcessor.initRuntime();
|
|
108
143
|
|
|
109
|
-
// From a file input or fetch
|
|
110
144
|
const response = await fetch("/my-image.jpg");
|
|
111
145
|
const buffer = await response.arrayBuffer();
|
|
112
146
|
|
|
113
|
-
const canvas = await
|
|
147
|
+
const canvas = await CanvasProcessor.prepareCanvas(buffer);
|
|
114
148
|
const processor = new ImageProcessor(canvas);
|
|
115
149
|
|
|
116
|
-
processor
|
|
150
|
+
processor
|
|
151
|
+
.grayscale()
|
|
152
|
+
.blur({ size: [5, 5] })
|
|
153
|
+
.threshold();
|
|
117
154
|
|
|
118
155
|
const result = processor.toCanvas(); // returns HTMLCanvasElement
|
|
119
156
|
document.body.appendChild(result);
|
|
@@ -127,11 +164,22 @@ processor.destroy();
|
|
|
127
164
|
|
|
128
165
|
```html
|
|
129
166
|
<script type="module">
|
|
130
|
-
import {
|
|
167
|
+
import {
|
|
168
|
+
CanvasProcessor,
|
|
169
|
+
ImageProcessor,
|
|
170
|
+
} from "https://cdn.jsdelivr.net/npm/ppu-ocv@3/index.web.js";
|
|
131
171
|
await ImageProcessor.initRuntime();
|
|
132
172
|
|
|
173
|
+
const response = await fetch("/my-image.jpg");
|
|
174
|
+
const canvas = await CanvasProcessor.prepareCanvas(
|
|
175
|
+
await response.arrayBuffer(),
|
|
176
|
+
);
|
|
177
|
+
|
|
133
178
|
const processor = new ImageProcessor(canvas);
|
|
134
|
-
processor
|
|
179
|
+
processor
|
|
180
|
+
.grayscale()
|
|
181
|
+
.blur({ size: [5, 5] })
|
|
182
|
+
.threshold();
|
|
135
183
|
|
|
136
184
|
const result = processor.toCanvas();
|
|
137
185
|
processor.destroy();
|
|
@@ -142,28 +190,32 @@ processor.destroy();
|
|
|
142
190
|
|
|
143
191
|
See the [interactive demo](./index.html) for a full working example.
|
|
144
192
|
|
|
145
|
-
###
|
|
193
|
+
### Entry point reference
|
|
146
194
|
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
| `
|
|
151
|
-
|
|
|
152
|
-
| `
|
|
153
|
-
| `Contours` | ✅ | ✅ Same API |
|
|
154
|
-
| Image analysis | ✅ | ✅ Same API |
|
|
195
|
+
| Import path | OpenCV | Canvas backend | `CanvasToolkit` | Use case |
|
|
196
|
+
| -------------------- | ------ | ------------------------------------- | -------------------- | ------------------------------------------ |
|
|
197
|
+
| `ppu-ocv` | ✅ | `@napi-rs/canvas` | Full (with file I/O) | Full pipeline, Node.js / Bun |
|
|
198
|
+
| `ppu-ocv/web` | ✅ | `HTMLCanvasElement`/`OffscreenCanvas` | Base only | Full pipeline, browser |
|
|
199
|
+
| `ppu-ocv/canvas` | ❌ | `@napi-rs/canvas` | Full (with file I/O) | Canvas-only, Node (extensions, edge, etc.) |
|
|
200
|
+
| `ppu-ocv/canvas-web` | ❌ | `HTMLCanvasElement`/`OffscreenCanvas` | Base only | Canvas-only, browser extensions / SW |
|
|
155
201
|
|
|
156
202
|
### Platform abstraction
|
|
157
203
|
|
|
158
|
-
Under the hood, ppu-ocv uses a platform abstraction layer.
|
|
204
|
+
Under the hood, ppu-ocv uses a platform abstraction layer. Each entry point auto-registers its platform. You can also register a custom platform:
|
|
159
205
|
|
|
160
206
|
```ts
|
|
161
207
|
import { setPlatform, type CanvasPlatform } from "ppu-ocv/web";
|
|
162
208
|
|
|
163
209
|
const myPlatform: CanvasPlatform = {
|
|
164
|
-
createCanvas(width, height) {
|
|
165
|
-
|
|
166
|
-
|
|
210
|
+
createCanvas(width, height) {
|
|
211
|
+
/* ... */
|
|
212
|
+
},
|
|
213
|
+
loadImage(source) {
|
|
214
|
+
/* ... */
|
|
215
|
+
},
|
|
216
|
+
isCanvas(value) {
|
|
217
|
+
/* ... */
|
|
218
|
+
},
|
|
167
219
|
};
|
|
168
220
|
|
|
169
221
|
setPlatform(myPlatform);
|
|
@@ -191,23 +243,34 @@ To avoid bloat, we only ship essential operations for chaining. Currently shippe
|
|
|
191
243
|
|
|
192
244
|
## Extending operations
|
|
193
245
|
|
|
194
|
-
You can easily add your own by creating a prototype method or
|
|
246
|
+
You can easily add your own by creating a prototype method or extending the `ImageProcessor` class.
|
|
195
247
|
|
|
196
248
|
See: [How to extend ppu-ocv operations](./docs/how-to-extend-ppu-ocv-operations.md)
|
|
197
249
|
|
|
198
250
|
## Class documentation
|
|
199
251
|
|
|
252
|
+
#### `CanvasProcessor`
|
|
253
|
+
|
|
254
|
+
Canvas I/O utilities with **no OpenCV dependency**. Available from all entry points including `ppu-ocv/canvas` and `ppu-ocv/canvas-web`.
|
|
255
|
+
|
|
256
|
+
| Method | Args | Description |
|
|
257
|
+
| ---------------------- | ----------- | ----------------------------------------------------- |
|
|
258
|
+
| static `prepareCanvas` | ArrayBuffer | Load image bytes into a `CanvasLike` |
|
|
259
|
+
| static `prepareBuffer` | CanvasLike | Export a `CanvasLike` to an `ArrayBuffer` (PNG bytes) |
|
|
260
|
+
|
|
200
261
|
#### `ImageProcessor`
|
|
201
262
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
|
210
|
-
| `
|
|
263
|
+
Requires OpenCV. Available from `ppu-ocv` and `ppu-ocv/web`.
|
|
264
|
+
|
|
265
|
+
| Method | Args | Description |
|
|
266
|
+
| -------------------- | ---------------- | ------------------------------------------------------------------ |
|
|
267
|
+
| constructor | cv.Mat or Canvas | Instantiate processor with initial image |
|
|
268
|
+
| static `initRuntime` | | OpenCV runtime initialization — required once per runtime |
|
|
269
|
+
| operations | depends | Chainable operations like `blur`, `grayscale`, `resize`, and so on |
|
|
270
|
+
| `execute` | name, options | Chainable operations via the `execute` API |
|
|
271
|
+
| `toMat` | | Return the current image as a `cv.Mat` |
|
|
272
|
+
| `toCanvas` | | Return the current image as a `CanvasLike` |
|
|
273
|
+
| `destroy` | | Clean up `cv.Mat` memory |
|
|
211
274
|
|
|
212
275
|
#### `CanvasToolkit`
|
|
213
276
|
|
|
@@ -215,31 +278,41 @@ See: [How to extend ppu-ocv operations](./docs/how-to-extend-ppu-ocv-operations.
|
|
|
215
278
|
| ------------- | ---------------------- | ----------------------------------------------------------------------------------------- |
|
|
216
279
|
| `crop` | BoundingBox, Canvas | Crop a part of source canvas and return a new canvas of the cropped part |
|
|
217
280
|
| `isDirty` | Canvas, threshold | Check whether a binary canvas is dirty (full of major color either black or white) or not |
|
|
218
|
-
| `saveImage` | Canvas, filename, path | Save a canvas to an image file
|
|
219
|
-
| `clearOutput` | path | Clear the output folder
|
|
281
|
+
| `saveImage` | Canvas, filename, path | Save a canvas to an image file _(Node only)_ |
|
|
282
|
+
| `clearOutput` | path | Clear the output folder _(Node only)_ |
|
|
220
283
|
| `drawLine` | ctx, coordinate, style | Draw a non-filled rectangle outline on the canvas |
|
|
221
|
-
| `drawContour` | ctx, contour, style | Draw a contour on the canvas
|
|
284
|
+
| `drawContour` | ctx, contour, style | Draw a contour on the canvas — accepts any `ContourLike` (`{ data32S }`) |
|
|
285
|
+
|
|
286
|
+
#### `DeskewService`
|
|
287
|
+
|
|
288
|
+
Detects and corrects text skew in document images using a multi-method consensus approach (minAreaRect, baseline analysis, Hough transform). Requires OpenCV. Available from `ppu-ocv` and `ppu-ocv/web`.
|
|
289
|
+
|
|
290
|
+
| Method | Args | Description |
|
|
291
|
+
| -------------------- | ------------- | ------------------------------------ |
|
|
292
|
+
| constructor | DeskewOptions | `verbose`, `minimumAreaThreshold` |
|
|
293
|
+
| `calculateSkewAngle` | CanvasLike | Detect skew angle in degrees |
|
|
294
|
+
| `deskewImage` | CanvasLike | Return a deskewed copy of the canvas |
|
|
222
295
|
|
|
223
296
|
#### `Contours`
|
|
224
297
|
|
|
225
|
-
| Method
|
|
226
|
-
|
|
|
227
|
-
| constructor
|
|
228
|
-
| `getAll`
|
|
229
|
-
| `getFromIndex`
|
|
230
|
-
| `getRect`
|
|
231
|
-
| `iterate`
|
|
232
|
-
| `getLargestContourArea`
|
|
233
|
-
| `getCornerPoints`
|
|
234
|
-
| `
|
|
298
|
+
| Method | Args | Description |
|
|
299
|
+
| -------------------------------- | --------------- | ---------------------------------------------------------------- |
|
|
300
|
+
| constructor | cv.Mat, options | Instantiate Contours and automatically find & store contour list |
|
|
301
|
+
| `getAll` | | Return the full `cv.MatVector` of contours |
|
|
302
|
+
| `getFromIndex` | index | Get contour at a specific index |
|
|
303
|
+
| `getRect` | contour | Get the bounding rectangle of a contour |
|
|
304
|
+
| `iterate` | callback | Iterate over all contours |
|
|
305
|
+
| `getLargestContourArea` | | Return the contour with the largest area |
|
|
306
|
+
| `getCornerPoints` | options | Get four corner points for perspective transformation (warp) |
|
|
307
|
+
| `getApproximateRectangleContour` | options | Simplify a contour to an approximate rectangle |
|
|
308
|
+
| `destroy` | | Destroy and clean up contour memory |
|
|
235
309
|
|
|
236
310
|
#### `ImageAnalysis`
|
|
237
311
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
- `calculateMeanNormalizedLabLightness`: Calculates the mean normalized lightness of an image using the L channel of the Lab color space. Lightness is normalized based on the image's own maximum lightness value before averaging.
|
|
312
|
+
A collection of utility functions for analyzing image properties (requires OpenCV).
|
|
241
313
|
|
|
242
|
-
- `
|
|
314
|
+
- `calculateMeanNormalizedLabLightness`: Calculates the mean normalized lightness of an image using the L channel of the Lab color space.
|
|
315
|
+
- `calculateMeanGrayscaleValue`: Calculates the mean pixel value after converting to grayscale.
|
|
243
316
|
|
|
244
317
|
## Contributing
|
|
245
318
|
|
|
@@ -262,12 +335,10 @@ Ensure that all tests pass before submitting your pull request.
|
|
|
262
335
|
|
|
263
336
|
## Scripts
|
|
264
337
|
|
|
265
|
-
Recommended development environment is in
|
|
338
|
+
Recommended development environment is in a Linux-based environment.
|
|
266
339
|
|
|
267
340
|
Library template: https://github.com/aquapi/lib-template
|
|
268
341
|
|
|
269
|
-
All script sources and usage.
|
|
270
|
-
|
|
271
342
|
### [Build](./scripts/build.ts)
|
|
272
343
|
|
|
273
344
|
Emit `.js` and `.d.ts` files to [`lib`](./lib).
|
|
@@ -276,6 +347,20 @@ Emit `.js` and `.d.ts` files to [`lib`](./lib).
|
|
|
276
347
|
|
|
277
348
|
Move [`package.json`](./package.json), [`README.md`](./README.md) to [`lib`](./lib) and publish the package.
|
|
278
349
|
|
|
350
|
+
## Migrating from v2
|
|
351
|
+
|
|
352
|
+
See [MIGRATION.md](./MIGRATION.md) for a full guide. The short version:
|
|
353
|
+
|
|
354
|
+
```diff
|
|
355
|
+
- import { ImageProcessor } from "ppu-ocv";
|
|
356
|
+
- const canvas = await ImageProcessor.prepareCanvas(buffer);
|
|
357
|
+
- const buf = await ImageProcessor.prepareBuffer(canvas);
|
|
358
|
+
|
|
359
|
+
+ import { CanvasProcessor } from "ppu-ocv";
|
|
360
|
+
+ const canvas = await CanvasProcessor.prepareCanvas(buffer);
|
|
361
|
+
+ const buf = await CanvasProcessor.prepareBuffer(canvas);
|
|
362
|
+
```
|
|
363
|
+
|
|
279
364
|
## License
|
|
280
365
|
|
|
281
366
|
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
package/canvas-factory.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let _platform=null;export function setPlatform(platform){_platform=platform}export function getPlatform(){if(!_platform){throw new Error("No canvas platform registered. "+'Import "ppu-ocv" (Node) or "ppu-ocv/web" (browser) to auto-register.')}return _platform}
|
|
1
|
+
let _platform=null;export function setPlatform(platform){_platform=platform}export function getPlatform(){if(!_platform){throw new Error("No canvas platform registered. "+'Import "ppu-ocv" (Node), "ppu-ocv/web" (browser), '+'"ppu-ocv/canvas" (Node canvas-only), or "ppu-ocv/canvas-web" (browser canvas-only) to auto-register.')}return _platform}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CanvasLike } from "./canvas-factory.js";
|
|
2
|
+
/**
|
|
3
|
+
* Canvas I/O utilities that work without OpenCV.
|
|
4
|
+
* Safe to use in constrained environments (e.g. Browser Extensions)
|
|
5
|
+
* where OpenCV cannot be initialized.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CanvasProcessor {
|
|
8
|
+
/**
|
|
9
|
+
* Convert an ArrayBuffer (image file bytes) to a CanvasLike.
|
|
10
|
+
* If the value is already a CanvasLike it is returned as-is.
|
|
11
|
+
*/
|
|
12
|
+
static prepareCanvas(file: ArrayBuffer): Promise<CanvasLike>;
|
|
13
|
+
/**
|
|
14
|
+
* Convert a CanvasLike to an ArrayBuffer (PNG bytes).
|
|
15
|
+
* If the value is already an ArrayBuffer it is returned as-is.
|
|
16
|
+
*/
|
|
17
|
+
static prepareBuffer(canvas: CanvasLike): Promise<ArrayBuffer>;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class CanvasProcessor{static async prepareCanvas(file){if(getPlatform().isCanvas(file))return file;return getPlatform().loadImage(file)}static async prepareBuffer(canvas){if(canvas instanceof ArrayBuffer)return canvas;if(typeof canvas.toBuffer==="function"){let buffer=canvas.toBuffer("image/png");let arrayBuffer=new ArrayBuffer(buffer.byteLength);new Uint8Array(arrayBuffer).set(new Uint8Array(buffer));return arrayBuffer}if(typeof canvas.toDataURL==="function"){let dataURL=canvas.toDataURL("image/png");let base64Data=dataURL.replace(/^data:image\/png;base64,/,"");let binaryString=atob(base64Data);let arrayBuffer=new ArrayBuffer(binaryString.length);let bytes=new Uint8Array(arrayBuffer);for(let i=0;i<binaryString.length;i++){bytes[i]=binaryString.charCodeAt(i)}return arrayBuffer}let ctx=canvas.getContext("2d");let imageData=ctx.getImageData(0,0,canvas.width,canvas.height);let canvasBuffer=new ArrayBuffer(imageData.data.byteLength);new Uint8Array(canvasBuffer).set(new Uint8Array(imageData.data.buffer,imageData.data.byteOffset,imageData.data.byteLength));return canvasBuffer}}import{getPlatform}from"./canvas-factory.js";
|
package/canvas-toolkit.base.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { BoundingBox } from "./index.interface.js";
|
|
2
2
|
import type { CanvasLike, Context2DLike } from "./canvas-factory.js";
|
|
3
|
-
|
|
3
|
+
/** Structural interface for contour-like objects with 32-bit signed integer point data */
|
|
4
|
+
export interface ContourLike {
|
|
5
|
+
data32S: Int32Array | number[];
|
|
6
|
+
}
|
|
4
7
|
/**
|
|
5
8
|
* Cross-platform base class for canvas manipulation utilities.
|
|
6
9
|
* Contains only methods that work in both Node and browser environments.
|
|
@@ -42,7 +45,7 @@ export declare class CanvasToolkitBase {
|
|
|
42
45
|
*/
|
|
43
46
|
drawContour(options: {
|
|
44
47
|
ctx: Context2DLike;
|
|
45
|
-
contour:
|
|
48
|
+
contour: ContourLike;
|
|
46
49
|
strokeStyle?: string;
|
|
47
50
|
lineWidth?: number;
|
|
48
51
|
}): void;
|
package/deskew.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { CanvasLike } from "./canvas-factory.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for configuring the deskew service
|
|
4
|
+
*/
|
|
5
|
+
export interface DeskewOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Enable detailed logging of each processing step.
|
|
8
|
+
* @default false
|
|
9
|
+
*/
|
|
10
|
+
verbose?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Remove detected boxes with area below this threshold, in pixels.
|
|
13
|
+
* Used to filter out noise when detecting text regions.
|
|
14
|
+
* @default 20
|
|
15
|
+
*/
|
|
16
|
+
minimumAreaThreshold?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Service for calculating the skew angle of an image containing text.
|
|
20
|
+
*
|
|
21
|
+
* This service analyzes text regions in an image to determine its skew angle
|
|
22
|
+
* using multiple methods (minAreaRect, baseline analysis, and Hough transform)
|
|
23
|
+
* to robustly calculate the average text orientation.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { DeskewService } from 'ppu-ocv';
|
|
28
|
+
*
|
|
29
|
+
* const service = new DeskewService({ verbose: true });
|
|
30
|
+
* const canvas = ...; // your canvas with text
|
|
31
|
+
* const angle = await service.calculateSkewAngle(canvas);
|
|
32
|
+
* console.log(`Skew angle: ${angle}°`);
|
|
33
|
+
*
|
|
34
|
+
* // Or deskew the image directly
|
|
35
|
+
* const deskewed = await service.deskewImage(canvas);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare class DeskewService {
|
|
39
|
+
private readonly verbose;
|
|
40
|
+
private readonly minimumAreaThreshold;
|
|
41
|
+
constructor(options?: DeskewOptions);
|
|
42
|
+
private log;
|
|
43
|
+
/**
|
|
44
|
+
* Calculate the skew angle of text in a probability map or binary image.
|
|
45
|
+
*
|
|
46
|
+
* This method processes the input image to detect text regions and calculates
|
|
47
|
+
* the average skew angle using multiple robust methods.
|
|
48
|
+
*
|
|
49
|
+
* @param canvas - Canvas containing a probability map or binary image of text regions
|
|
50
|
+
* @returns The calculated skew angle in degrees (positive = clockwise, negative = counter-clockwise)
|
|
51
|
+
*/
|
|
52
|
+
calculateSkewAngle(canvas: CanvasLike): Promise<number>;
|
|
53
|
+
/**
|
|
54
|
+
* Deskew an image by detecting its skew angle and rotating it.
|
|
55
|
+
*
|
|
56
|
+
* This is a convenience method that combines `calculateSkewAngle()`
|
|
57
|
+
* with rotation to produce a straightened image.
|
|
58
|
+
*
|
|
59
|
+
* @param canvas - Canvas containing the image to deskew
|
|
60
|
+
* @returns A new canvas with the deskewed image
|
|
61
|
+
*/
|
|
62
|
+
deskewImage(canvas: CanvasLike): Promise<CanvasLike>;
|
|
63
|
+
private calculateMinRectAngles;
|
|
64
|
+
private calculateBaselineAngles;
|
|
65
|
+
private calculateHoughAngles;
|
|
66
|
+
private calculateLineAngle;
|
|
67
|
+
private calculateConsensusAngle;
|
|
68
|
+
}
|
package/deskew.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class DeskewService{verbose;minimumAreaThreshold;constructor(options={}){this.verbose=options.verbose??false;this.minimumAreaThreshold=options.minimumAreaThreshold??20}log(message){if(this.verbose){console.log(`[DeskewService] ${message}`)}}async calculateSkewAngle(canvas){let processor=new ImageProcessor(canvas);let mat=processor.grayscale().threshold({lower:0,upper:255,type:cv.THRESH_BINARY+cv.THRESH_OTSU}).toMat();let contours=new Contours(mat,{mode:cv.RETR_LIST,method:cv.CHAIN_APPROX_SIMPLE});processor.destroy();let minAngle=-20;let maxAngle=20;let minArea=this.minimumAreaThreshold;let textRegions=[];contours.iterate((contour)=>{let rect=contours.getRect(contour);let area=rect.width*rect.height;if(area<minArea)return;let aspectRatio=rect.width/rect.height;if(aspectRatio>0.2&&aspectRatio<10){textRegions.push({rect,contour,area,aspectRatio})}});if(textRegions.length===0){this.log("No valid text regions found for skew calculation.");contours.destroy();return 0}let averageHeight=textRegions.reduce((sum,region)=>sum+region.rect.height,0)/textRegions.length;let filteredRegions=textRegions.filter((region)=>{return region.rect.height<=averageHeight*1.5});this.log(`Found ${filteredRegions.length} text regions for skew analysis.`);let minRectAngles=this.calculateMinRectAngles(filteredRegions,contours);let baselineAngles=this.calculateBaselineAngles(filteredRegions);let houghAngles=this.calculateHoughAngles(mat,minAngle,maxAngle);contours.destroy();let allAngles=[...minRectAngles.map((a)=>({...a,method:"minRect"})),...baselineAngles.map((a)=>({...a,method:"baseline"})),...houghAngles.map((a)=>({...a,method:"hough"}))];if(allAngles.length===0){this.log("No angles detected from any method.");return 0}let consensusAngle=this.calculateConsensusAngle(allAngles,minAngle,maxAngle);this.log(`Calculated skew angle: ${consensusAngle.toFixed(3)}° (from ${allAngles.length} measurements)`);return consensusAngle}async deskewImage(canvas){this.log("Starting image deskewing process");let angle=await this.calculateSkewAngle(canvas);this.log(`Detected skew angle: ${angle.toFixed(2)}°. Rotating image by ${-angle.toFixed(2)}°...`);let processor=new ImageProcessor(canvas);try{let rotatedCanvas=processor.rotate({angle}).toCanvas();return rotatedCanvas}finally{processor.destroy()}}calculateMinRectAngles(textRegions,contours){let angles=[];for(let region of textRegions){try{let minRect=cv.minAreaRect(region.contour);if(!minRect)continue;let angle=minRect.angle;if(angle>45){angle-=90}else if(angle<-45){angle+=90}let areaWeight=Math.log(region.area+1);let aspectWeight=Math.min(region.aspectRatio,1/region.aspectRatio)*2;let weight=areaWeight*aspectWeight;angles.push({angle,weight})}catch(error){continue}}return angles}calculateBaselineAngles(textRegions){let angles=[];for(let region of textRegions){try{let points=region.contour.data32S;if(!points||points.length<8)continue;let bottomPoints=[];for(let i=0;i<points.length;i+=2){let x=points[i];let y=points[i+1];if(x!==undefined&&y!==undefined){bottomPoints.push({x,y})}}if(bottomPoints.length<3)continue;bottomPoints.sort((a,b)=>a.x-b.x);let segments=3;let segmentSize=Math.floor(bottomPoints.length/segments);let baselinePoints=[];for(let seg=0;seg<segments;seg++){let start=seg*segmentSize;let end=seg===segments-1?bottomPoints.length:(seg+1)*segmentSize;let segmentPoints=bottomPoints.slice(start,end);if(segmentPoints.length>0){let maxYPoint=segmentPoints.reduce((max,point)=>point.y>max.y?point:max);baselinePoints.push(maxYPoint)}}if(baselinePoints.length>=2){let angle=this.calculateLineAngle(baselinePoints);let weight=region.area*Math.min(region.aspectRatio,1/region.aspectRatio);angles.push({angle,weight})}}catch(error){continue}}return angles}calculateHoughAngles(mat,minAngle,maxAngle){let angles=[];try{let kernel=cv.getStructuringElement(cv.MORPH_RECT,new cv.Size(3,1));let morphed=new cv.Mat;cv.morphologyEx(mat,morphed,cv.MORPH_CLOSE,kernel);let lines=new cv.Mat;cv.HoughLinesP(morphed,lines,1,Math.PI/180,30,50,10);for(let i=0;i<lines.rows;i++){let line=lines.data32S.subarray(i*4,(i+1)*4);const[x1,y1,x2,y2]=line;if(x1!==undefined&&y1!==undefined&&x2!==undefined&&y2!==undefined){let dx=x2-x1;let dy=y2-y1;if(Math.abs(dx)>1){let angle=Math.atan2(dy,dx)*180/Math.PI;if(angle>45)angle-=90;if(angle<-45)angle+=90;if(angle>=minAngle&&angle<=maxAngle){let lineLength=Math.sqrt(dx*dx+dy*dy);angles.push({angle,weight:lineLength})}}}}morphed.delete();lines.delete();kernel.delete()}catch(error){this.log("Hough transform failed, skipping this method.")}return angles}calculateLineAngle(points){if(points.length<2)return 0;let n=points.length;let sumX=points.reduce((sum,p)=>sum+p.x,0);let sumY=points.reduce((sum,p)=>sum+p.y,0);let sumXY=points.reduce((sum,p)=>sum+p.x*p.y,0);let sumXX=points.reduce((sum,p)=>sum+p.x*p.x,0);let denominator=n*sumXX-sumX*sumX;if(Math.abs(denominator)<0.0000000001)return 0;let slope=(n*sumXY-sumX*sumY)/denominator;let angle=Math.atan(slope)*180/Math.PI;if(angle>45)angle-=90;if(angle<-45)angle+=90;return angle}calculateConsensusAngle(angles,minAngle,maxAngle){if(angles.length===0)return 0;let sortedAngles=[...angles].sort((a,b)=>a.angle-b.angle);let q1Index=Math.floor(sortedAngles.length*0.25);let q3Index=Math.floor(sortedAngles.length*0.75);let q1=sortedAngles[q1Index]?.angle||0;let q3=sortedAngles[q3Index]?.angle||0;let iqr=q3-q1;let lowerBound=q1-1.5*iqr;let upperBound=q3+1.5*iqr;let filteredAngles=angles.filter((a)=>a.angle>=lowerBound&&a.angle<=upperBound&&a.angle>=minAngle&&a.angle<=maxAngle);if(filteredAngles.length===0){this.log("All angles filtered out as outliers, using median of original set.");let medianIndex=Math.floor(sortedAngles.length/2);return sortedAngles[medianIndex]?.angle||0}let totalWeight=filteredAngles.reduce((sum,a)=>sum+a.weight,0);if(totalWeight===0){let average=filteredAngles.reduce((sum,a)=>sum+a.angle,0)/filteredAngles.length;return average}let weightedSum=filteredAngles.reduce((sum,a)=>sum+a.angle*a.weight,0);let weightedAverage=weightedSum/totalWeight;let methodCounts=filteredAngles.reduce((counts,a)=>{counts[a.method]=(counts[a.method]||0)+1;return counts},{});this.log(`Angle methods used: ${Object.entries(methodCounts).map(([method,count])=>`${method}:${count}`).join(", ")}`);return Math.max(minAngle,Math.min(maxAngle,weightedAverage))}}import{Contours}from"./contours.js";import{cv}from"./cv-provider.js";import{ImageProcessor}from"./image-processor.js";
|
package/image-processor.d.ts
CHANGED
|
@@ -14,14 +14,6 @@ export declare class ImageProcessor {
|
|
|
14
14
|
* @param source Source image as CanvasLike or cv.Mat
|
|
15
15
|
*/
|
|
16
16
|
constructor(source: CanvasLike | cv.Mat);
|
|
17
|
-
/**
|
|
18
|
-
* Convert array buffer to canvas
|
|
19
|
-
*/
|
|
20
|
-
static prepareCanvas(file: ArrayBuffer): Promise<CanvasLike>;
|
|
21
|
-
/**
|
|
22
|
-
* Convert canvas to array buffer
|
|
23
|
-
*/
|
|
24
|
-
static prepareBuffer(canvas: CanvasLike): Promise<ArrayBuffer>;
|
|
25
17
|
/**
|
|
26
18
|
* Initialize OpenCV runtime. Must be called before any image processing.
|
|
27
19
|
*
|
package/image-processor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export class ImageProcessor{img;width;height;constructor(source){if(getPlatform().isCanvas(source)){let ctx=source.getContext("2d");let imageData=ctx.getImageData(0,0,source.width,source.height);this.img=cv.matFromImageData(imageData);this.width=source.width;this.height=source.height}else if(source instanceof cv.Mat){this.img=source;this.width=source.cols;this.height=source.rows}else{throw new Error("Invalid source type. Must be either Canvas or cv.Mat.")}}static async
|
|
1
|
+
export class ImageProcessor{img;width;height;constructor(source){if(getPlatform().isCanvas(source)){let ctx=source.getContext("2d");let imageData=ctx.getImageData(0,0,source.width,source.height);this.img=cv.matFromImageData(imageData);this.width=source.width;this.height=source.height}else if(source instanceof cv.Mat){this.img=source;this.width=source.cols;this.height=source.rows}else{throw new Error("Invalid source type. Must be either Canvas or cv.Mat.")}}static async initRuntime(){if(globalThis.cv?.Mat){setCv(globalThis.cv);return}try{let mod=await import("@techstark/opencv-js");let _cv=mod.default||mod;setCv(_cv);if(!_cv.Mat){await new Promise((res)=>{_cv["onRuntimeInitialized"]=()=>res()})}return}catch{}if(typeof document!=="undefined"){await new Promise((resolve,reject)=>{let script=document.createElement("script");script.src="https://cdn.jsdelivr.net/npm/@techstark/opencv-js@4.10.0-release.1/dist/opencv.js";script.async=true;script.onload=()=>{let g=globalThis;if(g.cv?.Mat){setCv(g.cv);resolve()}else if(g.cv){g.cv["onRuntimeInitialized"]=()=>{setCv(g.cv);resolve()}}else{reject(new Error("OpenCV.js loaded but cv not found on globalThis"))}};script.onerror=()=>reject(new Error("Failed to load @techstark/opencv-js from CDN"));document.head.appendChild(script)});return}throw new Error("Cannot initialize OpenCV runtime. Install @techstark/opencv-js or run in a browser.")}execute(operationName,options){let result=executeOperation(operationName,this.img,options);this.img=result.img;this.width=result.width;this.height=result.height;return this}grayscale(options){return this.execute("grayscale",options)}blur(options){return this.execute("blur",options)}threshold(options){return this.execute("threshold",options)}adaptiveThreshold(options){return this.execute("adaptiveThreshold",options)}invert(options){return this.execute("invert",options)}canny(options){return this.execute("canny",options)}dilate(options){return this.execute("dilate",options)}erode(options){return this.execute("erode",options)}border(options){return this.execute("border",options)}resize(options){return this.execute("resize",options)}rotate(options){return this.execute("rotate",options)}warp(options){return this.execute("warp",options)}convert(options){return this.execute("convert",options)}morphologicalGradient(options){return this.execute("morphologicalGradient",options)}toMat(){return this.img}toCanvas(){let platform=getPlatform();let canvas=platform.createCanvas(this.width,this.height);try{cv.imshow(canvas,this.img)}catch(e){let ctx=canvas.getContext("2d");if(!ctx)throw new Error("Could not get 2d context from canvas");let imgData=ctx.createImageData(this.width,this.height);if(this.img.channels()===1){let data=imgData.data;let gray=new Uint8Array(this.img.data);for(let i=0;i<gray.length;i++){data[i*4]=gray[i];data[i*4+1]=gray[i];data[i*4+2]=gray[i];data[i*4+3]=255}}else{imgData.data.set(new Uint8ClampedArray(this.img.data))}ctx.putImageData(imgData,0,0)}return canvas}destroy(){try{this.img.delete()}catch{}}}import{getPlatform}from"./canvas-factory.js";import{cv,setCv}from"./cv-provider.js";import{executeOperation}from"./pipeline/index.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { BoundingBox, Coordinate, Points } from "./index.interface.js";
|
|
2
|
+
export { getPlatform, setPlatform } from "./canvas-factory.js";
|
|
3
|
+
export type { CanvasLike, CanvasPlatform, Context2DLike, } from "./canvas-factory.js";
|
|
4
|
+
export { webPlatform } from "./platform/web.js";
|
|
5
|
+
export { CanvasToolkitBase as CanvasToolkit, CanvasToolkitBase, type ContourLike, } from "./canvas-toolkit.base.js";
|
|
6
|
+
export { CanvasProcessor } from "./canvas-processor.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{setPlatform}from"./canvas-factory.js";import{webPlatform}from"./platform/web.js";setPlatform(webPlatform);export{getPlatform,setPlatform}from"./canvas-factory.js";export{webPlatform}from"./platform/web.js";export{CanvasToolkitBase as CanvasToolkit,CanvasToolkitBase}from"./canvas-toolkit.base.js";export{CanvasProcessor}from"./canvas-processor.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Canvas, createCanvas, ImageData, loadImage } from "@napi-rs/canvas";
|
|
2
|
+
export type { SKRSContext2D } from "@napi-rs/canvas";
|
|
3
|
+
export type { BoundingBox, Coordinate, Points } from "./index.interface.js";
|
|
4
|
+
export { getPlatform, setPlatform } from "./canvas-factory.js";
|
|
5
|
+
export type { CanvasLike, CanvasPlatform, Context2DLike, } from "./canvas-factory.js";
|
|
6
|
+
export { CanvasToolkitBase, type ContourLike } from "./canvas-toolkit.base.js";
|
|
7
|
+
export { CanvasToolkit } from "./canvas-toolkit.js";
|
|
8
|
+
export { CanvasProcessor } from "./canvas-processor.js";
|
package/index.canvas.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{setPlatform}from"./canvas-factory.js";import{nodePlatform}from"./platform/node.js";setPlatform(nodePlatform);export{Canvas,createCanvas,ImageData,loadImage}from"@napi-rs/canvas";export{getPlatform,setPlatform}from"./canvas-factory.js";export{CanvasToolkitBase}from"./canvas-toolkit.base.js";export{CanvasToolkit}from"./canvas-toolkit.js";export{CanvasProcessor}from"./canvas-processor.js";
|
package/index.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ export type { BoundingBox, Coordinate, Points } from "./index.interface.js";
|
|
|
6
6
|
export { executeOperation, OperationRegistry, registry, } from "./pipeline/index.js";
|
|
7
7
|
export { getPlatform, setPlatform } from "./canvas-factory.js";
|
|
8
8
|
export type { CanvasLike, CanvasPlatform, Context2DLike, } from "./canvas-factory.js";
|
|
9
|
-
export { CanvasToolkitBase } from "./canvas-toolkit.base.js";
|
|
9
|
+
export { CanvasToolkitBase, type ContourLike } from "./canvas-toolkit.base.js";
|
|
10
10
|
export { CanvasToolkit } from "./canvas-toolkit.js";
|
|
11
|
+
export { CanvasProcessor } from "./canvas-processor.js";
|
|
11
12
|
export { Contours } from "./contours.js";
|
|
12
13
|
export { calculateMeanGrayscaleValue, calculateMeanNormalizedLabLightness, type CalculateMeanLightnessOptions, } from "./image-analysis.js";
|
|
13
14
|
export { ImageProcessor } from "./image-processor.js";
|
|
15
|
+
export { DeskewService, type DeskewOptions } from "./deskew.js";
|
|
14
16
|
export type { AdaptiveThresholdOptions, BlurOptions, BorderOptions, CannyOptions, DilateOptions, ErodeOptions, GrayscaleOptions, InvertOptions, MorphologicalGradientOptions, OperationFunction, OperationName, OperationOptions, OperationResult, PartialOptions, RegisteredOperations, RequiredOptions, ResizeOptions, RotateOptions, ThresholdOptions, WarpOptions, } from "./pipeline/index.js";
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import _cv from"@techstark/opencv-js";import{cv,setCv}from"./cv-provider.js";setCv(_cv);export{cv};import{setPlatform}from"./canvas-factory.js";import{nodePlatform}from"./platform/node.js";setPlatform(nodePlatform);export{Canvas,createCanvas,ImageData,loadImage}from"@napi-rs/canvas";export{executeOperation,OperationRegistry,registry}from"./pipeline/index.js";export{getPlatform,setPlatform}from"./canvas-factory.js";export{CanvasToolkitBase}from"./canvas-toolkit.base.js";export{CanvasToolkit}from"./canvas-toolkit.js";export{Contours}from"./contours.js";export{calculateMeanGrayscaleValue,calculateMeanNormalizedLabLightness}from"./image-analysis.js";export{ImageProcessor}from"./image-processor.js";
|
|
1
|
+
import _cv from"@techstark/opencv-js";import{cv,setCv}from"./cv-provider.js";setCv(_cv);export{cv};import{setPlatform}from"./canvas-factory.js";import{nodePlatform}from"./platform/node.js";setPlatform(nodePlatform);export{Canvas,createCanvas,ImageData,loadImage}from"@napi-rs/canvas";export{executeOperation,OperationRegistry,registry}from"./pipeline/index.js";export{getPlatform,setPlatform}from"./canvas-factory.js";export{CanvasToolkitBase}from"./canvas-toolkit.base.js";export{CanvasToolkit}from"./canvas-toolkit.js";export{CanvasProcessor}from"./canvas-processor.js";export{Contours}from"./contours.js";export{calculateMeanGrayscaleValue,calculateMeanNormalizedLabLightness}from"./image-analysis.js";export{ImageProcessor}from"./image-processor.js";export{DeskewService}from"./deskew.js";
|
package/index.web.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ export type { CanvasLike, CanvasPlatform, Context2DLike, } from "./canvas-factor
|
|
|
5
5
|
export { webPlatform } from "./platform/web.js";
|
|
6
6
|
export type { BoundingBox, Coordinate, Points } from "./index.interface.js";
|
|
7
7
|
export { executeOperation, OperationRegistry, registry, } from "./pipeline/index.js";
|
|
8
|
-
export { CanvasToolkitBase as CanvasToolkit, CanvasToolkitBase, } from "./canvas-toolkit.base.js";
|
|
8
|
+
export { CanvasToolkitBase as CanvasToolkit, CanvasToolkitBase, type ContourLike, } from "./canvas-toolkit.base.js";
|
|
9
|
+
export { CanvasProcessor } from "./canvas-processor.js";
|
|
9
10
|
export { Contours } from "./contours.js";
|
|
10
11
|
export { calculateMeanGrayscaleValue, calculateMeanNormalizedLabLightness, type CalculateMeanLightnessOptions, } from "./image-analysis.js";
|
|
11
12
|
export { ImageProcessor } from "./image-processor.js";
|
|
13
|
+
export { DeskewService, type DeskewOptions } from "./deskew.js";
|
|
12
14
|
export type { AdaptiveThresholdOptions, BlurOptions, BorderOptions, CannyOptions, DilateOptions, ErodeOptions, GrayscaleOptions, InvertOptions, MorphologicalGradientOptions, OperationFunction, OperationName, OperationOptions, OperationResult, PartialOptions, RegisteredOperations, RequiredOptions, ResizeOptions, RotateOptions, ThresholdOptions, WarpOptions, } from "./pipeline/index.js";
|
package/index.web.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cv}from"./cv-provider.js";export{cv};import{setPlatform}from"./canvas-factory.js";import{webPlatform}from"./platform/web.js";setPlatform(webPlatform);export{getPlatform,setPlatform}from"./canvas-factory.js";export{webPlatform}from"./platform/web.js";export{executeOperation,OperationRegistry,registry}from"./pipeline/index.js";export{CanvasToolkitBase as CanvasToolkit,CanvasToolkitBase}from"./canvas-toolkit.base.js";export{Contours}from"./contours.js";export{calculateMeanGrayscaleValue,calculateMeanNormalizedLabLightness}from"./image-analysis.js";export{ImageProcessor}from"./image-processor.js";
|
|
1
|
+
import{cv}from"./cv-provider.js";export{cv};import{setPlatform}from"./canvas-factory.js";import{webPlatform}from"./platform/web.js";setPlatform(webPlatform);export{getPlatform,setPlatform}from"./canvas-factory.js";export{webPlatform}from"./platform/web.js";export{executeOperation,OperationRegistry,registry}from"./pipeline/index.js";export{CanvasToolkitBase as CanvasToolkit,CanvasToolkitBase}from"./canvas-toolkit.base.js";export{CanvasProcessor}from"./canvas-processor.js";export{Contours}from"./contours.js";export{calculateMeanGrayscaleValue,calculateMeanNormalizedLabLightness}from"./image-analysis.js";export{ImageProcessor}from"./image-processor.js";export{DeskewService}from"./deskew.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ppu-ocv",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A type-safe, modular, chainable image processing library built on top of OpenCV.js with a fluent API leveraging pipeline processing.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"open-cv",
|
|
@@ -33,6 +33,14 @@
|
|
|
33
33
|
"./web": {
|
|
34
34
|
"types": "./index.web.d.ts",
|
|
35
35
|
"default": "./index.web.js"
|
|
36
|
+
},
|
|
37
|
+
"./canvas": {
|
|
38
|
+
"types": "./index.canvas.d.ts",
|
|
39
|
+
"default": "./index.canvas.js"
|
|
40
|
+
},
|
|
41
|
+
"./canvas-web": {
|
|
42
|
+
"types": "./index.canvas-web.d.ts",
|
|
43
|
+
"default": "./index.canvas-web.js"
|
|
36
44
|
}
|
|
37
45
|
},
|
|
38
46
|
"scripts": {
|
|
@@ -40,7 +48,8 @@
|
|
|
40
48
|
"build:test": "bun task build && bun test",
|
|
41
49
|
"build:publish": "bun task build && bun task report-size && bun task publish",
|
|
42
50
|
"lint": "prettier --check ./src",
|
|
43
|
-
"lint:fix": "prettier --write ./src"
|
|
51
|
+
"lint:fix": "prettier --write ./src",
|
|
52
|
+
"demo": "bunx -y serve -l 4567 ."
|
|
44
53
|
},
|
|
45
54
|
"devDependencies": {
|
|
46
55
|
"@stylistic/eslint-plugin": "latest",
|