seg-cam 0.4.6 → 0.4.7
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/dist/index.d.mts +153 -0
- package/dist/index.d.ts +153 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +1 -1
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
type TaskType = "object-detection" | "image-segmentation";
|
|
4
|
+
type ModelType = "BodyPix";
|
|
5
|
+
type ObjectDetectionType = {
|
|
6
|
+
score: number;
|
|
7
|
+
label: string;
|
|
8
|
+
box: {
|
|
9
|
+
xmin: number;
|
|
10
|
+
ymin: number;
|
|
11
|
+
xmax: number;
|
|
12
|
+
ymax: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type ImageSegmentationType = {
|
|
16
|
+
label: string;
|
|
17
|
+
score?: number;
|
|
18
|
+
mask: any;
|
|
19
|
+
};
|
|
20
|
+
type ImagesToReturn = "mask" | "mask_with_image" | "none";
|
|
21
|
+
declare const DEFAULT_CONFIG: {
|
|
22
|
+
TASK: TaskType;
|
|
23
|
+
MODEL: ModelType;
|
|
24
|
+
BODYPIX_ARCHITECTURE: "MobileNetV1" | "ResNet50";
|
|
25
|
+
BODYPIX_MULTIPLIER: number;
|
|
26
|
+
BODYPIX_QUANT_BYTES: number;
|
|
27
|
+
BODYPIX_STRIDE: number;
|
|
28
|
+
MULTI_SEGMENTATION: boolean;
|
|
29
|
+
SEGMENT_BODY_PARTS: boolean;
|
|
30
|
+
BACKGROUND_SHADE: number;
|
|
31
|
+
SHIRT_SHADE: number;
|
|
32
|
+
DETECTION_THRESHOLD: number;
|
|
33
|
+
TARGET_PART_ID: number;
|
|
34
|
+
IMAGES_TO_RETURN: ImagesToReturn;
|
|
35
|
+
VERBOSE: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Detection statistics interface
|
|
40
|
+
*/
|
|
41
|
+
interface DetectionStats {
|
|
42
|
+
/** Number of detections found */
|
|
43
|
+
jerseyCount: number;
|
|
44
|
+
/** Average confidence score (0-100) */
|
|
45
|
+
confidence: number;
|
|
46
|
+
/** Processing time in milliseconds */
|
|
47
|
+
processingTime: number;
|
|
48
|
+
/** Frames per second */
|
|
49
|
+
fps: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface JerseyDetectorHandle {
|
|
53
|
+
isReady: boolean;
|
|
54
|
+
stats: DetectionStats;
|
|
55
|
+
lastError: string | null;
|
|
56
|
+
capture: (format?: "image/jpeg" | "image/png", quality?: number) => string;
|
|
57
|
+
}
|
|
58
|
+
interface JerseyDetectorProps {
|
|
59
|
+
videoRef: React.RefObject<HTMLVideoElement>;
|
|
60
|
+
onWorkerReady?: (ready: boolean) => void;
|
|
61
|
+
onWorkerError?: (error: string | null) => void;
|
|
62
|
+
onStatsUpdate?: (stats: DetectionStats) => void;
|
|
63
|
+
onSegmentedImage?: (segmentedImages: ImageBitmap[]) => void;
|
|
64
|
+
task?: TaskType;
|
|
65
|
+
model?: ModelType;
|
|
66
|
+
verbose?: boolean;
|
|
67
|
+
bodyPixArchitecture?: "MobileNetV1" | "ResNet50";
|
|
68
|
+
bodyPixMultiplier?: number;
|
|
69
|
+
bodyPixQuantBytes?: number;
|
|
70
|
+
bodyPixStride?: number;
|
|
71
|
+
multiSegmentation?: boolean;
|
|
72
|
+
segmentBodyParts?: boolean;
|
|
73
|
+
backgroundShade?: number;
|
|
74
|
+
shirtShade?: number;
|
|
75
|
+
threshold?: number;
|
|
76
|
+
targetPartId?: number;
|
|
77
|
+
imagesToReturn?: ImagesToReturn;
|
|
78
|
+
workerUrl?: string;
|
|
79
|
+
}
|
|
80
|
+
declare const JerseyDetector: react.ForwardRefExoticComponent<JerseyDetectorProps & react.RefAttributes<JerseyDetectorHandle>>;
|
|
81
|
+
|
|
82
|
+
type WorkerConfig = {
|
|
83
|
+
task: TaskType;
|
|
84
|
+
model: ModelType;
|
|
85
|
+
verbose: boolean;
|
|
86
|
+
bodyPixArchitecture?: 'MobileNetV1' | 'ResNet50';
|
|
87
|
+
bodyPixMultiplier?: number;
|
|
88
|
+
bodyPixQuantBytes?: number;
|
|
89
|
+
bodyPixStride?: number;
|
|
90
|
+
multiSegmentation?: boolean;
|
|
91
|
+
segmentBodyParts?: boolean;
|
|
92
|
+
backgroundShade?: number;
|
|
93
|
+
shirtShade?: number;
|
|
94
|
+
threshold?: number;
|
|
95
|
+
targetPartId?: number;
|
|
96
|
+
imagesToReturn?: ImagesToReturn;
|
|
97
|
+
};
|
|
98
|
+
type ImageDimensions$1 = {
|
|
99
|
+
width: number;
|
|
100
|
+
height: number;
|
|
101
|
+
};
|
|
102
|
+
type WorkerInitMessage = {
|
|
103
|
+
type: "init";
|
|
104
|
+
isProduction: boolean;
|
|
105
|
+
config: WorkerConfig;
|
|
106
|
+
};
|
|
107
|
+
type WorkerDetectMessage = {
|
|
108
|
+
type: "detect";
|
|
109
|
+
dimensions: ImageDimensions$1;
|
|
110
|
+
threshold?: number;
|
|
111
|
+
bitmap: ImageBitmap;
|
|
112
|
+
};
|
|
113
|
+
type WorkerReadyMessage = {
|
|
114
|
+
type: "ready";
|
|
115
|
+
};
|
|
116
|
+
type WorkerProgressMessage = {
|
|
117
|
+
type: "loading_progress";
|
|
118
|
+
progress: number;
|
|
119
|
+
file: string;
|
|
120
|
+
};
|
|
121
|
+
type WorkerErrorMessage = {
|
|
122
|
+
type: "error";
|
|
123
|
+
error_message: string;
|
|
124
|
+
};
|
|
125
|
+
type WorkerDetectResponseMessage = {
|
|
126
|
+
type: "detect_response";
|
|
127
|
+
bitmap?: ImageBitmap;
|
|
128
|
+
stats: DetectionStats;
|
|
129
|
+
segmentedImages?: ImageBitmap[];
|
|
130
|
+
};
|
|
131
|
+
type WorkerDebugMessage = {
|
|
132
|
+
type: "debug";
|
|
133
|
+
debug_message: string;
|
|
134
|
+
};
|
|
135
|
+
type WorkerPostMessage = WorkerInitMessage | WorkerDetectMessage;
|
|
136
|
+
type WorkerResponseMessage = WorkerReadyMessage | WorkerProgressMessage | WorkerErrorMessage | WorkerDetectResponseMessage | WorkerDetectMessage;
|
|
137
|
+
|
|
138
|
+
interface ImageDimensions {
|
|
139
|
+
width: number;
|
|
140
|
+
height: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Simplified hook for jersey detection worker
|
|
144
|
+
* Manages worker lifecycle, state, and detection requests
|
|
145
|
+
*/
|
|
146
|
+
declare function useJerseyWorker(config: WorkerConfig, workerUrlProp?: string): {
|
|
147
|
+
isReady: boolean;
|
|
148
|
+
workerReady: boolean;
|
|
149
|
+
lastError: string | null;
|
|
150
|
+
detect: (bitmap: ImageBitmap, dimensions: ImageDimensions, threshold?: number) => Promise<any>;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export { DEFAULT_CONFIG, type DetectionStats, type ImageDimensions$1 as ImageDimensions, type ImageSegmentationType, type ImagesToReturn, JerseyDetector, type JerseyDetectorHandle, type JerseyDetectorProps, type ModelType, type ObjectDetectionType, type TaskType, type WorkerConfig, type WorkerDebugMessage, type WorkerDetectMessage, type WorkerDetectResponseMessage, type WorkerErrorMessage, type WorkerInitMessage, type WorkerPostMessage, type WorkerProgressMessage, type WorkerReadyMessage, type WorkerResponseMessage, useJerseyWorker };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
type TaskType = "object-detection" | "image-segmentation";
|
|
4
|
+
type ModelType = "BodyPix";
|
|
5
|
+
type ObjectDetectionType = {
|
|
6
|
+
score: number;
|
|
7
|
+
label: string;
|
|
8
|
+
box: {
|
|
9
|
+
xmin: number;
|
|
10
|
+
ymin: number;
|
|
11
|
+
xmax: number;
|
|
12
|
+
ymax: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type ImageSegmentationType = {
|
|
16
|
+
label: string;
|
|
17
|
+
score?: number;
|
|
18
|
+
mask: any;
|
|
19
|
+
};
|
|
20
|
+
type ImagesToReturn = "mask" | "mask_with_image" | "none";
|
|
21
|
+
declare const DEFAULT_CONFIG: {
|
|
22
|
+
TASK: TaskType;
|
|
23
|
+
MODEL: ModelType;
|
|
24
|
+
BODYPIX_ARCHITECTURE: "MobileNetV1" | "ResNet50";
|
|
25
|
+
BODYPIX_MULTIPLIER: number;
|
|
26
|
+
BODYPIX_QUANT_BYTES: number;
|
|
27
|
+
BODYPIX_STRIDE: number;
|
|
28
|
+
MULTI_SEGMENTATION: boolean;
|
|
29
|
+
SEGMENT_BODY_PARTS: boolean;
|
|
30
|
+
BACKGROUND_SHADE: number;
|
|
31
|
+
SHIRT_SHADE: number;
|
|
32
|
+
DETECTION_THRESHOLD: number;
|
|
33
|
+
TARGET_PART_ID: number;
|
|
34
|
+
IMAGES_TO_RETURN: ImagesToReturn;
|
|
35
|
+
VERBOSE: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Detection statistics interface
|
|
40
|
+
*/
|
|
41
|
+
interface DetectionStats {
|
|
42
|
+
/** Number of detections found */
|
|
43
|
+
jerseyCount: number;
|
|
44
|
+
/** Average confidence score (0-100) */
|
|
45
|
+
confidence: number;
|
|
46
|
+
/** Processing time in milliseconds */
|
|
47
|
+
processingTime: number;
|
|
48
|
+
/** Frames per second */
|
|
49
|
+
fps: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface JerseyDetectorHandle {
|
|
53
|
+
isReady: boolean;
|
|
54
|
+
stats: DetectionStats;
|
|
55
|
+
lastError: string | null;
|
|
56
|
+
capture: (format?: "image/jpeg" | "image/png", quality?: number) => string;
|
|
57
|
+
}
|
|
58
|
+
interface JerseyDetectorProps {
|
|
59
|
+
videoRef: React.RefObject<HTMLVideoElement>;
|
|
60
|
+
onWorkerReady?: (ready: boolean) => void;
|
|
61
|
+
onWorkerError?: (error: string | null) => void;
|
|
62
|
+
onStatsUpdate?: (stats: DetectionStats) => void;
|
|
63
|
+
onSegmentedImage?: (segmentedImages: ImageBitmap[]) => void;
|
|
64
|
+
task?: TaskType;
|
|
65
|
+
model?: ModelType;
|
|
66
|
+
verbose?: boolean;
|
|
67
|
+
bodyPixArchitecture?: "MobileNetV1" | "ResNet50";
|
|
68
|
+
bodyPixMultiplier?: number;
|
|
69
|
+
bodyPixQuantBytes?: number;
|
|
70
|
+
bodyPixStride?: number;
|
|
71
|
+
multiSegmentation?: boolean;
|
|
72
|
+
segmentBodyParts?: boolean;
|
|
73
|
+
backgroundShade?: number;
|
|
74
|
+
shirtShade?: number;
|
|
75
|
+
threshold?: number;
|
|
76
|
+
targetPartId?: number;
|
|
77
|
+
imagesToReturn?: ImagesToReturn;
|
|
78
|
+
workerUrl?: string;
|
|
79
|
+
}
|
|
80
|
+
declare const JerseyDetector: react.ForwardRefExoticComponent<JerseyDetectorProps & react.RefAttributes<JerseyDetectorHandle>>;
|
|
81
|
+
|
|
82
|
+
type WorkerConfig = {
|
|
83
|
+
task: TaskType;
|
|
84
|
+
model: ModelType;
|
|
85
|
+
verbose: boolean;
|
|
86
|
+
bodyPixArchitecture?: 'MobileNetV1' | 'ResNet50';
|
|
87
|
+
bodyPixMultiplier?: number;
|
|
88
|
+
bodyPixQuantBytes?: number;
|
|
89
|
+
bodyPixStride?: number;
|
|
90
|
+
multiSegmentation?: boolean;
|
|
91
|
+
segmentBodyParts?: boolean;
|
|
92
|
+
backgroundShade?: number;
|
|
93
|
+
shirtShade?: number;
|
|
94
|
+
threshold?: number;
|
|
95
|
+
targetPartId?: number;
|
|
96
|
+
imagesToReturn?: ImagesToReturn;
|
|
97
|
+
};
|
|
98
|
+
type ImageDimensions$1 = {
|
|
99
|
+
width: number;
|
|
100
|
+
height: number;
|
|
101
|
+
};
|
|
102
|
+
type WorkerInitMessage = {
|
|
103
|
+
type: "init";
|
|
104
|
+
isProduction: boolean;
|
|
105
|
+
config: WorkerConfig;
|
|
106
|
+
};
|
|
107
|
+
type WorkerDetectMessage = {
|
|
108
|
+
type: "detect";
|
|
109
|
+
dimensions: ImageDimensions$1;
|
|
110
|
+
threshold?: number;
|
|
111
|
+
bitmap: ImageBitmap;
|
|
112
|
+
};
|
|
113
|
+
type WorkerReadyMessage = {
|
|
114
|
+
type: "ready";
|
|
115
|
+
};
|
|
116
|
+
type WorkerProgressMessage = {
|
|
117
|
+
type: "loading_progress";
|
|
118
|
+
progress: number;
|
|
119
|
+
file: string;
|
|
120
|
+
};
|
|
121
|
+
type WorkerErrorMessage = {
|
|
122
|
+
type: "error";
|
|
123
|
+
error_message: string;
|
|
124
|
+
};
|
|
125
|
+
type WorkerDetectResponseMessage = {
|
|
126
|
+
type: "detect_response";
|
|
127
|
+
bitmap?: ImageBitmap;
|
|
128
|
+
stats: DetectionStats;
|
|
129
|
+
segmentedImages?: ImageBitmap[];
|
|
130
|
+
};
|
|
131
|
+
type WorkerDebugMessage = {
|
|
132
|
+
type: "debug";
|
|
133
|
+
debug_message: string;
|
|
134
|
+
};
|
|
135
|
+
type WorkerPostMessage = WorkerInitMessage | WorkerDetectMessage;
|
|
136
|
+
type WorkerResponseMessage = WorkerReadyMessage | WorkerProgressMessage | WorkerErrorMessage | WorkerDetectResponseMessage | WorkerDetectMessage;
|
|
137
|
+
|
|
138
|
+
interface ImageDimensions {
|
|
139
|
+
width: number;
|
|
140
|
+
height: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Simplified hook for jersey detection worker
|
|
144
|
+
* Manages worker lifecycle, state, and detection requests
|
|
145
|
+
*/
|
|
146
|
+
declare function useJerseyWorker(config: WorkerConfig, workerUrlProp?: string): {
|
|
147
|
+
isReady: boolean;
|
|
148
|
+
workerReady: boolean;
|
|
149
|
+
lastError: string | null;
|
|
150
|
+
detect: (bitmap: ImageBitmap, dimensions: ImageDimensions, threshold?: number) => Promise<any>;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export { DEFAULT_CONFIG, type DetectionStats, type ImageDimensions$1 as ImageDimensions, type ImageSegmentationType, type ImagesToReturn, JerseyDetector, type JerseyDetectorHandle, type JerseyDetectorProps, type ModelType, type ObjectDetectionType, type TaskType, type WorkerConfig, type WorkerDebugMessage, type WorkerDetectMessage, type WorkerDetectResponseMessage, type WorkerErrorMessage, type WorkerInitMessage, type WorkerPostMessage, type WorkerProgressMessage, type WorkerReadyMessage, type WorkerResponseMessage, useJerseyWorker };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var K=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var he=Object.prototype.hasOwnProperty;var De=(e,n)=>{for(var u in n)K(e,u,{get:n[u],enumerable:!0})},be=(e,n,u,y)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of Ee(n))!he.call(e,s)&&s!==u&&K(e,s,{get:()=>n[s],enumerable:!(y=Te(n,s))||y.enumerable});return e};var ke=e=>be(K({},"__esModule",{value:!0}),e);var W=(e,n,u)=>new Promise((y,s)=>{var O=l=>{try{D(u.next(l))}catch(b){s(b)}},E=l=>{try{D(u.throw(l))}catch(b){s(b)}},D=l=>l.done?y(l.value):Promise.resolve(l.value).then(O,E);D((u=u.apply(e,n)).next())});var we={};De(we,{DEFAULT_CONFIG:()=>c,JerseyDetector:()=>ee,useJerseyWorker:()=>$});module.exports=ke(we);var t=require("react");var f=require("react");var m=null,v=!1,F=null,Q=0,Z=null,T=new Map,Ie=0,X=new Map;function $(e,n){let u=(0,f.useRef)(!1),[y,s]=(0,f.useState)(!1),[O,E]=(0,f.useState)(null),D=(0,f.useRef)(!0),l=(0,f.useRef)(!1),b=(0,f.useRef)(`instance_${Math.random().toString(36).substr(2,9)}`),A=(0,f.useRef)(0);(0,f.useEffect)(()=>{var w;if(!e)return;D.current=!0,A.current++;let R=A.current,M=b.current,N=(w=X.get(M))!=null?w:0;return R>N&&(Q++,X.set(M,R)),W(null,null,function*(){var d;if(!m||!Re(Z,e)){m&&(m.terminate(),m=null,v=!1);try{l.current=(d=e.verbose)!=null?d:l.current;let a=n||"/jersey-detector-worker.js";m=new Worker(a),Z=e,v=!1,F=null,s(!1),E(null),m.onmessage=g=>{let i=g.data;switch(i.type){case"ready":v=!0,s(!0);break;case"loading_progress":l.current&&console.log(`[v0 useJerseyWorker] Loaded ${i.progress}% of ${i.file}`);break;case"debug":l.current&&console.log(i.debug_message);break;case"error":let _=i.error_message||"Unknown worker error";console.error("[v0 useJerseyWorker] Worker sent error message:",_),v=!1,F=_,s(!1),E(_);break;case"detect_response":if(i.requestId&&T.has(i.requestId)){let p=T.get(i.requestId);p&&(p.resolve(i),T.delete(i.requestId))}else if(T.size>0){let p=T.entries().next();if(!p.done){let[B,x]=p.value;x.resolve(i),T.delete(B)}}break}},m.onerror=g=>{let i=g.message||"Worker initialization error";console.error("[useJerseyWorker] Worker error:",i),v=!1,F=i,s(!1),E(i)},m.postMessage({type:"init",config:e})}catch(a){let g=(a==null?void 0:a.message)||String(a);console.error("[useJerseyWorker] Failed to create worker:",g),s(!1),E(g)}}else s(v),E(F)}),()=>{D.current=!1;let d=b.current,a=X.get(d),g=A.current;a===g&&(Q--,X.delete(d),Q<=0&&m&&(m.terminate(),m=null,v=!1,F=null,Z=null,T.clear()))}},[]);let G=(0,f.useCallback)((R,M,N=.5)=>W(null,null,function*(){if(!m||!v)throw new Error("Worker not ready");if(u.current)return null;let k=`req_${++Ie}_${Date.now()}`;return new Promise((w,d)=>{T.set(k,{resolve:w,reject:d});try{u.current=!0,m.postMessage({type:"detect",requestId:k,dimensions:M,bitmap:R,threshold:N},[R])}catch(a){T.delete(k);let g=`Failed to send detect: ${a==null?void 0:a.message}`;d(new Error(g))}finally{u.current=!1}setTimeout(()=>{T.has(k)&&(T.delete(k),d(new Error("Detection timeout")))},1e4)})}),[y]);return{isReady:y,workerReady:y,lastError:O,detect:G}}function Re(e,n){return e?JSON.stringify(e)===JSON.stringify(n):!1}var c={TASK:"image-segmentation",MODEL:"BodyPix",BODYPIX_ARCHITECTURE:"MobileNetV1",BODYPIX_MULTIPLIER:.75,BODYPIX_QUANT_BYTES:2,BODYPIX_STRIDE:16,MULTI_SEGMENTATION:!0,SEGMENT_BODY_PARTS:!0,BACKGROUND_SHADE:0,SHIRT_SHADE:170,DETECTION_THRESHOLD:.5,TARGET_PART_ID:12,IMAGES_TO_RETURN:"mask",VERBOSE:!1};var ue=require("react/jsx-runtime"),ee=(0,t.forwardRef)(({videoRef:e,onWorkerReady:n,onWorkerError:u,onStatsUpdate:y,onSegmentedImage:s,task:O=c.TASK,model:E=c.MODEL,verbose:D=c.VERBOSE,bodyPixArchitecture:l=c.BODYPIX_ARCHITECTURE,bodyPixMultiplier:b=c.BODYPIX_MULTIPLIER,bodyPixQuantBytes:A=c.BODYPIX_QUANT_BYTES,bodyPixStride:G=c.BODYPIX_STRIDE,multiSegmentation:R=c.MULTI_SEGMENTATION,segmentBodyParts:M=c.SEGMENT_BODY_PARTS,backgroundShade:N=c.BACKGROUND_SHADE,shirtShade:k=c.SHIRT_SHADE,threshold:w=c.DETECTION_THRESHOLD,targetPartId:d=c.TARGET_PART_ID,imagesToReturn:a=c.IMAGES_TO_RETURN,workerUrl:g},i)=>{var te,ne;let _=(0,t.useRef)(null),p=(0,t.useRef)(null),B=(0,t.useRef)(!1),x=(0,t.useRef)([]),le=(0,t.useRef)(null),J=(0,t.useRef)(!1),Y=(0,t.useRef)(void 0);Y.current=u;let z=(0,t.useRef)({jerseyCount:0,confidence:0,fps:0,processingTime:0}),re=(0,t.useRef)(0),me=500,fe=(0,t.useMemo)(()=>({task:O,model:E,verbose:D,bodyPixArchitecture:l,bodyPixMultiplier:b,bodyPixQuantBytes:A,bodyPixStride:G,multiSegmentation:R,segmentBodyParts:M,backgroundShade:N,shirtShade:k,threshold:w,targetPartId:d,imagesToReturn:a}),[O,E,D,l,b,A,G,R,M,N,k,w,d,a]),de=(0,t.useMemo)(()=>{var r,o;return{width:((r=e.current)==null?void 0:r.videoWidth)||0,height:((o=e.current)==null?void 0:o.videoHeight)||0}},[(te=e.current)==null?void 0:te.videoWidth,(ne=e.current)==null?void 0:ne.videoHeight]),{isReady:H,workerReady:S,lastError:L,detect:ge}=$(fe,g);(0,t.useEffect)(()=>{n==null||n(S)},[S,n]),(0,t.useEffect)(()=>{var r;L&&(J.current=!0,(r=Y.current)==null||r.call(Y,L))},[L]);let ye=()=>W(null,null,function*(){var se,oe,ie;let r=e.current,o=_.current;if(J.current||!H||!S||!r||!o||B.current||r.readyState<2||r.paused||r.ended||r.videoWidth===0||r.videoHeight===0)return;let I=o.getContext("2d");if(!I||o.width<=0||o.height<=0)return;let C=null,P=null;try{B.current=!0;let U=r.videoWidth,j=r.videoHeight;le.current={width:U,height:j},C=yield createImageBitmap(r);let h=yield ge(C,de,w);if((h==null?void 0:h.type)==="detect_response"&&h.bitmap){P=h.bitmap,(o.width!==U||o.height!==j)&&(o.width=U,o.height=j),a==="mask"&&I.clearRect(0,0,U,j),P&&I.drawImage(P,0,0),x.current.push(Date.now()),x.current=x.current.filter(V=>Date.now()-V<1e3);let q={jerseyCount:((se=h.stats)==null?void 0:se.detectionCount)||0,confidence:((oe=h.stats)==null?void 0:oe.averageConfidence)||0,fps:x.current.length,processingTime:((ie=h.stats)==null?void 0:ie.processingTime)||0},ae=z.current;z.current=q;let ce=Date.now();if((ce-re.current>me||q.jerseyCount!==ae.jerseyCount||q.confidence!==ae.confidence)&&y&&(y(q),re.current=ce),h.segmentedImages){let V=h.segmentedImages;W(null,null,function*(){try{yield s==null?void 0:s(V)}finally{V.forEach(pe=>pe.close())}})}}}catch(U){J.current=!0}finally{C==null||C.close(),P==null||P.close(),B.current=!1}});return(0,t.useImperativeHandle)(i,()=>({get isReady(){return H},get lastError(){return L},get stats(){return z.current},capture:(r="image/jpeg",o=.92)=>{let I=_.current;if(!I)throw new Error("Canvas not ready for capture");return I.toDataURL(r,o)}}),[H,L,S]),(0,t.useEffect)(()=>{if(!S||!H||J.current)return;let r=e.current,o=_.current;if(!r||!o||r.videoWidth===0||r.videoHeight===0){let C=setTimeout(()=>{p.current=requestAnimationFrame(()=>{})},100);return()=>clearTimeout(C)}(o.width!==r.videoWidth||o.height!==r.videoHeight)&&(o.width=r.videoWidth,o.height=r.videoHeight);let I=()=>W(null,null,function*(){!S||!H||J.current||(yield ye(),p.current=requestAnimationFrame(I))});return p.current=requestAnimationFrame(I),()=>{p.current&&cancelAnimationFrame(p.current)}},[S,H]),(0,ue.jsx)("canvas",{ref:_,className:"absolute inset-0 pointer-events-none",style:{zIndex:10,width:"100%",height:"100%"}})});ee.displayName="JerseyDetector";0&&(module.exports={DEFAULT_CONFIG,JerseyDetector,useJerseyWorker});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var C=(t,d,g)=>new Promise((k,a)=>{var W=o=>{try{T(g.next(o))}catch(E){a(E)}},y=o=>{try{T(g.throw(o))}catch(E){a(E)}},T=o=>o.done?k(o.value):Promise.resolve(o.value).then(W,y);T((g=g.apply(t,d)).next())});import{forwardRef as ke,useImperativeHandle as Ie,useRef as b,useEffect as Z,useMemo as ue}from"react";import{useEffect as Ee,useState as ce,useCallback as he,useRef as U}from"react";var c=null,_=!1,F=null,z=0,K=null,f=new Map,De=0,X=new Map;function Q(t,d){let g=U(!1),[k,a]=ce(!1),[W,y]=ce(null),T=U(!0),o=U(!1),E=U(`instance_${Math.random().toString(36).substr(2,9)}`),O=U(0);Ee(()=>{var R;if(!t)return;T.current=!0,O.current++;let I=O.current,v=E.current,A=(R=X.get(v))!=null?R:0;return I>A&&(z++,X.set(v,I)),C(null,null,function*(){var u;if(!c||!be(K,t)){c&&(c.terminate(),c=null,_=!1);try{o.current=(u=t.verbose)!=null?u:o.current;let s=d||"/jersey-detector-worker.js";c=new Worker(s),K=t,_=!1,F=null,a(!1),y(null),c.onmessage=l=>{let n=l.data;switch(n.type){case"ready":_=!0,a(!0);break;case"loading_progress":o.current&&console.log(`[v0 useJerseyWorker] Loaded ${n.progress}% of ${n.file}`);break;case"debug":o.current&&console.log(n.debug_message);break;case"error":let w=n.error_message||"Unknown worker error";console.error("[v0 useJerseyWorker] Worker sent error message:",w),_=!1,F=w,a(!1),y(w);break;case"detect_response":if(n.requestId&&f.has(n.requestId)){let m=f.get(n.requestId);m&&(m.resolve(n),f.delete(n.requestId))}else if(f.size>0){let m=f.entries().next();if(!m.done){let[P,N]=m.value;N.resolve(n),f.delete(P)}}break}},c.onerror=l=>{let n=l.message||"Worker initialization error";console.error("[useJerseyWorker] Worker error:",n),_=!1,F=n,a(!1),y(n)},c.postMessage({type:"init",config:t})}catch(s){let l=(s==null?void 0:s.message)||String(s);console.error("[useJerseyWorker] Failed to create worker:",l),a(!1),y(l)}}else a(_),y(F)}),()=>{T.current=!1;let u=E.current,s=X.get(u),l=O.current;s===l&&(z--,X.delete(u),z<=0&&c&&(c.terminate(),c=null,_=!1,F=null,K=null,f.clear()))}},[]);let G=he((I,v,A=.5)=>C(null,null,function*(){if(!c||!_)throw new Error("Worker not ready");if(g.current)return null;let h=`req_${++De}_${Date.now()}`;return new Promise((R,u)=>{f.set(h,{resolve:R,reject:u});try{g.current=!0,c.postMessage({type:"detect",requestId:h,dimensions:v,bitmap:I,threshold:A},[I])}catch(s){f.delete(h);let l=`Failed to send detect: ${s==null?void 0:s.message}`;u(new Error(l))}finally{g.current=!1}setTimeout(()=>{f.has(h)&&(f.delete(h),u(new Error("Detection timeout")))},1e4)})}),[k]);return{isReady:k,workerReady:k,lastError:W,detect:G}}function be(t,d){return t?JSON.stringify(t)===JSON.stringify(d):!1}var i={TASK:"image-segmentation",MODEL:"BodyPix",BODYPIX_ARCHITECTURE:"MobileNetV1",BODYPIX_MULTIPLIER:.75,BODYPIX_QUANT_BYTES:2,BODYPIX_STRIDE:16,MULTI_SEGMENTATION:!0,SEGMENT_BODY_PARTS:!0,BACKGROUND_SHADE:0,SHIRT_SHADE:170,DETECTION_THRESHOLD:.5,TARGET_PART_ID:12,IMAGES_TO_RETURN:"mask",VERBOSE:!1};import{jsx as Re}from"react/jsx-runtime";var le=ke(({videoRef:t,onWorkerReady:d,onWorkerError:g,onStatsUpdate:k,onSegmentedImage:a,task:W=i.TASK,model:y=i.MODEL,verbose:T=i.VERBOSE,bodyPixArchitecture:o=i.BODYPIX_ARCHITECTURE,bodyPixMultiplier:E=i.BODYPIX_MULTIPLIER,bodyPixQuantBytes:O=i.BODYPIX_QUANT_BYTES,bodyPixStride:G=i.BODYPIX_STRIDE,multiSegmentation:I=i.MULTI_SEGMENTATION,segmentBodyParts:v=i.SEGMENT_BODY_PARTS,backgroundShade:A=i.BACKGROUND_SHADE,shirtShade:h=i.SHIRT_SHADE,threshold:R=i.DETECTION_THRESHOLD,targetPartId:u=i.TARGET_PART_ID,imagesToReturn:s=i.IMAGES_TO_RETURN,workerUrl:l},n)=>{var re,te;let w=b(null),m=b(null),P=b(!1),N=b([]),me=b(null),B=b(!1),Y=b(void 0);Y.current=g;let $=b({jerseyCount:0,confidence:0,fps:0,processingTime:0}),ee=b(0),fe=500,de=ue(()=>({task:W,model:y,verbose:T,bodyPixArchitecture:o,bodyPixMultiplier:E,bodyPixQuantBytes:O,bodyPixStride:G,multiSegmentation:I,segmentBodyParts:v,backgroundShade:A,shirtShade:h,threshold:R,targetPartId:u,imagesToReturn:s}),[W,y,T,o,E,O,G,I,v,A,h,R,u,s]),ge=ue(()=>{var e,r;return{width:((e=t.current)==null?void 0:e.videoWidth)||0,height:((r=t.current)==null?void 0:r.videoHeight)||0}},[(re=t.current)==null?void 0:re.videoWidth,(te=t.current)==null?void 0:te.videoHeight]),{isReady:x,workerReady:M,lastError:J,detect:ye}=Q(de,l);Z(()=>{d==null||d(M)},[M,d]),Z(()=>{var e;J&&(B.current=!0,(e=Y.current)==null||e.call(Y,J))},[J]);let pe=()=>C(null,null,function*(){var ne,se,oe;let e=t.current,r=w.current;if(B.current||!x||!M||!e||!r||P.current||e.readyState<2||e.paused||e.ended||e.videoWidth===0||e.videoHeight===0)return;let D=r.getContext("2d");if(!D||r.width<=0||r.height<=0)return;let S=null,H=null;try{P.current=!0;let L=e.videoWidth,j=e.videoHeight;me.current={width:L,height:j},S=yield createImageBitmap(e);let p=yield ye(S,ge,R);if((p==null?void 0:p.type)==="detect_response"&&p.bitmap){H=p.bitmap,(r.width!==L||r.height!==j)&&(r.width=L,r.height=j),s==="mask"&&D.clearRect(0,0,L,j),H&&D.drawImage(H,0,0),N.current.push(Date.now()),N.current=N.current.filter(V=>Date.now()-V<1e3);let q={jerseyCount:((ne=p.stats)==null?void 0:ne.detectionCount)||0,confidence:((se=p.stats)==null?void 0:se.averageConfidence)||0,fps:N.current.length,processingTime:((oe=p.stats)==null?void 0:oe.processingTime)||0},ie=$.current;$.current=q;let ae=Date.now();if((ae-ee.current>fe||q.jerseyCount!==ie.jerseyCount||q.confidence!==ie.confidence)&&k&&(k(q),ee.current=ae),p.segmentedImages){let V=p.segmentedImages;C(null,null,function*(){try{yield a==null?void 0:a(V)}finally{V.forEach(Te=>Te.close())}})}}}catch(L){B.current=!0}finally{S==null||S.close(),H==null||H.close(),P.current=!1}});return Ie(n,()=>({get isReady(){return x},get lastError(){return J},get stats(){return $.current},capture:(e="image/jpeg",r=.92)=>{let D=w.current;if(!D)throw new Error("Canvas not ready for capture");return D.toDataURL(e,r)}}),[x,J,M]),Z(()=>{if(!M||!x||B.current)return;let e=t.current,r=w.current;if(!e||!r||e.videoWidth===0||e.videoHeight===0){let S=setTimeout(()=>{m.current=requestAnimationFrame(()=>{})},100);return()=>clearTimeout(S)}(r.width!==e.videoWidth||r.height!==e.videoHeight)&&(r.width=e.videoWidth,r.height=e.videoHeight);let D=()=>C(null,null,function*(){!M||!x||B.current||(yield pe(),m.current=requestAnimationFrame(D))});return m.current=requestAnimationFrame(D),()=>{m.current&&cancelAnimationFrame(m.current)}},[M,x]),Re("canvas",{ref:w,className:"absolute inset-0 pointer-events-none",style:{zIndex:10,width:"100%",height:"100%"}})});le.displayName="JerseyDetector";export{i as DEFAULT_CONFIG,le as JerseyDetector,Q as useJerseyWorker};
|