ppu-ocv 1.5.2 → 1.6.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 +0 -36
- package/index.d.ts +1 -2
- package/index.interface.d.ts +0 -9
- package/index.js +1 -1
- package/package.json +1 -1
- package/face-detector.d.ts +0 -70
- package/face-detector.js +0 -1
- package/src/haarcascade_eye.xml +0 -12213
- package/src/haarcascade_eye_tree_eyeglasses.xml +0 -22619
- package/src/haarcascade_frontalface_default.xml +0 -33314
package/README.md
CHANGED
|
@@ -165,42 +165,6 @@ See: [How to extend ppu-ocv operations](./docs/how-to-extend-ppu-ocv-operations.
|
|
|
165
165
|
| `getCornerPoints` | Canvas, contour | Get four corner points for a given contour. Useful for perspective transformation (warp). |
|
|
166
166
|
| `destroy` | | Destroy & clean-up the memory from the contours |
|
|
167
167
|
|
|
168
|
-
#### `FaceDetector`
|
|
169
|
-
|
|
170
|
-
Singleton class for face and eye detection using Haar Cascade classifiers.
|
|
171
|
-
|
|
172
|
-
| Method | Args | Description |
|
|
173
|
-
| ------------- | --------------------------- | ---------------------------------------------------------------------- |
|
|
174
|
-
| `getInstance` | | Get the singleton instance of FaceDetector |
|
|
175
|
-
| `detectFace` | Canvas, options | Detect faces in the given canvas, returns `{ faces: BoundingBox[] }` |
|
|
176
|
-
| `detectEye` | Canvas, options | Detect eyes in the given canvas, returns `{ eyes: { left, right }[] }` |
|
|
177
|
-
| `alignFace` | Canvas, [leftEye, rightEye] | Align face based on eye positions, returns aligned Canvas |
|
|
178
|
-
|
|
179
|
-
**Usage Example:**
|
|
180
|
-
|
|
181
|
-
```ts
|
|
182
|
-
import { FaceDetector, ImageProcessor } from "ppu-ocv";
|
|
183
|
-
|
|
184
|
-
await ImageProcessor.initRuntime();
|
|
185
|
-
const file = Bun.file("./image.jpg");
|
|
186
|
-
const canvas = await ImageProcessor.prepareCanvas(await file.arrayBuffer());
|
|
187
|
-
|
|
188
|
-
const faceDetector = await FaceDetector.getInstance();
|
|
189
|
-
|
|
190
|
-
// Detect faces
|
|
191
|
-
const faceResult = await faceDetector.detectFace(canvas);
|
|
192
|
-
console.log(`Found ${faceResult.faces.length} faces`);
|
|
193
|
-
|
|
194
|
-
// Detect eyes
|
|
195
|
-
const eyeResult = await faceDetector.detectEye(canvas);
|
|
196
|
-
|
|
197
|
-
// Align face if eyes detected
|
|
198
|
-
if (eyeResult.eyes.length > 0) {
|
|
199
|
-
const { left, right } = eyeResult.eyes[0];
|
|
200
|
-
const alignedCanvas = await faceDetector.alignFace(canvas, [left, right]);
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
168
|
#### `ImageAnalysis`
|
|
205
169
|
|
|
206
170
|
Just a collection of utility functions for analyzing image properties.
|
package/index.d.ts
CHANGED
|
@@ -2,11 +2,10 @@ import cv from "@techstark/opencv-js";
|
|
|
2
2
|
export { cv };
|
|
3
3
|
export { Canvas, createCanvas, ImageData, loadImage } from "@napi-rs/canvas";
|
|
4
4
|
export type { SKRSContext2D } from "@napi-rs/canvas";
|
|
5
|
-
export type { BoundingBox, Coordinate, Points
|
|
5
|
+
export type { BoundingBox, Coordinate, Points } from "./index.interface";
|
|
6
6
|
export { executeOperation, OperationRegistry, registry } from "./pipeline";
|
|
7
7
|
export { CanvasToolkit } from "./canvas-toolkit";
|
|
8
8
|
export { Contours } from "./contours";
|
|
9
9
|
export { calculateMeanGrayscaleValue, calculateMeanNormalizedLabLightness, type CalculateMeanLightnessOptions, } from "./image-analysis";
|
|
10
10
|
export { ImageProcessor } from "./image-processor";
|
|
11
|
-
export { FaceDetector } from "./face-detector";
|
|
12
11
|
export type { AdaptiveThresholdOptions, BlurOptions, BorderOptions, CannyOptions, DilateOptions, ErodeOptions, GrayscaleOptions, InvertOptions, MorphologicalGradientOptions, OperationFunction, OperationName, OperationOptions, OperationResult, PartialOptions, RegisteredOperations, RequiredOptions, ResizeOptions, RotateOptions, ThresholdOptions, WarpOptions, } from "./pipeline";
|
package/index.interface.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import cv from"@techstark/opencv-js";export{cv};export{Canvas,createCanvas,ImageData,loadImage}from"@napi-rs/canvas";export{executeOperation,OperationRegistry,registry}from"./pipeline";export{CanvasToolkit}from"./canvas-toolkit";export{Contours}from"./contours";export{calculateMeanGrayscaleValue,calculateMeanNormalizedLabLightness}from"./image-analysis";export{ImageProcessor}from"./image-processor";
|
|
1
|
+
import cv from"@techstark/opencv-js";export{cv};export{Canvas,createCanvas,ImageData,loadImage}from"@napi-rs/canvas";export{executeOperation,OperationRegistry,registry}from"./pipeline";export{CanvasToolkit}from"./canvas-toolkit";export{Contours}from"./contours";export{calculateMeanGrayscaleValue,calculateMeanNormalizedLabLightness}from"./image-analysis";export{ImageProcessor}from"./image-processor";
|
package/package.json
CHANGED
package/face-detector.d.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Canvas } from "./index";
|
|
2
|
-
import type { BoundingBox, EyesDetectorResult, FaceDetectorResult } from "./index.interface";
|
|
3
|
-
export declare class FaceDetector {
|
|
4
|
-
private static instance;
|
|
5
|
-
private frontalFaceCascade;
|
|
6
|
-
private eyeCascade;
|
|
7
|
-
private eyeGlassCascade;
|
|
8
|
-
/**
|
|
9
|
-
* Private constructor to prevent direct instantiation
|
|
10
|
-
*/
|
|
11
|
-
private constructor();
|
|
12
|
-
/**
|
|
13
|
-
* Get the singleton instance of FaceDetector
|
|
14
|
-
* @returns The singleton instance
|
|
15
|
-
* @example
|
|
16
|
-
* const faceDetector = await FaceDetector.getInstance();
|
|
17
|
-
*/
|
|
18
|
-
static getInstance(): Promise<FaceDetector>;
|
|
19
|
-
/**
|
|
20
|
-
* Detect faces in the given canvas
|
|
21
|
-
* @param canvas Source canvas containing the image
|
|
22
|
-
* @param options Detection options
|
|
23
|
-
* @returns Promise resolving to detected faces
|
|
24
|
-
* @example
|
|
25
|
-
* const result = await faceDetector.detectFace(canvas);
|
|
26
|
-
* console.log(`Found ${result.faces.length} faces`);
|
|
27
|
-
*/
|
|
28
|
-
detectFace(canvas: Canvas, options?: {
|
|
29
|
-
scaleFactor?: number;
|
|
30
|
-
minNeighbors?: number;
|
|
31
|
-
minSize?: {
|
|
32
|
-
width: number;
|
|
33
|
-
height: number;
|
|
34
|
-
};
|
|
35
|
-
}): Promise<FaceDetectorResult>;
|
|
36
|
-
/**
|
|
37
|
-
* Detect eyes in the given canvas
|
|
38
|
-
* @param canvas Source canvas containing the image
|
|
39
|
-
* @param options Detection options
|
|
40
|
-
* @returns Promise resolving to detected eyes
|
|
41
|
-
* @example
|
|
42
|
-
* const result = await faceDetector.detectEye(canvas);
|
|
43
|
-
* console.log(`Found ${result.eyes.length} eye pairs`);
|
|
44
|
-
*/
|
|
45
|
-
detectEye(canvas: Canvas, options?: {
|
|
46
|
-
scaleFactor?: number;
|
|
47
|
-
minNeighbors?: number;
|
|
48
|
-
minSize?: {
|
|
49
|
-
width: number;
|
|
50
|
-
height: number;
|
|
51
|
-
};
|
|
52
|
-
useFallback?: boolean;
|
|
53
|
-
}): Promise<EyesDetectorResult>;
|
|
54
|
-
/**
|
|
55
|
-
* Detect eyes with glasses/sunglasses
|
|
56
|
-
* @param gray Grayscale cv.Mat image
|
|
57
|
-
* @param options Detection options
|
|
58
|
-
* @returns Detected eyes result
|
|
59
|
-
*/
|
|
60
|
-
private detectEyeSunglass;
|
|
61
|
-
/**
|
|
62
|
-
* Align face based on eye positions
|
|
63
|
-
* @param canvas Source canvas containing the face
|
|
64
|
-
* @param eyes Tuple of left and right eye bounding boxes
|
|
65
|
-
* @returns Promise resolving to aligned face canvas
|
|
66
|
-
* @example
|
|
67
|
-
* const aligned = await faceDetector.alignFace(canvas, [leftEye, rightEye]);
|
|
68
|
-
*/
|
|
69
|
-
alignFace(canvas: Canvas, eyes: [BoundingBox, BoundingBox]): Promise<Canvas>;
|
|
70
|
-
}
|
package/face-detector.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export class FaceDetector{static instance=null;frontalFaceCascade;eyeCascade;eyeGlassCascade;constructor(){let __dirname=dirname(fileURLToPath(import.meta.url));let frontalFaceData=readFileSync(join(__dirname,"haarcascade_frontalface_default.xml"));let eyeData=readFileSync(join(__dirname,"haarcascade_eye.xml"));let eyeGlassData=readFileSync(join(__dirname,"haarcascade_eye_tree_eyeglasses.xml"));cv.FS.writeFile("haarcascade_frontalface_default.xml",frontalFaceData);cv.FS.writeFile("haarcascade_eye.xml",eyeData);cv.FS.writeFile("haarcascade_eye_tree_eyeglasses.xml",eyeGlassData);this.frontalFaceCascade=new cv.CascadeClassifier;this.eyeCascade=new cv.CascadeClassifier;this.eyeGlassCascade=new cv.CascadeClassifier;this.frontalFaceCascade.load("haarcascade_frontalface_default.xml");this.eyeCascade.load("haarcascade_eye.xml");this.eyeGlassCascade.load("haarcascade_eye_tree_eyeglasses.xml")}static async getInstance(){await ImageProcessor.initRuntime();if(!FaceDetector.instance){FaceDetector.instance=new FaceDetector}return FaceDetector.instance}async detectFace(canvas,options={}){const{scaleFactor=1.1,minNeighbors=3,minSize={width:30,height:30}}=options;let processor=new ImageProcessor(canvas);let faces=new cv.RectVector;let minSizeMat=new cv.Size(minSize.width,minSize.height);let detectedFaces=[];try{let grayScaled=processor.grayscale().toMat();this.frontalFaceCascade.detectMultiScale(grayScaled,faces,scaleFactor,minNeighbors,0,minSizeMat);for(let i=0;i<faces.size();i++){let face=faces.get(i);detectedFaces.push({x0:face.x,y0:face.y,x1:face.x+face.width,y1:face.y+face.height})}}catch(error){}finally{faces.delete();processor.destroy()}return{faces:detectedFaces}}async detectEye(canvas,options={}){const{scaleFactor=1.05,minNeighbors=3,minSize={width:10,height:10},useFallback=true}=options;let processor=new ImageProcessor(canvas);let grayscaled=processor.grayscale().toMat();let eyes=new cv.RectVector;let minSizeMat=new cv.Size(minSize.width,minSize.height);let result;try{this.eyeCascade.detectMultiScale(grayscaled,eyes,scaleFactor,minNeighbors,0,minSizeMat);if(eyes.size()===0&&useFallback){let eyesWithGlasses=this.detectEyeSunglass(grayscaled,{scaleFactor,minNeighbors,minSize});result=eyesWithGlasses}else{let detectedEyes=[];let eyeArray=[];for(let i=0;i<eyes.size();i++){let eye=eyes.get(i);eyeArray.push({x0:eye.x,y0:eye.y,x1:eye.x+eye.width,y1:eye.y+eye.height})}eyeArray.sort((a,b)=>a.x0-b.x0);for(let i=0;i<eyeArray.length-1;i+=2){detectedEyes.push({left:eyeArray[i],right:eyeArray[i+1]})}result={eyes:detectedEyes}}}catch(error){console.error(`[detectEyes error]: `,error);result={eyes:[]}}finally{eyes.delete();processor.destroy()}return result}detectEyeSunglass(grayscale,options){const{scaleFactor,minNeighbors,minSize}=options;let eyes=new cv.RectVector;let minSizeMat=new cv.Size(minSize.width,minSize.height);this.eyeGlassCascade.detectMultiScale(grayscale,eyes,scaleFactor,minNeighbors,0,minSizeMat);let detectedEyes=[];let eyeArray=[];for(let i=0;i<eyes.size();i++){let eye=eyes.get(i);eyeArray.push({x0:eye.x,y0:eye.y,x1:eye.x+eye.width,y1:eye.y+eye.height})}eyeArray.sort((a,b)=>a.x0-b.x0);for(let i=0;i<eyeArray.length-1;i+=2){detectedEyes.push({left:eyeArray[i],right:eyeArray[i+1]})}return{eyes:detectedEyes}}async alignFace(canvas,eyes){const[leftEye,rightEye]=eyes;let leftEyeCenter={x:(leftEye.x0+leftEye.x1)/2,y:(leftEye.y0+leftEye.y1)/2};let rightEyeCenter={x:(rightEye.x0+rightEye.x1)/2,y:(rightEye.y0+rightEye.y1)/2};let deltaX=rightEyeCenter.x-leftEyeCenter.x;let deltaY=rightEyeCenter.y-leftEyeCenter.y;let angle=Math.atan2(deltaY,deltaX)*(180/Math.PI);let centerX=(leftEyeCenter.x+rightEyeCenter.x)/2;let centerY=(leftEyeCenter.y+rightEyeCenter.y)/2;let center=new cv.Point(centerX,centerY);let processor=new ImageProcessor(canvas);let rotated=processor.rotate({angle,center}).toCanvas();return rotated}}import{readFileSync}from"fs";import{dirname,join}from"path";import{fileURLToPath}from"url";import{cv,ImageProcessor}from"./index";
|