Spaces:
Running
Running
fix blank Space: stop unregistering the coi-serviceworker we just registered
Browse files- README.md +1 -3
- assets/index-DbiX_hBC.js +0 -0
- assets/inference.worker-CKN52DNs.js +1 -0
- index.html +1 -1
README.md
CHANGED
|
@@ -11,8 +11,6 @@ short_description: Open-vocabulary detection in-browser via WebGPU
|
|
| 11 |
|
| 12 |
# Falcon Perception — In-Browser Demo
|
| 13 |
|
| 14 |
-
Interactive demo of [tiiuae/Falcon-Perception](https://huggingface.co/tiiuae/Falcon-Perception),
|
| 15 |
-
|
| 16 |
-
Image, webcam, and video input with Detection, Segmentation, and HUD Tracker render modes. Runs multi-threaded WASM via `coi-serviceworker`; example images are base64-inlined so the COEP-enforced document can still load them.
|
| 17 |
|
| 18 |
Weights: [shreyask/falcon-perception-onnx-webgpu](https://huggingface.co/shreyask/falcon-perception-onnx-webgpu).
|
|
|
|
| 11 |
|
| 12 |
# Falcon Perception — In-Browser Demo
|
| 13 |
|
| 14 |
+
Interactive demo of [tiiuae/Falcon-Perception](https://huggingface.co/tiiuae/Falcon-Perception). Image / webcam / video modes, three render modes (Detection / Segment / Tracker). Multi-threaded WASM via coi-serviceworker; example images base64-inlined.
|
|
|
|
|
|
|
| 15 |
|
| 16 |
Weights: [shreyask/falcon-perception-onnx-webgpu](https://huggingface.co/shreyask/falcon-perception-onnx-webgpu).
|
assets/index-DbiX_hBC.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/inference.worker-CKN52DNs.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
const e=`shreyask/falcon-perception-onnx-webgpu`,t=`https://huggingface.co/${e}/resolve/main`,n={unified:{file:`unified_v2.onnx`,size:203e7},embed_tokens:{file:`embed_tokens.onnx`,size:256e6},coord_decoder:{file:`coord_decoder.onnx`,size:96e6},size_decoder:{file:`size_decoder.onnx`,size:96e6},segm_head:{file:`segm_head.onnx`,size:9e6},img_projector:{file:`img_projector.onnx`,size:3e6},coord_encoder:{file:`coord_encoder.onnx`,size:2e6},size_encoder:{file:`size_encoder.onnx`,size:2e6}},r={dim:1024,n_layers:28,n_heads:16,head_dim:128,n_kv_heads:8,vocab_size:65536,max_seq_len:8192,segm_out_dim:256,coord_out_dim:2048,size_out_dim:2048,coord_token_id:240,size_token_id:241,seg_token_id:262,eos_id:11,img_id:227,image_cls_token_id:244,img_end_id:230,spatial_patch_size:16,temporal_patch_size:1,channel_size:3,rope_theta:1e4,presence_token_id:268,absence_token_id:269,end_of_query_token_id:263,start_of_query_token_id:264,ref_seg_token_id:258};function i(e,t=.6){if(e.length<=1)return e;let n=e.map((e,t)=>({det:e,idx:t,area:o(e.box)}));n.sort((e,t)=>t.area-e.area);let r=new Set,i=[];for(let{det:e,idx:o}of n){let n=!1;for(let r of i)if(a(e.box,r)>t){n=!0;break}n||(r.add(o),i.push(e.box))}return e.filter((e,t)=>r.has(t))}function a(e,t){let n=Math.max(e.x1,t.x1),r=Math.max(e.y1,t.y1),i=Math.min(e.x2,t.x2),a=Math.min(e.y2,t.y2),s=i-n,c=a-r;if(s<=0||c<=0)return 0;let l=s*c,u=o(e)+o(t)-l;return u>0?l/u:0}function o(e){return Math.max(0,e.x2-e.x1)*Math.max(0,e.y2-e.y1)}let s,c=null,l=!1,u=null;const d={};function f(e){self.postMessage(e)}function p(e){let t=d[e];if(!t)throw Error(`ONNX session not loaded: ${e}`);return t}async function m(e,n){let r=`${t}/${e}`,i=await fetch(r);if(!i.ok)throw Error(`Failed to fetch ${e}: ${i.status}`);let a=i.body?.getReader();if(!a)return i.arrayBuffer();let o=[],s=0;for(;;){let{done:t,value:r}=await a.read();if(t)break;o.push(r),s+=r.length,f({type:`progress`,progress:Math.round(s/n*100),loaded:s,total:n,file:e})}let c=new Uint8Array(s),l=0;for(let e of o)c.set(e,l),l+=e.length;return c.buffer}async function h(e,t,n,r){let i=`${t}.data`,[a,o]=await Promise.all([m(t,n*.01),m(i,n*.99)]),c=await s.InferenceSession.create(a,{executionProviders:r,externalData:[{path:i,data:new Uint8Array(o)}]});return console.log(`Loaded ${e}: inputs=[${c.inputNames}] outputs=[${c.outputNames}]`),c}async function g(){try{s=await import(`./ort.bundle.min-BZrO1_VY.js`);let t=typeof SharedArrayBuffer<`u`;s.env.wasm.numThreads=t?Math.min(4,navigator.hardwareConcurrency||2):1;let r=import(`./transformers.web-DaZ4EEMB.js`).then(async({AutoTokenizer:t})=>{try{c=await t.from_pretrained(e),console.log(`Tokenizer loaded`)}catch(e){console.warn(`AutoTokenizer failed, will use fallback:`,x(e,`unknown error`))}}),i=[`unified`,`embed_tokens`,`coord_decoder`,`size_decoder`,`segm_head`,`img_projector`,`coord_encoder`,`size_encoder`],a=0,o=Object.values(n).reduce((e,t)=>e+t.size,0),l=new Set([`unified`]);for(let e of i){let{file:t,size:r}=n[e];f({type:`progress`,progress:Math.round(a/o*100),loaded:a,total:o,file:t});let i=l.has(e)?[`wasm`]:[`webgpu`,`wasm`];try{d[e]=await h(e,t,r,i)}catch(n){console.warn(`${i[0]} failed for ${e}, trying WASM:`,x(n,`unknown error`));try{d[e]=await h(e,t,r,[`wasm`])}catch(t){console.error(`Failed to load ${e}:`,x(t,`unknown error`))}}a+=r}await r,c||console.log(`Using fallback tokenizer (hardcoded prompt tokens)`),f({type:`loaded`})}catch(e){f({type:`error`,message:x(e,`Failed to load models`)})}}function ee(e){let t=r.spatial_patch_size,n=e.width,i=e.height,a=Math.min(256/n,256/i,1);n=Math.floor(Math.round(n*a)/t)*t,i=Math.floor(Math.round(i*a)/t)*t,n=Math.max(n,t),i=Math.max(i,t);let o=new OffscreenCanvas(n,i).getContext(`2d`);o.drawImage(e,0,0,n,i);let s=o.getImageData(0,0,n,i),c=new Float32Array(i*n*3);for(let e=0;e<i*n;e++)c[e*3+0]=s.data[e*4+0]/255*2-1,c[e*3+1]=s.data[e*4+1]/255*2-1,c[e*3+2]=s.data[e*4+2]/255*2-1;return{pixels:c,width:n,height:i,patchH:i/t,patchW:n/t}}function te(e,t){let n=Math.sqrt(t/e),r=Math.sqrt(e/t),i=new Float32Array(e*t*2);for(let a=0;a<e;a++){let o=e>1?r*(2*a/(e-1)-1):0;for(let e=0;e<t;e++){let r=t>1?n*(2*e/(t-1)-1):0,s=a*t+e;i[s*2+0]=o,i[s*2+1]=r}}return i}function _(e){u?.image&&u.image!==e.image&&u.image.close(),u=e}function v(e){if(l){_(e),console.log(`[detect] queued latest frame while inference is running`);return}y(e)}async function y(e){l=!0;let{image:t,query:n,requestId:a,sourceTimestampMs:o,capturedAtMs:m}=e,h=(e,t)=>{f({type:`result`,detections:e,inferenceMs:t,query:n,requestId:a,sourceTimestampMs:o,capturedAtMs:m})};if(console.log(`[detect] query="${n}" image=${t.width}x${t.height}`),!d.unified||!d.embed_tokens){f({type:`error`,message:`Not ready. Sessions: ${Object.keys(d).join(`,`)}`}),l=!1;return}try{let e=performance.now(),a=r.dim,o=r.spatial_patch_size,l=o*o*r.channel_size,{pixels:u,width:d,patchH:f,patchW:m}=ee(t),g=f*m;console.log(`[detect] image: ${d}px, ${f}x${m}=${g} patches`);let _=`Segment these expressions in the image:<|start_of_query|>${n}<|REF_SEG|>`,v;if(c){let e=c.encode(_,{add_special_tokens:!1});v=Array.from(e),console.log(`[detect] text tokens (${v.length}):`,v)}else v=[37462,1978,20528,821,790,6883,549,264,258],console.log(`[detect] using fallback tokens (no query text):`,v);let y=[245,246,247,248],x=1+y.length+g+1+v.length,S=new BigInt64Array(x),C=0;S[C++]=BigInt(r.image_cls_token_id);for(let e of y)S[C++]=BigInt(e);let w=C;for(let e=0;e<g;e++)S[C++]=BigInt(r.img_id);S[C++]=BigInt(r.img_end_id);for(let e of v)S[C++]=BigInt(e);console.log(`[detect] total seq_len=${x}, token IDs: [${Array.from(S.slice(0,5)).map(Number)}...${Array.from(S.slice(-5)).map(Number)}]`);let re=await p(`embed_tokens`).run({token_ids:new s.Tensor(`int64`,S,[1,x])}),T=new Float32Array(re.embeddings.data),E=new Float32Array(g*l);for(let e=0;e<f;e++)for(let t=0;t<m;t++){let n=e*m+t;for(let r=0;r<o;r++)for(let i=0;i<o;i++){let a=e*o+r,s=t*o+i,c=(a*d+s)*3,f=n*l+(r*o+i)*3;E[f+0]=u[c+0],E[f+1]=u[c+1],E[f+2]=u[c+2]}}let ie=(await p(`img_projector`).run({pixel_patches:new s.Tensor(`float32`,E,[g,l])})).projected.data;for(let e=0;e<g;e++){let t=w*a+e*a,n=e*a;for(let e=0;e<a;e++)T[t+e]=ie[n+e]}let ae=T.slice(0,5);console.log(`[detect] embedding[0][0:5]: [${Array.from(ae).map(e=>e.toFixed(3)).join(`, `)}]`);let oe=T.slice(w*a,w*a+5);console.log(`[detect] embedding[imgStart][0:5]: [${Array.from(oe).map(e=>e.toFixed(3)).join(`, `)}]`);let se=T.slice((x-1)*a,(x-1)*a+5);console.log(`[detect] embedding[last][0:5]: [${Array.from(se).map(e=>e.toFixed(3)).join(`, `)}]`),console.log(`[detect] running encoder (seq_len=${x})...`);let D=new Float32Array(x),O=w+g+1,ce=new Set([245,246,247,248,r.img_id,r.img_end_id]),k=new Float32Array(x);for(let e=0;e<x;e++){let t=Number(S[e]);k[e]=ce.has(t)&&e<O?0:1}let A=0;for(let e=0;e<x;e++)A+=k[e],D[e]=A-1;let j=r.head_dim/4,le=r.rope_theta,M=new Float32Array(x*j*2);for(let e=0;e<x;e++){let t=D[e];for(let n=0;n<j;n++){let r=t/le**(2*n/(j*2));M[(e*j+n)*2+0]=Math.cos(r),M[(e*j+n)*2+1]=Math.sin(r)}}let N=new Uint8Array(x*x);for(let e=0;e<x;e++)for(let t=0;t<=e;t++)N[e*x+t]=1;for(let e=0;e<O;e++)for(let t=0;t<O;t++)N[e*x+t]=1;let P=r.vocab_size,F=r.coord_out_dim/2,I=r.n_layers,L=r.n_heads,R=r.head_dim,ue=new Float32Array(I*2*1*L*0*R),z=new Float32Array(x*2);z.fill(NaN);let B=te(f,m);for(let e=0;e<g;e++){let t=(w+e)*2;z[t+0]=B[e*2+0],z[t+1]=B[e*2+1]}console.log(`[detect] prefill (seq_len=${x})...`);let V=await p(`unified`).run({token_embeddings:new s.Tensor(`float32`,T,[1,x,a]),freqs_cis:new s.Tensor(`float32`,M,[1,x,j,2]),pos_hw:new s.Tensor(`float32`,z,[1,x,2]),attention_mask:new s.Tensor(`bool`,N,[1,x,x]),past_kv:new s.Tensor(`float32`,ue,[I,2,1,L,0,R]),past_len:new s.Tensor(`int64`,new BigInt64Array([0n]),[])}),H=V.logits.data,U=V.new_kv,W=x,G=(x-1)*P,K=H[G+r.presence_token_id],q=H[G+r.absence_token_id];console.log(`[detect] prefill done: presence=${K.toFixed(2)}, absence=${q.toFixed(2)}`);let J=[];if(K<=q&&K<0){console.log(`[detect] object "${n}" not found`),h(J,performance.now()-e);return}let de=V.hidden_states.data,Y=new Float32Array(de.subarray((x-1)*a,x*a)),X=H,fe=D[x-1]+1,Z=null,Q=null,pe=new Set([r.eos_id,r.end_of_query_token_id]);for(let t=0;t<510;t++){let i=X.length,o=b(X,i-P,P);if(pe.has(o)){console.log(`[detect] stop token ${o} (${ne(o)}) at step ${t}`);break}if(o===r.absence_token_id){console.log(`[detect] <absence> at step ${t}, stopping`);break}if(o===r.coord_token_id){let e=await p(`coord_decoder`).run({hidden:new s.Tensor(`float32`,Y,[1,a])}),n=new Float32Array(e.logits.data),r=.01,i=0,o=0,c=0,l=0;for(let e=0;e<100&&(i=b(n,0,F),o=b(n,F,F),c=i/(F-1),l=o/(F-1),J.some(e=>{let t=(e.box.x1+e.box.x2)/2,n=(e.box.y1+e.box.y2)/2;return Math.abs(t-c)<r&&Math.abs(n-l)<r}));e++)n[i]=-1/0,n[F+o]=-1/0;Z=[c,l],console.log(`[detect] step ${t}: <coord> → (${c.toFixed(3)}, ${l.toFixed(3)})`)}else if(o===r.size_token_id){let e=(await p(`size_decoder`).run({hidden:new s.Tensor(`float32`,Y,[1,a])})).logits.data,n=b(e,0,F),r=b(e,F,F),i=Math.log2(1/F),o=2**(n/(F-1)*-i+i),c=2**(r/(F-1)*-i+i);Q=[o,c],console.log(`[detect] step ${t}: <size> → (h=${o.toFixed(3)}, w=${c.toFixed(3)})`)}else if(o===r.seg_token_id){if(Z&&Q){let[r,i]=Z,[a,o]=Q;if(J.push({label:n,score:1/(1+Math.exp(-(K-q))),box:{x1:Math.max(0,r-o/2),y1:Math.max(0,i-a/2),x2:Math.min(1,r+o/2),y2:Math.min(1,i+a/2)}}),console.log(`[detect] step ${t}: <seg> → object #${J.length} xy=(${r.toFixed(2)},${i.toFixed(2)}) hw=(${a.toFixed(2)},${o.toFixed(2)})`),h([...J],performance.now()-e),J.length>=100){console.log(`[detect] reached max 100 objects`);break}Z=null,Q=null}}else console.log(`[detect] step ${t}: ${ne(o)} (${o})`);let c;if(o===r.coord_token_id&&Z){let e=await p(`coord_encoder`).run({coords:new s.Tensor(`float32`,new Float32Array(Z),[1,2])});c=new Float32Array(e.encoded.data)}else if(o===r.size_token_id&&Q){let e=await p(`size_encoder`).run({sizes:new s.Tensor(`float32`,new Float32Array(Q),[1,2])});c=new Float32Array(e.encoded.data)}else{let e=await p(`embed_tokens`).run({token_ids:new s.Tensor(`int64`,new BigInt64Array([BigInt(o)]),[1,1])});c=new Float32Array(e.embeddings.data)}let l=new Float32Array(j*2);for(let e=0;e<j;e++){let t=fe/le**(2*e/(j*2));l[e*2+0]=Math.cos(t),l[e*2+1]=Math.sin(t)}let u=new Uint8Array(W+1);u.fill(1);let d=new Float32Array([NaN,NaN]),f=await p(`unified`).run({token_embeddings:new s.Tensor(`float32`,c,[1,1,a]),freqs_cis:new s.Tensor(`float32`,l,[1,1,j,2]),pos_hw:new s.Tensor(`float32`,d,[1,1,2]),attention_mask:new s.Tensor(`bool`,u,[1,1,W+1]),past_kv:U,past_len:new s.Tensor(`int64`,new BigInt64Array([BigInt(W)]),[])});Y=new Float32Array(f.hidden_states.data),X=f.logits.data,U=f.new_kv,W+=1,fe+=1}let me=J.length,$=i(J,.6),he=performance.now()-e;console.log(`[detect] done in ${he.toFixed(0)}ms, ${$.length} detections (${me} raw, ${me-$.length} merged by bbox-IoU NMS)`),h($,he)}catch(e){console.error(`[detect] error:`,e),f({type:`error`,message:x(e,`Inference failed`)})}finally{t.close(),l=!1;let e=u;u=null,e&&v(e)}}function b(e,t,n){let r=0,i=-1/0;for(let a=0;a<n;a++)e[t+a]>i&&(i=e[t+a],r=a);return r}function x(e,t){return e instanceof Error?e.message:t}function ne(e){return{[r.coord_token_id]:`<coord>`,[r.size_token_id]:`<size>`,[r.seg_token_id]:`<seg>`,[r.eos_id]:`<eos>`,[r.presence_token_id]:`<presence>`,[r.absence_token_id]:`<absence>`,[r.end_of_query_token_id]:`<end_of_query>`}[e]??`token_${e}`}self.onmessage=async e=>{switch(e.data.type){case`load`:await g();break;case`detect`:v(e.data);break}};
|
index.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
});
|
| 16 |
}
|
| 17 |
</script>
|
| 18 |
-
<script type="module" crossorigin src="/assets/index-
|
| 19 |
<link rel="stylesheet" crossorigin href="/assets/index-DpjQuLKn.css">
|
| 20 |
</head>
|
| 21 |
<body class="bg-gray-950 text-gray-100 antialiased">
|
|
|
|
| 15 |
});
|
| 16 |
}
|
| 17 |
</script>
|
| 18 |
+
<script type="module" crossorigin src="/assets/index-DbiX_hBC.js"></script>
|
| 19 |
<link rel="stylesheet" crossorigin href="/assets/index-DpjQuLKn.css">
|
| 20 |
</head>
|
| 21 |
<body class="bg-gray-950 text-gray-100 antialiased">
|