seg-cam 1.2.0 → 1.4.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/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var We=Object.create;var V=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames,ge=Object.getOwnPropertySymbols,Se=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty,Oe=Object.prototype.propertyIsEnumerable;var pe=(e,r,t)=>r in e?V(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,he=(e,r)=>{for(var t in r||(r={}))ye.call(r,t)&&pe(e,t,r[t]);if(ge)for(var t of ge(r))Oe.call(r,t)&&pe(e,t,r[t]);return e};var Ae=(e,r)=>{for(var t in r)V(e,t,{get:r[t],enumerable:!0})},Te=(e,r,t,E)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of Be(r))!ye.call(e,a)&&a!==t&&V(e,a,{get:()=>r[a],enumerable:!(E=xe(r,a))||E.enumerable});return e};var Ne=(e,r,t)=>(t=e!=null?We(Se(e)):{},Te(r||!e||!e.__esModule?V(t,"default",{value:e,enumerable:!0}):t,e)),Je=e=>Te(V({},"__esModule",{value:!0}),e);var B=(e,r,t)=>new Promise((E,a)=>{var S=d=>{try{I(t.next(d))}catch(R){a(R)}},k=d=>{try{I(t.throw(d))}catch(R){a(R)}},I=d=>d.done?E(d.value):Promise.resolve(d.value).then(S,k);I((t=t.apply(e,r)).next())});var Ue={};Ae(Ue,{DEFAULT_CONFIG:()=>l,JerseyDetector:()=>le,useJerseyWorker:()=>re});module.exports=Je(Ue);var i=require("react");var h=require("react");var y=null,M=!1,G=null,ce=0,ue=null,b=new Map,He=0,ee=new Map;function re(e,r){let t=(0,h.useRef)(!1),[E,a]=(0,h.useState)(!1),[S,k]=(0,h.useState)(null),I=(0,h.useRef)(!0),d=(0,h.useRef)(!1),R=(0,h.useRef)(`instance_${Math.random().toString(36).substr(2,9)}`),O=(0,h.useRef)(0);(0,h.useEffect)(()=>{var _;if(!e)return;I.current=!0,O.current++;let v=O.current,W=R.current,A=(_=ee.get(W))!=null?_:0;return v>A&&(ce++,ee.set(W,v)),B(null,null,function*(){var m;if(!y||!Pe(ue,e)){y&&(y.terminate(),y=null,M=!1,console.log("[v0 useJerseyWorker] Worker terminated because of change in config"));try{d.current=(m=e.verbose)!=null?m:d.current;let g=r||"/jersey-detector-worker.js";y=new Worker(g),ue=e,M=!1,G=null,a(!1),k(null),y.onmessage=f=>{let s=f.data;switch(s.type){case"ready":M=!0,a(!0),d.current&&console.log("[v0 useJerseyWorker] Worker Ready",{device:s.device,dtype:s.dtype,config:s.config});break;case"loading_progress":d.current&&console.log(`[v0 useJerseyWorker] Loaded ${s.progress}% of ${s.file}`);break;case"debug":d.current&&console.log(s.debug_message);break;case"error":let D=s.error_message||"Unknown worker error";console.error("[v0 useJerseyWorker] Worker sent error message:",D),M=!1,G=D,a(!1),k(D);break;case"detect_response":if(s.requestId&&b.has(s.requestId)){let x=b.get(s.requestId);x&&(x.resolve(s),b.delete(s.requestId))}else if(b.size>0){let x=b.entries().next();if(!x.done){let[te,p]=x.value;p.resolve(s),b.delete(te)}}break}},y.onerror=f=>{let s=f.message||"Worker initialization error";console.error("[useJerseyWorker] Worker error:",s),M=!1,G=s,a(!1),k(s)},y.postMessage({type:"init",config:e})}catch(g){let f=(g==null?void 0:g.message)||String(g);console.error("[useJerseyWorker] Failed to create worker:",f),a(!1),k(f)}}else a(M),k(G)}),()=>{I.current=!1;let m=R.current,g=ee.get(m),f=O.current;g===f&&(ce--,ee.delete(m),ce<=0&&y&&(y.terminate(),y=null,M=!1,G=null,ue=null,b.clear()))}},[]);let Y=(0,h.useCallback)((v,W,A=.5,P=!0,_)=>B(null,null,function*(){if(!y||!M)throw new Error("Worker not ready");if(t.current)return null;let m=`req_${++He}_${Date.now()}`;return new Promise((g,f)=>{b.set(m,{resolve:g,reject:f});try{t.current=!0,y.postMessage({type:"detect",requestId:m,dimensions:W,bitmap:v,threshold:A,includeSegmentedImages:P,lastJerseyCount:_},[v])}catch(s){b.delete(m);let D=`Failed to send detect: ${s==null?void 0:s.message}`;f(new Error(D))}finally{t.current=!1}setTimeout(()=>{b.has(m)&&(b.delete(m),f(new Error("Detection timeout")))},1e4)})}),[E]);return{isReady:E,workerReady:E,lastError:S,detect:Y}}function Pe(e,r){return e?JSON.stringify(e)===JSON.stringify(r):!1}var l={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,MIN_DETECTION_AREA:1e4};var Ee=Ne(require("p-limit"));var De=require("react/jsx-runtime"),le=(0,i.forwardRef)(({videoRef:e,onWorkerReady:r,onWorkerError:t,onStatsUpdate:E,onSegmentedImage:a,task:S=l.TASK,model:k=l.MODEL,verbose:I=l.VERBOSE,bodyPixArchitecture:d=l.BODYPIX_ARCHITECTURE,bodyPixMultiplier:R=l.BODYPIX_MULTIPLIER,bodyPixQuantBytes:O=l.BODYPIX_QUANT_BYTES,bodyPixStride:Y=l.BODYPIX_STRIDE,multiSegmentation:v=l.MULTI_SEGMENTATION,segmentBodyParts:W=l.SEGMENT_BODY_PARTS,backgroundShade:A=l.BACKGROUND_SHADE,shirtShade:P=l.SHIRT_SHADE,threshold:_=l.DETECTION_THRESHOLD,targetPartId:m=l.TARGET_PART_ID,imagesToReturn:g=l.IMAGES_TO_RETURN,minDetectionArea:f=l.MIN_DETECTION_AREA,throttleMs:s=1e3,onImageSegmentedLimit:D=2,workerUrl:x,className:te,style:p},be)=>{let q=(0,i.useRef)(null),U=(0,i.useRef)(null),ne=(0,i.useRef)(!1),X=(0,i.useRef)([]),ke=(0,i.useRef)(null),L=(0,i.useRef)(!1),$=(0,i.useRef)(void 0);$.current=t;let z=(0,i.useRef)({jerseyCount:0,confidence:0,fps:0,processingTime:0}),oe=(0,i.useRef)(0),se=(0,i.useMemo)(()=>(0,Ee.default)(D),[D]),K=(0,i.useMemo)(()=>({task:S,model:k,verbose:I,bodyPixArchitecture:d,bodyPixMultiplier:R,bodyPixQuantBytes:O,bodyPixStride:Y,multiSegmentation:v,segmentBodyParts:W,backgroundShade:A,shirtShade:P,threshold:_,targetPartId:m,imagesToReturn:g,minDetectionArea:f,mirror:(p==null?void 0:p.transform)==="scaleX(-1)"||typeof(p==null?void 0:p.transform)=="string"&&p.transform.includes("scaleX(-1)")}),[S,k,I,d,R,O,Y,v,W,A,P,_,m,g,f,p==null?void 0:p.transform]),Ie=()=>{var n,c;return{width:((n=e.current)==null?void 0:n.videoWidth)||0,height:((c=e.current)==null?void 0:c.videoHeight)||0}},{isReady:N,workerReady:C,lastError:j,detect:Re}=re(K,x);(0,i.useEffect)(()=>{C&&console.log("[JerseyDetector] Worker Ready with config:",K),r==null||r(C)},[C,r,K]),(0,i.useEffect)(()=>{var n;j&&(L.current=!0,(n=$.current)==null||n.call($,j))},[j]);let we=(0,i.useCallback)((n,c)=>{if(se.activeCount>=D){n.forEach(o=>{var u;return(u=o==null?void 0:o.close)==null?void 0:u.call(o)}),console.warn(`[JerseyDetector] Dropped new segmented images \u2014 max ${D} classifications running`);return}se(()=>B(null,null,function*(){try{a==null||a(n,c)}catch(o){console.error("[JerseyDetector] Classification error:",o)}finally{n.forEach(o=>{var u;return(u=o==null?void 0:o.close)==null?void 0:u.call(o)})}}))},[a,D,se]),ve=()=>B(null,null,function*(){var J,ie,de;let n=e.current,c=q.current;if(L.current||!N||!C||!n||!c||ne.current||n.readyState<2||n.paused||n.ended||n.videoWidth===0||n.videoHeight===0)return;let o=c.getContext("2d");if(!o||c.width<=0||c.height<=0)return;let u=null,w=null;try{ne.current=!0;let F=n.videoWidth,Q=n.videoHeight;ke.current={width:F,height:Q},u=yield createImageBitmap(n);let _e=Ie(),ae=Date.now(),Ce=ae-oe.current>s,Me=z.current.jerseyCount,T=yield Re(u,_e,_,Ce,Me);if((T==null?void 0:T.type)==="detect_response"){if(g!=="none"&&((c.width!==F||c.height!==Q)&&(c.width=F,c.height=Q),o.clearRect(0,0,F,Q),T.bitmap)){let H=T.bitmap;o.drawImage(H,0,0),console.log(`[JerseyDetector] Bitmap created with dims ${H.width}x${H.height}`),H.close()}X.current.push(Date.now()),X.current=X.current.filter(H=>Date.now()-H<1e3);let Z={jerseyCount:((J=T.stats)==null?void 0:J.jerseyCount)||0,confidence:((ie=T.stats)==null?void 0:ie.confidence)||0,fps:X.current.length,processingTime:((de=T.stats)==null?void 0:de.processingTime)||0},fe=z.current;z.current=Z;let me=ae-oe.current>s||Z.jerseyCount!==fe.jerseyCount||Z.confidence!==fe.confidence;me&&E&&(E(Z),oe.current=ae),me&&T.segmentedImages&&T.segmentedImages.length>0&&a&&we(T.segmentedImages,T.bboxes)}}catch(F){L.current=!0}finally{u==null||u.close(),ne.current=!1}});return(0,i.useImperativeHandle)(be,()=>({get isReady(){return N},get lastError(){return j},get stats(){return z.current},capture:(n="image/jpeg",c=.92)=>{let o=e.current,u=q.current;if(!o||o.videoWidth<=0||o.videoHeight<=0)throw new Error("Video not ready for capture");let w=document.createElement("canvas");w.width=o.videoWidth,w.height=o.videoHeight;let J=w.getContext("2d");if(!J)throw new Error("Failed to get context for capture canvas");let ie=K.mirror;return J.drawImage(o,0,0,w.width,w.height),u&&u.width>0&&u.height>0&&J.drawImage(u,0,0,w.width,w.height),w.toDataURL(n,c)}}),[N,j,C]),(0,i.useEffect)(()=>{if(!C||!N||L.current)return;let n=e.current,c=q.current;if(!n||!c||n.videoWidth===0||n.videoHeight===0){let u=setTimeout(()=>{U.current=requestAnimationFrame(()=>{})},100);return()=>clearTimeout(u)}(c.width!==n.videoWidth||c.height!==n.videoHeight)&&(c.width=n.videoWidth,c.height=n.videoHeight);let o=()=>B(null,null,function*(){!C||!N||L.current||(yield ve(),U.current=requestAnimationFrame(o))});return U.current=requestAnimationFrame(o),()=>{U.current&&cancelAnimationFrame(U.current)}},[C,N]),(0,De.jsx)("canvas",{ref:q,className:`absolute inset-0 pointer-events-none ${te||""}`,style:he({zIndex:10,width:"100%",height:"100%"},p)})});le.displayName="JerseyDetector";0&&(module.exports={DEFAULT_CONFIG,JerseyDetector,useJerseyWorker});
1
+ "use strict";var Se=Object.create;var Y=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames,ye=Object.getOwnPropertySymbols,Ne=Object.getPrototypeOf,Ee=Object.prototype.hasOwnProperty,He=Object.prototype.propertyIsEnumerable;var De=(e,r,t)=>r in e?Y(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,Re=(e,r)=>{for(var t in r||(r={}))Ee.call(r,t)&&De(e,t,r[t]);if(ye)for(var t of ye(r))He.call(r,t)&&De(e,t,r[t]);return e};var Je=(e,r)=>{for(var t in r)Y(e,t,{get:r[t],enumerable:!0})},Ie=(e,r,t,y)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of Ae(r))!Ee.call(e,a)&&a!==t&&Y(e,a,{get:()=>r[a],enumerable:!(y=Oe(r,a))||y.enumerable});return e};var Pe=(e,r,t)=>(t=e!=null?Se(Ne(e)):{},Ie(r||!e||!e.__esModule?Y(t,"default",{value:e,enumerable:!0}):t,e)),je=e=>Ie(Y({},"__esModule",{value:!0}),e);var S=(e,r,t)=>new Promise((y,a)=>{var O=h=>{try{k(t.next(h))}catch(v){a(v)}},R=h=>{try{k(t.throw(h))}catch(v){a(v)}},k=h=>h.done?y(h.value):Promise.resolve(h.value).then(O,R);k((t=t.apply(e,r)).next())});var Le={};Je(Le,{DEFAULT_CONFIG:()=>m,JerseyDetector:()=>ge,useJerseyWorker:()=>se});module.exports=je(Le);var s=require("react");var p=require("react");var f=null,_=!1,q=null,de=0,ne=null,E=new Map,Ue=0,oe=new Map;function se(e,r){let t=(0,p.useRef)(!1),[y,a]=(0,p.useState)(!1),[O,R]=(0,p.useState)(null),k=(0,p.useRef)(!0),h=(0,p.useRef)(!1),v=(0,p.useRef)(`instance_${Math.random().toString(36).substr(2,9)}`),A=(0,p.useRef)(0),[U,X]=(0,p.useState)(0);(0,p.useEffect)(()=>{var M;if(!e)return;k.current=!0,A.current++;let I=A.current,b=v.current,N=(M=oe.get(b))!=null?M:0;return I>N&&(de++,oe.set(b,I)),S(null,null,function*(){var T;if(!f||!Ve(ne,e)){f&&(f.terminate(),f=null,_=!1,console.log("[v0 useJerseyWorker] Worker terminated because of change in config or watchdog"));try{h.current=(T=e.verbose)!=null?T:h.current;let d=r||"/jersey-detector-worker.js";f=new Worker(d),ne=e,_=!1,q=null,a(!1),R(null),f.onmessage=w=>{let u=w.data;switch(u.type){case"ready":_=!0,a(!0);break;case"debug":h.current&&console.log(u.debug_message);break;case"error":let l=u.error_message||"Unknown worker error";console.error("[v0 useJerseyWorker] Worker sent error message:",l),_=!1,q=l,a(!1),R(l);break;case"detect_response":if(u.requestId&&E.has(u.requestId)){let W=E.get(u.requestId);W==null||W.resolve(u),E.delete(u.requestId)}break}},f.onerror=w=>{let u=w.message||"Worker initialization error";_=!1,q=u,a(!1),R(u)},f.postMessage({type:"init",config:e})}catch(d){a(!1),R((d==null?void 0:d.message)||String(d))}}else a(_),R(q)}),()=>{k.current=!1;let T=v.current,d=oe.get(T),w=A.current;d===w&&(de--,oe.delete(T),de<=0&&f&&(f.terminate(),f=null,_=!1,q=null,ne=null,E.clear()))}},[e,r,U]);let x=(0,p.useRef)(0);(0,p.useEffect)(()=>{if(!f)return;let I=setInterval(()=>{E.size>0?x.current>=3&&(console.error("[v0 useJerseyWorker] Watchdog: Worker appears hung after 3 consecutive timeouts. Restarting..."),x.current=0,f&&(f.terminate(),f=null,_=!1,ne=null,a(!1),X(b=>b+1))):x.current=0},2e3);return()=>clearInterval(I)},[y,U]);let z=(0,p.useCallback)((I,b,N=.5,H=!0,M)=>S(null,null,function*(){if(!f||!_)return null;if(t.current||E.size>0)return h.current,null;let T=`req_${++Ue}_${Date.now()}`;return new Promise((d,w)=>{let u=setTimeout(()=>{if(E.has(T)){x.current++;let g=E.get(T);g==null||g.reject(new Error("Detection timeout")),E.delete(T),t.current=!1}},5e3),l=g=>{x.current=0,clearTimeout(u),t.current=!1,d(g)},W=g=>{clearTimeout(u),t.current=!1,w(g)};E.set(T,{resolve:l,reject:W});try{t.current=!0,f.postMessage({type:"detect",requestId:T,dimensions:b,bitmap:I,threshold:N,includeSegmentedImages:H,lastJerseyCount:M},[I])}catch(g){clearTimeout(u),E.delete(T),t.current=!1,w(new Error(`Failed to send detect: ${g==null?void 0:g.message}`))}})}),[y]);return{isReady:y,workerReady:y,lastError:O,detect:z}}function Ve(e,r){return e?JSON.stringify(e)===JSON.stringify(r):!1}var m={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,MIN_DETECTION_AREA:1e4};var be=Pe(require("p-limit"));var we=require("react/jsx-runtime"),ge=(0,s.forwardRef)(({videoRef:e,onWorkerReady:r,onWorkerError:t,onStatsUpdate:y,onSegmentedImage:a,task:O=m.TASK,model:R=m.MODEL,verbose:k=m.VERBOSE,bodyPixArchitecture:h=m.BODYPIX_ARCHITECTURE,bodyPixMultiplier:v=m.BODYPIX_MULTIPLIER,bodyPixQuantBytes:A=m.BODYPIX_QUANT_BYTES,bodyPixStride:U=m.BODYPIX_STRIDE,multiSegmentation:X=m.MULTI_SEGMENTATION,segmentBodyParts:x=m.SEGMENT_BODY_PARTS,backgroundShade:z=m.BACKGROUND_SHADE,shirtShade:I=m.SHIRT_SHADE,threshold:b=m.DETECTION_THRESHOLD,targetPartId:N=m.TARGET_PART_ID,imagesToReturn:H=m.IMAGES_TO_RETURN,minDetectionArea:M=m.MIN_DETECTION_AREA,throttleMs:T=1e3,onImageSegmentedLimit:d=2,workerUrl:w,className:u,style:l},W)=>{let g=(0,s.useRef)(null),ae=(0,s.useRef)(null),V=(0,s.useRef)(null),$=(0,s.useRef)(!1),L=(0,s.useRef)(null),ie=(0,s.useRef)(!1),K=(0,s.useRef)([]),ke=(0,s.useRef)(null),Q=(0,s.useRef)(!1),Z=(0,s.useRef)(void 0);Z.current=t;let ee=(0,s.useRef)({jerseyCount:0,confidence:0,fps:0,processingTime:0}),ce=(0,s.useRef)(0),ue=(0,s.useMemo)(()=>(0,be.default)(d),[d]),re=(0,s.useMemo)(()=>({task:O,model:R,verbose:k,bodyPixArchitecture:h,bodyPixMultiplier:v,bodyPixQuantBytes:A,bodyPixStride:U,multiSegmentation:X,segmentBodyParts:x,backgroundShade:z,shirtShade:I,threshold:b,targetPartId:N,imagesToReturn:H,minDetectionArea:M,mirror:(l==null?void 0:l.transform)==="scaleX(-1)"||typeof(l==null?void 0:l.transform)=="string"&&l.transform.includes("scaleX(-1)")}),[O,R,k,h,v,A,U,X,x,z,I,b,N,H,M,l==null?void 0:l.transform]),ve=()=>{var n,i;return{width:((n=e.current)==null?void 0:n.videoWidth)||0,height:((i=e.current)==null?void 0:i.videoHeight)||0}},{isReady:J,workerReady:B,lastError:F,detect:Ce}=se(re,w);(0,s.useEffect)(()=>{B&&(console.log("[JerseyDetector] Worker Ready with config:",re),Q.current=!1),r==null||r(B)},[B,r,re]),(0,s.useEffect)(()=>{var n;F&&((n=Z.current)==null||n.call(Z,F))},[F]);let _e=(0,s.useCallback)((n,i)=>{if(ue.activeCount>=d){n.forEach(o=>{var c;return(c=o==null?void 0:o.close)==null?void 0:c.call(o)}),console.warn(`[JerseyDetector] Dropped new segmented images \u2014 max ${d} classifications running`);return}ue(()=>S(null,null,function*(){try{a==null||a(n,i)}catch(o){console.error("[JerseyDetector] Classification error:",o)}finally{n.forEach(o=>{var c;return(c=o==null?void 0:o.close)==null?void 0:c.call(o)})}}))},[a,d,ue]),xe=()=>S(null,null,function*(){var P,le,pe;let n=e.current,i=g.current;if(Q.current||!J||!B||!n||!i||ie.current||n.readyState<2||n.paused||n.ended||n.videoWidth===0||n.videoHeight===0)return;!V.current&&!ae.current&&(V.current=i.getContext("bitmaprenderer"),$.current=!!V.current,$.current||(ae.current=i.getContext("2d")));let o=ae.current;if(!$.current&&!o||i.width<=0||i.height<=0)return;let c=null,C=null;try{ie.current=!0;let G=n.videoWidth,fe=n.videoHeight;ke.current={width:G,height:fe},c=yield createImageBitmap(n);let Be=ve(),me=Date.now(),Me=me-ce.current>T,We=ee.current.jerseyCount,D=yield Ce(c,Be,b,Me,We);if((D==null?void 0:D.type)==="detect_response"){if(H!=="none"&&((i.width!==G||i.height!==fe)&&(i.width=G,i.height=fe),D.bitmap)){let j=D.bitmap;$.current&&V.current?V.current.transferFromImageBitmap(j):(o&&o.drawImage(j,0,0),j.close())}K.current.push(Date.now()),K.current=K.current.filter(j=>Date.now()-j<1e3);let te={jerseyCount:((P=D.stats)==null?void 0:P.jerseyCount)||0,confidence:((le=D.stats)==null?void 0:le.confidence)||0,fps:K.current.length,processingTime:((pe=D.stats)==null?void 0:pe.processingTime)||0},he=ee.current;ee.current=te;let Te=me-ce.current>T||te.jerseyCount!==he.jerseyCount||te.confidence!==he.confidence;Te&&y&&(y(te),ce.current=me),Te&&D.segmentedImages&&D.segmentedImages.length>0&&a&&_e(D.segmentedImages,D.bboxes)}}catch(G){console.warn("[JerseyDetector] Detection error (skipping frame):",G)}finally{c==null||c.close(),ie.current=!1}});return(0,s.useImperativeHandle)(W,()=>({get isReady(){return J},get lastError(){return F},get stats(){return ee.current},capture:(n="image/jpeg",i=.92)=>{let o=e.current,c=g.current;if(!o||o.videoWidth<=0||o.videoHeight<=0)throw new Error("Video not ready for capture");let C=document.createElement("canvas");C.width=o.videoWidth,C.height=o.videoHeight;let P=C.getContext("2d");if(!P)throw new Error("Failed to get context for capture canvas");let le=re.mirror;return P.drawImage(o,0,0,C.width,C.height),c&&c.width>0&&c.height>0&&P.drawImage(c,0,0,C.width,C.height),C.toDataURL(n,i)}}),[J,F,B]),(0,s.useEffect)(()=>{if(!B||!J||Q.current)return;let n=e.current,i=g.current;if(!n||!i||n.videoWidth===0||n.videoHeight===0){let c=setTimeout(()=>{L.current=requestAnimationFrame(()=>{})},100);return()=>clearTimeout(c)}(i.width!==n.videoWidth||i.height!==n.videoHeight)&&(i.width=n.videoWidth,i.height=n.videoHeight);let o=()=>S(null,null,function*(){!B||!J||Q.current||(yield xe(),L.current=requestAnimationFrame(o))});return L.current=requestAnimationFrame(o),()=>{L.current&&cancelAnimationFrame(L.current)}},[B,J]),(0,we.jsx)("canvas",{ref:g,className:`absolute inset-0 pointer-events-none ${u||""}`,style:Re({zIndex:10,width:"100%",height:"100%"},l)})});ge.displayName="JerseyDetector";0&&(module.exports={DEFAULT_CONFIG,JerseyDetector,useJerseyWorker});
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var Ce=Object.defineProperty;var me=Object.getOwnPropertySymbols;var Me=Object.prototype.hasOwnProperty,We=Object.prototype.propertyIsEnumerable;var ge=(n,o,s)=>o in n?Ce(n,o,{enumerable:!0,configurable:!0,writable:!0,value:s}):n[o]=s,pe=(n,o)=>{for(var s in o||(o={}))Me.call(o,s)&&ge(n,s,o[s]);if(me)for(var s of me(o))We.call(o,s)&&ge(n,s,o[s]);return n};var x=(n,o,s)=>new Promise((R,l)=>{var B=c=>{try{D(s.next(c))}catch(b){l(b)}},E=c=>{try{D(s.throw(c))}catch(b){l(b)}},D=c=>c.done?R(c.value):Promise.resolve(c.value).then(B,E);D((s=s.apply(n,o)).next())});import{forwardRef as Ae,useImperativeHandle as Ne,useRef as I,useEffect as ue,useMemo as he,useCallback as Je}from"react";import{useEffect as xe,useState as ye,useCallback as Be,useRef as F}from"react";var p=null,C=!1,V=null,ie=0,ae=null,T=new Map,Se=0,Z=new Map;function ce(n,o){let s=F(!1),[R,l]=ye(!1),[B,E]=ye(null),D=F(!0),c=F(!1),b=F(`instance_${Math.random().toString(36).substr(2,9)}`),S=F(0);xe(()=>{var v;if(!n)return;D.current=!0,S.current++;let w=S.current,M=b.current,O=(v=Z.get(M))!=null?v:0;return w>O&&(ie++,Z.set(M,w)),x(null,null,function*(){var f;if(!p||!Oe(ae,n)){p&&(p.terminate(),p=null,C=!1,console.log("[v0 useJerseyWorker] Worker terminated because of change in config"));try{c.current=(f=n.verbose)!=null?f:c.current;let m=o||"/jersey-detector-worker.js";p=new Worker(m),ae=n,C=!1,V=null,l(!1),E(null),p.onmessage=d=>{let t=d.data;switch(t.type){case"ready":C=!0,l(!0),c.current&&console.log("[v0 useJerseyWorker] Worker Ready",{device:t.device,dtype:t.dtype,config:t.config});break;case"loading_progress":c.current&&console.log(`[v0 useJerseyWorker] Loaded ${t.progress}% of ${t.file}`);break;case"debug":c.current&&console.log(t.debug_message);break;case"error":let h=t.error_message||"Unknown worker error";console.error("[v0 useJerseyWorker] Worker sent error message:",h),C=!1,V=h,l(!1),E(h);break;case"detect_response":if(t.requestId&&T.has(t.requestId)){let W=T.get(t.requestId);W&&(W.resolve(t),T.delete(t.requestId))}else if(T.size>0){let W=T.entries().next();if(!W.done){let[ee,g]=W.value;g.resolve(t),T.delete(ee)}}break}},p.onerror=d=>{let t=d.message||"Worker initialization error";console.error("[useJerseyWorker] Worker error:",t),C=!1,V=t,l(!1),E(t)},p.postMessage({type:"init",config:n})}catch(m){let d=(m==null?void 0:m.message)||String(m);console.error("[useJerseyWorker] Failed to create worker:",d),l(!1),E(d)}}else l(C),E(V)}),()=>{D.current=!1;let f=b.current,m=Z.get(f),d=S.current;m===d&&(ie--,Z.delete(f),ie<=0&&p&&(p.terminate(),p=null,C=!1,V=null,ae=null,T.clear()))}},[]);let G=Be((w,M,O=.5,H=!0,v)=>x(null,null,function*(){if(!p||!C)throw new Error("Worker not ready");if(s.current)return null;let f=`req_${++Se}_${Date.now()}`;return new Promise((m,d)=>{T.set(f,{resolve:m,reject:d});try{s.current=!0,p.postMessage({type:"detect",requestId:f,dimensions:M,bitmap:w,threshold:O,includeSegmentedImages:H,lastJerseyCount:v},[w])}catch(t){T.delete(f);let h=`Failed to send detect: ${t==null?void 0:t.message}`;d(new Error(h))}finally{s.current=!1}setTimeout(()=>{T.has(f)&&(T.delete(f),d(new Error("Detection timeout")))},1e4)})}),[R]);return{isReady:R,workerReady:R,lastError:B,detect:G}}function Oe(n,o){return n?JSON.stringify(n)===JSON.stringify(o):!1}var u={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,MIN_DETECTION_AREA:1e4};import He from"p-limit";import{jsx as Pe}from"react/jsx-runtime";var Te=Ae(({videoRef:n,onWorkerReady:o,onWorkerError:s,onStatsUpdate:R,onSegmentedImage:l,task:B=u.TASK,model:E=u.MODEL,verbose:D=u.VERBOSE,bodyPixArchitecture:c=u.BODYPIX_ARCHITECTURE,bodyPixMultiplier:b=u.BODYPIX_MULTIPLIER,bodyPixQuantBytes:S=u.BODYPIX_QUANT_BYTES,bodyPixStride:G=u.BODYPIX_STRIDE,multiSegmentation:w=u.MULTI_SEGMENTATION,segmentBodyParts:M=u.SEGMENT_BODY_PARTS,backgroundShade:O=u.BACKGROUND_SHADE,shirtShade:H=u.SHIRT_SHADE,threshold:v=u.DETECTION_THRESHOLD,targetPartId:f=u.TARGET_PART_ID,imagesToReturn:m=u.IMAGES_TO_RETURN,minDetectionArea:d=u.MIN_DETECTION_AREA,throttleMs:t=1e3,onImageSegmentedLimit:h=2,workerUrl:W,className:ee,style:g},Ee)=>{let Y=I(null),P=I(null),re=I(!1),q=I([]),De=I(null),U=I(!1),X=I(void 0);X.current=s;let $=I({jerseyCount:0,confidence:0,fps:0,processingTime:0}),te=I(0),ne=he(()=>He(h),[h]),z=he(()=>({task:B,model:E,verbose:D,bodyPixArchitecture:c,bodyPixMultiplier:b,bodyPixQuantBytes:S,bodyPixStride:G,multiSegmentation:w,segmentBodyParts:M,backgroundShade:O,shirtShade:H,threshold:v,targetPartId:f,imagesToReturn:m,minDetectionArea:d,mirror:(g==null?void 0:g.transform)==="scaleX(-1)"||typeof(g==null?void 0:g.transform)=="string"&&g.transform.includes("scaleX(-1)")}),[B,E,D,c,b,S,G,w,M,O,H,v,f,m,d,g==null?void 0:g.transform]),be=()=>{var e,i;return{width:((e=n.current)==null?void 0:e.videoWidth)||0,height:((i=n.current)==null?void 0:i.videoHeight)||0}},{isReady:A,workerReady:_,lastError:L,detect:ke}=ce(z,W);ue(()=>{_&&console.log("[JerseyDetector] Worker Ready with config:",z),o==null||o(_)},[_,o,z]),ue(()=>{var e;L&&(U.current=!0,(e=X.current)==null||e.call(X,L))},[L]);let Ie=Je((e,i)=>{if(ne.activeCount>=h){e.forEach(r=>{var a;return(a=r==null?void 0:r.close)==null?void 0:a.call(r)}),console.warn(`[JerseyDetector] Dropped new segmented images \u2014 max ${h} classifications running`);return}ne(()=>x(null,null,function*(){try{l==null||l(e,i)}catch(r){console.error("[JerseyDetector] Classification error:",r)}finally{e.forEach(r=>{var a;return(a=r==null?void 0:r.close)==null?void 0:a.call(r)})}}))},[l,h,ne]),Re=()=>x(null,null,function*(){var N,oe,le;let e=n.current,i=Y.current;if(U.current||!A||!_||!e||!i||re.current||e.readyState<2||e.paused||e.ended||e.videoWidth===0||e.videoHeight===0)return;let r=i.getContext("2d");if(!r||i.width<=0||i.height<=0)return;let a=null,k=null;try{re.current=!0;let j=e.videoWidth,K=e.videoHeight;De.current={width:j,height:K},a=yield createImageBitmap(e);let we=be(),se=Date.now(),ve=se-te.current>t,_e=$.current.jerseyCount,y=yield ke(a,we,v,ve,_e);if((y==null?void 0:y.type)==="detect_response"){if(m!=="none"&&((i.width!==j||i.height!==K)&&(i.width=j,i.height=K),r.clearRect(0,0,j,K),y.bitmap)){let J=y.bitmap;r.drawImage(J,0,0),console.log(`[JerseyDetector] Bitmap created with dims ${J.width}x${J.height}`),J.close()}q.current.push(Date.now()),q.current=q.current.filter(J=>Date.now()-J<1e3);let Q={jerseyCount:((N=y.stats)==null?void 0:N.jerseyCount)||0,confidence:((oe=y.stats)==null?void 0:oe.confidence)||0,fps:q.current.length,processingTime:((le=y.stats)==null?void 0:le.processingTime)||0},de=$.current;$.current=Q;let fe=se-te.current>t||Q.jerseyCount!==de.jerseyCount||Q.confidence!==de.confidence;fe&&R&&(R(Q),te.current=se),fe&&y.segmentedImages&&y.segmentedImages.length>0&&l&&Ie(y.segmentedImages,y.bboxes)}}catch(j){U.current=!0}finally{a==null||a.close(),re.current=!1}});return Ne(Ee,()=>({get isReady(){return A},get lastError(){return L},get stats(){return $.current},capture:(e="image/jpeg",i=.92)=>{let r=n.current,a=Y.current;if(!r||r.videoWidth<=0||r.videoHeight<=0)throw new Error("Video not ready for capture");let k=document.createElement("canvas");k.width=r.videoWidth,k.height=r.videoHeight;let N=k.getContext("2d");if(!N)throw new Error("Failed to get context for capture canvas");let oe=z.mirror;return N.drawImage(r,0,0,k.width,k.height),a&&a.width>0&&a.height>0&&N.drawImage(a,0,0,k.width,k.height),k.toDataURL(e,i)}}),[A,L,_]),ue(()=>{if(!_||!A||U.current)return;let e=n.current,i=Y.current;if(!e||!i||e.videoWidth===0||e.videoHeight===0){let a=setTimeout(()=>{P.current=requestAnimationFrame(()=>{})},100);return()=>clearTimeout(a)}(i.width!==e.videoWidth||i.height!==e.videoHeight)&&(i.width=e.videoWidth,i.height=e.videoHeight);let r=()=>x(null,null,function*(){!_||!A||U.current||(yield Re(),P.current=requestAnimationFrame(r))});return P.current=requestAnimationFrame(r),()=>{P.current&&cancelAnimationFrame(P.current)}},[_,A]),Pe("canvas",{ref:Y,className:`absolute inset-0 pointer-events-none ${ee||""}`,style:pe({zIndex:10,width:"100%",height:"100%"},g)})});Te.displayName="JerseyDetector";export{u as DEFAULT_CONFIG,Te as JerseyDetector,ce as useJerseyWorker};
1
+ var We=Object.defineProperty;var ye=Object.getOwnPropertySymbols;var Se=Object.prototype.hasOwnProperty,Oe=Object.prototype.propertyIsEnumerable;var De=(t,o,n)=>o in t?We(t,o,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[o]=n,Ee=(t,o)=>{for(var n in o||(o={}))Se.call(o,n)&&De(t,n,o[n]);if(ye)for(var n of ye(o))Oe.call(o,n)&&De(t,n,o[n]);return t};var W=(t,o,n)=>new Promise((b,l)=>{var S=g=>{try{w(n.next(g))}catch(k){l(k)}},D=g=>{try{w(n.throw(g))}catch(k){l(k)}},w=g=>g.done?b(g.value):Promise.resolve(g.value).then(S,D);w((n=n.apply(t,o)).next())});import{forwardRef as Je,useImperativeHandle as Pe,useRef as T,useEffect as ge,useMemo as Ie,useCallback as je}from"react";import{useEffect as Re,useState as fe,useCallback as Ae,useRef as j}from"react";var u=null,C=!1,Y=null,me=0,te=null,y=new Map,Ne=0,ne=new Map;function de(t,o){let n=j(!1),[b,l]=fe(!1),[S,D]=fe(null),w=j(!0),g=j(!1),k=j(`instance_${Math.random().toString(36).substr(2,9)}`),O=j(0),[U,q]=fe(0);Re(()=>{var B;if(!t)return;w.current=!0,O.current++;let E=O.current,R=k.current,A=(B=ne.get(R))!=null?B:0;return E>A&&(me++,ne.set(R,E)),W(null,null,function*(){var p;if(!u||!He(te,t)){u&&(u.terminate(),u=null,C=!1,console.log("[v0 useJerseyWorker] Worker terminated because of change in config or watchdog"));try{g.current=(p=t.verbose)!=null?p:g.current;let f=o||"/jersey-detector-worker.js";u=new Worker(f),te=t,C=!1,Y=null,l(!1),D(null),u.onmessage=I=>{let i=I.data;switch(i.type){case"ready":C=!0,l(!0);break;case"debug":g.current&&console.log(i.debug_message);break;case"error":let c=i.error_message||"Unknown worker error";console.error("[v0 useJerseyWorker] Worker sent error message:",c),C=!1,Y=c,l(!1),D(c);break;case"detect_response":if(i.requestId&&y.has(i.requestId)){let M=y.get(i.requestId);M==null||M.resolve(i),y.delete(i.requestId)}break}},u.onerror=I=>{let i=I.message||"Worker initialization error";C=!1,Y=i,l(!1),D(i)},u.postMessage({type:"init",config:t})}catch(f){l(!1),D((f==null?void 0:f.message)||String(f))}}else l(C),D(Y)}),()=>{w.current=!1;let p=k.current,f=ne.get(p),I=O.current;f===I&&(me--,ne.delete(p),me<=0&&u&&(u.terminate(),u=null,C=!1,Y=null,te=null,y.clear()))}},[t,o,U]);let _=j(0);Re(()=>{if(!u)return;let E=setInterval(()=>{y.size>0?_.current>=3&&(console.error("[v0 useJerseyWorker] Watchdog: Worker appears hung after 3 consecutive timeouts. Restarting..."),_.current=0,u&&(u.terminate(),u=null,C=!1,te=null,l(!1),q(R=>R+1))):_.current=0},2e3);return()=>clearInterval(E)},[b,U]);let X=Ae((E,R,A=.5,N=!0,B)=>W(null,null,function*(){if(!u||!C)return null;if(n.current||y.size>0)return g.current,null;let p=`req_${++Ne}_${Date.now()}`;return new Promise((f,I)=>{let i=setTimeout(()=>{if(y.has(p)){_.current++;let m=y.get(p);m==null||m.reject(new Error("Detection timeout")),y.delete(p),n.current=!1}},5e3),c=m=>{_.current=0,clearTimeout(i),n.current=!1,f(m)},M=m=>{clearTimeout(i),n.current=!1,I(m)};y.set(p,{resolve:c,reject:M});try{n.current=!0,u.postMessage({type:"detect",requestId:p,dimensions:R,bitmap:E,threshold:A,includeSegmentedImages:N,lastJerseyCount:B},[E])}catch(m){clearTimeout(i),y.delete(p),n.current=!1,I(new Error(`Failed to send detect: ${m==null?void 0:m.message}`))}})}),[b]);return{isReady:b,workerReady:b,lastError:S,detect:X}}function He(t,o){return t?JSON.stringify(t)===JSON.stringify(o):!1}var d={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,MIN_DETECTION_AREA:1e4};import Ue from"p-limit";import{jsx as Ve}from"react/jsx-runtime";var be=Je(({videoRef:t,onWorkerReady:o,onWorkerError:n,onStatsUpdate:b,onSegmentedImage:l,task:S=d.TASK,model:D=d.MODEL,verbose:w=d.VERBOSE,bodyPixArchitecture:g=d.BODYPIX_ARCHITECTURE,bodyPixMultiplier:k=d.BODYPIX_MULTIPLIER,bodyPixQuantBytes:O=d.BODYPIX_QUANT_BYTES,bodyPixStride:U=d.BODYPIX_STRIDE,multiSegmentation:q=d.MULTI_SEGMENTATION,segmentBodyParts:_=d.SEGMENT_BODY_PARTS,backgroundShade:X=d.BACKGROUND_SHADE,shirtShade:E=d.SHIRT_SHADE,threshold:R=d.DETECTION_THRESHOLD,targetPartId:A=d.TARGET_PART_ID,imagesToReturn:N=d.IMAGES_TO_RETURN,minDetectionArea:B=d.MIN_DETECTION_AREA,throttleMs:p=1e3,onImageSegmentedLimit:f=2,workerUrl:I,className:i,style:c},M)=>{let m=T(null),oe=T(null),V=T(null),z=T(!1),L=T(null),se=T(!1),$=T([]),we=T(null),K=T(!1),Q=T(void 0);Q.current=n;let Z=T({jerseyCount:0,confidence:0,fps:0,processingTime:0}),ae=T(0),ie=Ie(()=>Ue(f),[f]),ee=Ie(()=>({task:S,model:D,verbose:w,bodyPixArchitecture:g,bodyPixMultiplier:k,bodyPixQuantBytes:O,bodyPixStride:U,multiSegmentation:q,segmentBodyParts:_,backgroundShade:X,shirtShade:E,threshold:R,targetPartId:A,imagesToReturn:N,minDetectionArea:B,mirror:(c==null?void 0:c.transform)==="scaleX(-1)"||typeof(c==null?void 0:c.transform)=="string"&&c.transform.includes("scaleX(-1)")}),[S,D,w,g,k,O,U,q,_,X,E,R,A,N,B,c==null?void 0:c.transform]),ke=()=>{var e,s;return{width:((e=t.current)==null?void 0:e.videoWidth)||0,height:((s=t.current)==null?void 0:s.videoHeight)||0}},{isReady:H,workerReady:x,lastError:F,detect:ve}=de(ee,I);ge(()=>{x&&(console.log("[JerseyDetector] Worker Ready with config:",ee),K.current=!1),o==null||o(x)},[x,o,ee]),ge(()=>{var e;F&&((e=Q.current)==null||e.call(Q,F))},[F]);let Ce=je((e,s)=>{if(ie.activeCount>=f){e.forEach(r=>{var a;return(a=r==null?void 0:r.close)==null?void 0:a.call(r)}),console.warn(`[JerseyDetector] Dropped new segmented images \u2014 max ${f} classifications running`);return}ie(()=>W(null,null,function*(){try{l==null||l(e,s)}catch(r){console.error("[JerseyDetector] Classification error:",r)}finally{e.forEach(r=>{var a;return(a=r==null?void 0:r.close)==null?void 0:a.call(r)})}}))},[l,f,ie]),_e=()=>W(null,null,function*(){var J,ce,pe;let e=t.current,s=m.current;if(K.current||!H||!x||!e||!s||se.current||e.readyState<2||e.paused||e.ended||e.videoWidth===0||e.videoHeight===0)return;!V.current&&!oe.current&&(V.current=s.getContext("bitmaprenderer"),z.current=!!V.current,z.current||(oe.current=s.getContext("2d")));let r=oe.current;if(!z.current&&!r||s.width<=0||s.height<=0)return;let a=null,v=null;try{se.current=!0;let G=e.videoWidth,ue=e.videoHeight;we.current={width:G,height:ue},a=yield createImageBitmap(e);let xe=ke(),le=Date.now(),Be=le-ae.current>p,Me=Z.current.jerseyCount,h=yield ve(a,xe,R,Be,Me);if((h==null?void 0:h.type)==="detect_response"){if(N!=="none"&&((s.width!==G||s.height!==ue)&&(s.width=G,s.height=ue),h.bitmap)){let P=h.bitmap;z.current&&V.current?V.current.transferFromImageBitmap(P):(r&&r.drawImage(P,0,0),P.close())}$.current.push(Date.now()),$.current=$.current.filter(P=>Date.now()-P<1e3);let re={jerseyCount:((J=h.stats)==null?void 0:J.jerseyCount)||0,confidence:((ce=h.stats)==null?void 0:ce.confidence)||0,fps:$.current.length,processingTime:((pe=h.stats)==null?void 0:pe.processingTime)||0},he=Z.current;Z.current=re;let Te=le-ae.current>p||re.jerseyCount!==he.jerseyCount||re.confidence!==he.confidence;Te&&b&&(b(re),ae.current=le),Te&&h.segmentedImages&&h.segmentedImages.length>0&&l&&Ce(h.segmentedImages,h.bboxes)}}catch(G){console.warn("[JerseyDetector] Detection error (skipping frame):",G)}finally{a==null||a.close(),se.current=!1}});return Pe(M,()=>({get isReady(){return H},get lastError(){return F},get stats(){return Z.current},capture:(e="image/jpeg",s=.92)=>{let r=t.current,a=m.current;if(!r||r.videoWidth<=0||r.videoHeight<=0)throw new Error("Video not ready for capture");let v=document.createElement("canvas");v.width=r.videoWidth,v.height=r.videoHeight;let J=v.getContext("2d");if(!J)throw new Error("Failed to get context for capture canvas");let ce=ee.mirror;return J.drawImage(r,0,0,v.width,v.height),a&&a.width>0&&a.height>0&&J.drawImage(a,0,0,v.width,v.height),v.toDataURL(e,s)}}),[H,F,x]),ge(()=>{if(!x||!H||K.current)return;let e=t.current,s=m.current;if(!e||!s||e.videoWidth===0||e.videoHeight===0){let a=setTimeout(()=>{L.current=requestAnimationFrame(()=>{})},100);return()=>clearTimeout(a)}(s.width!==e.videoWidth||s.height!==e.videoHeight)&&(s.width=e.videoWidth,s.height=e.videoHeight);let r=()=>W(null,null,function*(){!x||!H||K.current||(yield _e(),L.current=requestAnimationFrame(r))});return L.current=requestAnimationFrame(r),()=>{L.current&&cancelAnimationFrame(L.current)}},[x,H]),Ve("canvas",{ref:m,className:`absolute inset-0 pointer-events-none ${i||""}`,style:Ee({zIndex:10,width:"100%",height:"100%"},c)})});be.displayName="JerseyDetector";export{d as DEFAULT_CONFIG,be as JerseyDetector,de as useJerseyWorker};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seg-cam",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -82168,7 +82168,7 @@ var BodyPixSegmenter = class {
82168
82168
  };
82169
82169
  BodyPixSegmenter.instance = null;
82170
82170
  BodyPixSegmenter.isInitialized = false;
82171
- async function processSinglePerson(person, originalImageTensor) {
82171
+ async function processSinglePerson(person, originalImageTensor, includeSegmentedImages = true) {
82172
82172
  const width = originalImageTensor.shape[1];
82173
82173
  const height = originalImageTensor.shape[0];
82174
82174
  const rawMaskTensor = await person.mask.toTensor();
@@ -82224,15 +82224,18 @@ async function processSinglePerson(person, originalImageTensor) {
82224
82224
  sendDebug(`[Worker] No torso or too small: ${hasTorso}, ${area}`);
82225
82225
  return { personBitmap: null, isUpperTorso: null, bbox };
82226
82226
  }
82227
- const rgbaTensor = tf.tidy(() => {
82228
- const rgbTensor = tf.slice(originalImageTensor, [top, left, 0], [bboxHeight, bboxWidth, 3]);
82229
- const alphaTensor = tf.fill([bboxHeight, bboxWidth, 1], 255);
82230
- return tf.concat([rgbTensor, alphaTensor], 2);
82231
- });
82232
- const pixelData = await rgbaTensor.data();
82233
- const imageData = new ImageData(new Uint8ClampedArray(pixelData), bboxWidth, bboxHeight);
82234
- const personBitmap = await createImageBitmap(imageData);
82235
- rgbaTensor.dispose();
82227
+ let personBitmap = null;
82228
+ if (includeSegmentedImages) {
82229
+ const rgbaTensor = tf.tidy(() => {
82230
+ const rgbTensor = tf.slice(originalImageTensor, [top, left, 0], [bboxHeight, bboxWidth, 3]);
82231
+ const alphaTensor = tf.fill([bboxHeight, bboxWidth, 1], 255);
82232
+ return tf.concat([rgbTensor, alphaTensor], 2);
82233
+ });
82234
+ const pixelData = await rgbaTensor.data();
82235
+ const imageData = new ImageData(new Uint8ClampedArray(pixelData), bboxWidth, bboxHeight);
82236
+ personBitmap = await createImageBitmap(imageData);
82237
+ rgbaTensor.dispose();
82238
+ }
82236
82239
  partIds.dispose();
82237
82240
  return {
82238
82241
  personBitmap,
@@ -82243,6 +82246,8 @@ async function processSinglePerson(person, originalImageTensor) {
82243
82246
  }
82244
82247
  var canvas = null;
82245
82248
  var ctx = null;
82249
+ var mirrorCanvas = null;
82250
+ var mirrorCtx = null;
82246
82251
  var currentConfig = null;
82247
82252
  var isProcessing = false;
82248
82253
  var isInitInProgress = false;
@@ -82275,9 +82280,10 @@ var handleInit = async (message) => {
82275
82280
  }
82276
82281
  };
82277
82282
  var handleDetect = async (message) => {
82278
- const { requestId, dimensions, bitmap: inputBitmap, threshold: threshold3 } = message;
82283
+ const { requestId, dimensions, bitmap: inputBitmap, threshold: threshold3, includeSegmentedImages = true, lastJerseyCount } = message;
82279
82284
  let outputBitmap;
82280
82285
  let originalImageTensor = null;
82286
+ let fallbackImageData = null;
82281
82287
  try {
82282
82288
  if (isProcessing) throw new Error("New request before previous finished");
82283
82289
  isProcessing = true;
@@ -82289,32 +82295,41 @@ var handleDetect = async (message) => {
82289
82295
  }
82290
82296
  if (!ctx) throw new Error("Failed to get canvas context");
82291
82297
  const { width, height } = canvas;
82292
- ctx.clearRect(0, 0, width, height);
82293
- ctx.drawImage(inputBitmap, 0, 0);
82294
- const imageData = ctx.getImageData(0, 0, width, height);
82295
- originalImageTensor = tf.tidy(() => {
82296
- const rgba = tf.tensor3d(new Uint8Array(imageData.data), [height, width, 4], "int32");
82297
- return tf.slice(rgba, [0, 0, 0], [-1, -1, 3]);
82298
- });
82299
- inputBitmap.close();
82298
+ let segmentInput = inputBitmap;
82299
+ try {
82300
+ originalImageTensor = tf.browser.fromPixels(inputBitmap, 3);
82301
+ } catch {
82302
+ ctx.clearRect(0, 0, width, height);
82303
+ ctx.drawImage(inputBitmap, 0, 0);
82304
+ fallbackImageData = ctx.getImageData(0, 0, width, height);
82305
+ segmentInput = fallbackImageData;
82306
+ originalImageTensor = tf.tidy(() => {
82307
+ const rgba = tf.tensor3d(new Uint8Array(fallbackImageData.data), [height, width, 4], "int32");
82308
+ return tf.slice(rgba, [0, 0, 0], [-1, -1, 3]);
82309
+ });
82310
+ }
82300
82311
  const segmenter = await BodyPixSegmenter.getInstance();
82301
- const people = await segmenter.segmentPeople(imageData, {
82312
+ const people = await segmenter.segmentPeople(segmentInput, {
82302
82313
  multiSegmentation: currentConfig?.multiSegmentation ?? true,
82303
82314
  segmentBodyParts: currentConfig?.segmentBodyParts ?? true,
82304
82315
  segmentationThreshold: currentConfig?.threshold ?? 0.5
82305
82316
  });
82317
+ inputBitmap.close();
82306
82318
  const segmentedImages = [];
82307
82319
  const bboxes = [];
82308
82320
  let allTorsosMask = null;
82309
82321
  sendDebug(`[Worker] Found ${people.length} person(s)`);
82310
82322
  if (people && people.length > 0) {
82311
82323
  const imagesToReturn = currentConfig?.imagesToReturn ?? "mask";
82324
+ const shouldExtract = includeSegmentedImages || lastJerseyCount !== void 0 && people.length !== lastJerseyCount;
82312
82325
  for (const person of people) {
82313
- const { personBitmap, isUpperTorso, bbox } = await processSinglePerson(person, originalImageTensor);
82326
+ const { personBitmap, isUpperTorso, bbox } = await processSinglePerson(person, originalImageTensor, shouldExtract);
82314
82327
  if (!isUpperTorso) continue;
82315
82328
  if (personBitmap) {
82316
82329
  segmentedImages.push(personBitmap);
82317
82330
  bboxes.push(bbox);
82331
+ } else {
82332
+ bboxes.push(bbox);
82318
82333
  }
82319
82334
  if (imagesToReturn !== "none") {
82320
82335
  if (!allTorsosMask) {
@@ -82362,12 +82377,16 @@ var handleDetect = async (message) => {
82362
82377
  const overlayData = await overlayTensor.data();
82363
82378
  ctx.putImageData(new ImageData(new Uint8ClampedArray(overlayData), width, height), 0, 0);
82364
82379
  if (currentConfig?.mirror) {
82365
- const mirrorCanvas = new OffscreenCanvas(width, height);
82366
- const mctx = mirrorCanvas.getContext("2d");
82367
- if (mctx) {
82368
- mctx.translate(width, 0);
82369
- mctx.scale(-1, 1);
82370
- mctx.drawImage(canvas, 0, 0);
82380
+ if (!mirrorCanvas || mirrorCanvas.width !== width || mirrorCanvas.height !== height) {
82381
+ mirrorCanvas = new OffscreenCanvas(width, height);
82382
+ mirrorCtx = mirrorCanvas.getContext("2d");
82383
+ }
82384
+ if (mirrorCtx && mirrorCanvas) {
82385
+ mirrorCtx.setTransform(1, 0, 0, 1, 0, 0);
82386
+ mirrorCtx.clearRect(0, 0, width, height);
82387
+ mirrorCtx.translate(width, 0);
82388
+ mirrorCtx.scale(-1, 1);
82389
+ mirrorCtx.drawImage(canvas, 0, 0);
82371
82390
  outputBitmap = await createImageBitmap(mirrorCanvas);
82372
82391
  } else {
82373
82392
  outputBitmap = await createImageBitmap(canvas);
@@ -82385,7 +82404,9 @@ var handleDetect = async (message) => {
82385
82404
  } else {
82386
82405
  sendDebug("[Worker] No output bitmap created");
82387
82406
  }
82388
- segmentedImages.forEach((img) => transferList.push(img));
82407
+ segmentedImages.forEach((img) => {
82408
+ if (img) transferList.push(img);
82409
+ });
82389
82410
  self.postMessage({
82390
82411
  type: "detect_response",
82391
82412
  requestId,