diff --git a/CHANGELOG.md b/CHANGELOG.md index 5870693..0816df4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,52 @@ +## 0.15.0 - 2026-09-03 + +### ๐Ÿ› Bug Fixes + +- Rename vitest.config.ts to .mts to silence the CJS/ESM warning (63e802b) + +- Match_t is original, not derived from jsfeat (11572e4) + +- Reject mismatched descriptor widths and export the new types (1f0e55d) + +- Compare effective row bytes, not cols, and require U8 (6d87c69) + + +### ๐Ÿ“š Documentation + +- Record the agreed 1.0.0 milestone plan (dcfb524) + +- Restore the class description displaced by the ic_angle change (9c3d8b0) + + +### ๐Ÿ“ฆ Build + +- Bump actions/upload-artifact from 5 to 7 (7d28d72) + +- Bump vite from 8.2.1 to 8.2.2 (4ff82fc) + + +### ๐Ÿš€ Features + +- Brute-force Hamming matcher and match_t (f82d402) + +- Use bfmatcher in the ORB samples instead of inline match_pattern (4c48c50) + +- Closed-form planar pose from homography and intrinsics (c0ca5d5) + +- Expose ic_angle, the keypoint orientation step (#96) (3baaf09) + + +### ๐Ÿงช Testing + +- Cover ratio_test edge cases and empty-train cross-check (5fb2402) + +- Perturbed-H orthonormalization case; document pose_t.t (eb54c61) + +- Cover setIntrinsics, the n2 guard, and the normalize zero-fallback (24a9c65) + + + ## 0.14.0 - 2026-08-25 ### โšก Performance diff --git a/dist/jsfeatNext.js b/dist/jsfeatNext.js index 4731f19..28e557a 100644 --- a/dist/jsfeatNext.js +++ b/dist/jsfeatNext.js @@ -1,5 +1,5 @@ /*! - * jsfeatNext v0.14.0 โ€” https://github.com/webarkit/jsfeatNext + * jsfeatNext v0.15.0 โ€” https://github.com/webarkit/jsfeatNext * * SPDX-License-Identifier: LGPL-3.0-or-later * Copyright 2026 WebARKit. Author(s): Walter Perdan @kalwalt @@ -11,4 +11,4 @@ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for details: http://www.gnu.org/licenses/ */ -(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.jsfeatNext=t())})(this,function(){var e=new class{constructor(){this._data_type_size=new Int32Array([-1,1,4,-1,4,-1,-1,-1,8,-1,-1,-1,-1,-1,-1,-1,8])}_get_data_type(e){return e&65280}_get_channel(e){return e&255}_get_data_type_size(e){return this._data_type_size[(e&65280)>>8]}},t=class{constructor(e,t){this.size=(e+7|0)&-8,t===void 0?this.buffer=new ArrayBuffer(this.size):(this.buffer=t,this.size=t.byteLength),this.u8=new Uint8Array(this.buffer),this.i32=new Int32Array(this.buffer),this.f32=new Float32Array(this.buffer),this.f64=new Float64Array(this.buffer)}},n=class{constructor(e){this.next=null,this.data=new t(e),this.size=this.data.size,this.buffer=this.data.buffer,this.u8=this.data.u8,this.i32=this.data.i32,this.f32=this.data.f32,this.f64=this.data.f64}resize(e){delete this.data,this.data=new t(e),this.size=this.data.size,this.buffer=this.data.buffer,this.u8=this.data.u8,this.i32=this.data.i32,this.f32=this.data.f32,this.f64=this.data.f64}},r=class{constructor(){this._pool_head,this._pool_tail,this._pool_size=0}allocate(e,t){this._pool_head=this._pool_tail=new n(t);for(let r=0;rt.size&&t.resize(e),t}put_buffer(e){this._pool_tail=this._pool_tail.next=e,this._pool_size++}},i={EPSILON:1.192092896e-7,FLT_MIN:1e-37,U8_t:256,S32_t:512,F32_t:1024,S64_t:2048,F64_t:4096,C1_t:1,C2_t:2,C3_t:3,C4_t:4,COLOR_RGBA2GRAY:0,COLOR_RGB2GRAY:1,COLOR_BGRA2GRAY:2,COLOR_BGR2GRAY:3,BOX_BLUR_NOSCALE:1,SVD_U_T:1,SVD_V_T:2,U8C1_t:257,U8C3_t:259,U8C4_t:260,F32C1_t:1025,F32C2_t:1026,S32C1_t:513,S32C2_t:514},a={name:`@webarkit/jsfeat-next`,version:`0.14.0`,description:`Typescript version of jsfeat for WebARKit`,main:`dist/jsfeatNext.js`,module:`dist/jsfeatNext.mjs`,types:`types/src/index.d.ts`,unpkg:`dist/jsfeatNext.js`,jsdelivr:`dist/jsfeatNext.js`,exports:{".":{types:`./types/src/index.d.ts`,import:`./dist/jsfeatNext.mjs`,require:`./dist/jsfeatNext.js`},"./package.json":`./package.json`},files:[`dist`,`types`],scripts:{"build-ts":`vite build`,"dev-ts":`vite build --watch`,"format-check":`prettier --check .`,format:`prettier --write .`,"license-check":`node scripts/check-license-headers.mjs`,typecheck:`tsc --noEmit -p tsconfig.check.json`,"bench:smoke":`vitest bench --run --testNamePattern="__collect_only__"`,test:`vitest run`,"test:coverage":`vitest run --coverage`,bench:`vitest bench`,"bench:ratios":`vitest bench --run --outputJson bench-results/raw.json && node scripts/bench-ratios.mjs bench-results/raw.json --append bench/history.jsonl`,"test:watch":`vitest`,docs:`typedoc`},repository:{type:`git`,url:`git+https://github.com/webarkit/jsfeatNext.git`},keywords:[`jsfeat`,`jsfeatNext`,`WebAR`,`WebARKit`,`AugmentedReality`,`computer`,`vision`],author:`Walter Perdan @kalwalt`,license:`LGPL-3.0-or-later`,bugs:{url:`https://github.com/webarkit/jsfeatNext/issues`},homepage:`https://github.com/webarkit/jsfeatNext#readme`,devDependencies:{"@vitest/coverage-v8":`^4.1.11`,prettier:`~3.9.4`,typedoc:`^0.28.20`,typescript:`^6.0.3`,vite:`^8.1.4`,"vite-plugin-dts":`^5.0.3`,vitest:`^4.1.10`}},o,s=new r;s.allocate(30,2560);var c=class{constructor(){this.dt=e,this.cache=s}get_data_type(e){return this.dt._get_data_type(e)}get_channel(e){return this.dt._get_channel(e)}get_data_type_size(e){return this.dt._get_data_type_size(e)}};o=c,o.VERSION=a.version,o.EPSILON=i.EPSILON,o.FLT_MIN=i.FLT_MIN,o.U8_t=i.U8_t,o.S32_t=i.S32_t,o.F32_t=i.F32_t,o.S64_t=i.S64_t,o.F64_t=i.F64_t,o.C1_t=i.C1_t,o.C2_t=i.C2_t,o.C3_t=i.C3_t,o.C4_t=i.C4_t,o.COLOR_RGBA2GRAY=i.COLOR_RGBA2GRAY,o.COLOR_RGB2GRAY=i.COLOR_RGB2GRAY,o.COLOR_BGRA2GRAY=i.COLOR_BGRA2GRAY,o.COLOR_BGR2GRAY=i.COLOR_BGR2GRAY,o.BOX_BLUR_NOSCALE=i.BOX_BLUR_NOSCALE,o.SVD_U_T=i.SVD_U_T,o.SVD_V_T=i.SVD_V_T,o.U8C1_t=o.U8_t|o.C1_t,o.U8C3_t=o.U8_t|o.C3_t,o.U8C4_t=o.U8_t|o.C4_t,o.F32C1_t=o.F32_t|o.C1_t,o.F32C2_t=o.F32_t|o.C2_t,o.S32C1_t=o.S32_t|o.C1_t,o.S32C2_t=o.S32_t|o.C2_t;var l=class{constructor(t,n,r,a){this.dt=e,this.type=this.dt._get_data_type(r)|0,this.channel=this.dt._get_channel(r)|0,this.cols=t|0,this.rows=n|0,a===void 0?this.allocate():(this.buffer=a,this.data=this.type&i.U8_t?this.buffer.u8:this.type&i.S32_t?this.buffer.i32:this.type&i.F32_t?this.buffer.f32:this.buffer.f64)}allocate(){delete this.data,delete this.buffer,this.buffer=new t(this.cols*this.dt._get_data_type_size(this.type)*this.channel*this.rows),this.data=this.type&i.U8_t?this.buffer.u8:this.type&i.S32_t?this.buffer.i32:this.type&i.F32_t?this.buffer.f32:this.buffer.f64}copy_to(e){let t=e.data,n=this.data,r=0,i=this.cols*this.rows*this.channel|0;for(;rthis.buffer.size?(this.cols=e,this.rows=t,this.channel=n,this.allocate()):(this.cols=e,this.rows=t,this.channel=n)}};function u(e,t,n,r,i){let a=0,o=e.channel,s=e.cols,c=e.rows,l=e.data,u=t.data,d=s/r,f=c/i,p=d*f*65536|0,m=0,h=0,g=0,_=0,v=0,y=0,b=0,x=0,S=0,C=0,w=0,T=0,E=0,D=0,O=0,k=0,A=n.get_buffer(r*o<<2),j=n.get_buffer(r*o<<2),M=n.get_buffer(s*2*3<<2),N=A.i32,P=j.i32,F=M.i32;for(;mS&&(F[x++]=m*o|0,F[x++]=(v-1)*o|0,F[x++]=(v-S)*256|0,a++),g=v;g.001&&(a++,F[x++]=m*o|0,F[x++]=y*o|0,F[x++]=(C-y)*256|0)}for(m=0;mS&&(a++,F[x++]=(v-1)*o|0,F[x++]=m*o|0,F[x++]=(v-S)*p),g=v;g.001&&(a++,F[x++]=y*o|0,F[x++]=m*o|0,F[x++]=(C-y)*p)}for(m=0;m>8,255),n[f+l+1]=Math.min(m>>8,255),n[f+l+2]=Math.min(h>>8,255),n[f+l+3]=Math.min(g>>8,255)}for(;l>8,255)}d+=r,f+=r}for(c=0;c>8,255),n[f+r]=Math.min(m>>8,255),n[f+y]=Math.min(h>>8,255),n[f+b]=Math.min(g>>8,255)}for(;l>8,255)}}}function p(e,t,n,r,i,a,o,s){let c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0,g=0,_=a[0],v=0,y=r<<1,b=r*3,x=r<<2;for(;c>1){case 0:f[0]=1,u=1;break;case 1:f[0]=.25,f[1]=.5,f[2]=.25,u=1;break;case 2:f[0]=.0625,f[1]=.25,f[2]=.375,f[3]=.25,f[4]=.0625,u=1;break;case 3:f[0]=.03125,f[1]=.109375,f[2]=.21875,f[3]=.28125,f[4]=.21875,f[5]=.109375,f[6]=.03125,u=1}else for(c=t>0?t:((e-1)*.5-1)*.3+.8,l=-.5/(c*c);a=0;)for(l=E[c<<1],u=E[(c<<1)+1],c--;;){if(f=u-l+1,f<=7){for(m=l+1;m<=u;m++)for(h=m;h>l&&r(e[h],e[h-1]);h--)i=e[h],e[h]=e[h-1],e[h-1]=i;break}for(T=0,_=l,y=u,x=l+(f>>1),f>40&&(g=f>>3,S=l,C=l+g,w=l+(g<<1),a=e[S],o=e[C],s=e[w],l=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w,S=x-g,C=x,w=x+g,a=e[S],o=e[C],s=e[w],x=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w,S=u-(g<<1),C=u-g,w=u,a=e[S],o=e[C],s=e[w],u=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w),S=l,C=x,w=u,a=e[S],o=e[C],s=e[w],x=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w,x!=_&&(i=e[x],e[x]=e[_],e[_]=i,x=_),l=v=_+1,u=b=y,a=e[x];;){for(;l<=u&&!r(a,e[l]);)r(e[l],a)||(l>v&&(i=e[v],e[v]=e[l],e[l]=i),T=1,v++),l++;for(;l<=u&&!r(e[u],a);)r(a,e[u])||(uu)break;i=e[l],e[l]=e[u],e[u]=i,T=1,l++,u--}if(T==0){for(l=_,u=y,m=l+1;m<=u;m++)for(h=m;h>l&&r(e[h],e[h-1]);h--)i=e[h],e[h]=e[h-1],e[h-1]=i;break}for(f=Math.min(v-_,l-v),p=l-f|0,d=0;d1)p>1?f>p?(++c,E[c<<1]=_,E[(c<<1)+1]=_+f-1,l=y-p+1,u=y):(++c,E[c<<1]=y-p+1,E[(c<<1)+1]=y,l=_,u=_+f-1):(l=_,u=_+f-1);else if(p>1)l=y-p+1,u=y;else break}}median(e,t,n){let r,i=0,a=0,o=0,s=t+n>>1;for(;;){if(n<=t)return e[s];if(n==t+1)return e[t]>e[n]&&(r=e[t],e[t]=e[n],e[n]=r),e[s];for(i=t+n>>1,e[i]>e[n]&&(r=e[i],e[i]=e[n],e[n]=r),e[t]>e[n]&&(r=e[t],e[t]=e[n],e[n]=r),e[i]>e[t]&&(r=e[i],e[i]=e[t],e[t]=r),a=t+1,r=e[i],e[i]=e[a],e[a]=r,o=n;;){do++a;while(e[t]>e[a]);do--o;while(e[o]>e[t]);if(o=s&&(n=o-1)}return 0}},h=class extends c{constructor(){super()}grayscale(e,t,n,r,a){a===void 0&&(a=i.COLOR_RGBA2GRAY);let o=0,s=0,c=0,l=0,u=0,d=0,f=4899,p=9617,m=1868,h=4;(a==i.COLOR_BGRA2GRAY||a==i.COLOR_BGR2GRAY)&&(f=1868,m=4899),(a==i.COLOR_RGB2GRAY||a==i.COLOR_BGR2GRAY)&&(h=3);let g=h<<1,_=h*3|0;r.resize(t,n,1);let v=r.data;for(s=0;s>14,v[d+1]=e[u+h]*f+e[u+h+1]*p+e[u+h+2]*m+8192>>14,v[d+2]=e[u+g]*f+e[u+g+1]*p+e[u+g+2]*m+8192>>14,v[d+3]=e[u+_]*f+e[u+_+1]*p+e[u+_+2]*m+8192>>14;for(;o>14}}resample(e,t,n,r){let a=e.rows,o=e.cols;a>r&&o>n&&(t.resize(n,r,e.channel),e.type&i.U8_t&&t.type&i.U8_t&&a*o/(r*n)<256?u(e,t,this.cache,n,r):d(e,t,this.cache,n,r))}box_blur_gray(e,t,n,r){r===void 0&&(r=0),n|=0;let a=e.cols|0,o=e.rows|0,s=n+1|0,c=(n<<1)+1|0,l=c*c,u=(r&i.BOX_BLUR_NOSCALE)!==0,d=this.cache.get_buffer(a*o<<2),f=d.i32;t.resize(a,o,e.channel);let p=0,m=0,h=0,g=0,_=0,v=0,y=0,b=e.data;for(m=0;m0?v:0)]}let x=t.data;for(m=0;m0?v:0)]}this.cache.put_buffer(d)}gaussian_blur(e,t,n,r){let a=new m;r===void 0&&(r=0),n===void 0&&(n=0),n=n==0?Math.max(1,4*r+1-1e-8)*2+1|0:n;let o=n>>1,s=e.cols,c=e.rows,l=e.type,u=l&i.U8_t;t.resize(s,c,e.channel);let d=e.data,h=t.data,g,_,v=n+Math.max(c,s)|0,y=this.cache.get_buffer(v<<2),b=this.cache.get_buffer(n<<2);u?(g=y.i32,_=b.i32):l&i.S32_t?(g=y.i32,_=b.f32):(g=y.f32,_=b.f32),a.get_gaussian_kernel(n,r,_,l),u?f(g,d,h,s,c,_,n,o):p(g,d,h,s,c,_,n,o),this.cache.put_buffer(y),this.cache.put_buffer(b)}hough_transform(e,t,n,r){let i,a,o=e.data,s=e.cols,c=e.rows,l=s,u=Math.round((Math.PI-0)/n),d=Math.round(((s+c)*2+1)/t),f=1/t,p=new Int32Array((u+2)*(d+2)),m=new Float32Array(u),h=new Float32Array(u),g=0,_=0;for(;gr&&p[e]>p[e-1]&&p[e]>=p[e+1]&&p[e]>p[e-d-2]&&p[e]>=p[e+d+2]&&v.push(e)}v.sort(function(e,t){return p[e]>p[t]||p[e]==p[t]&&e>1,s=a>>1,c=o-(n<<1),l=s-(r<<1),u=0,d=0,f=n+r*i,p=0,m=0,h=0;t.resize(o,s,e.channel);let g=e.data,_=t.data;for(d=0;d>2,_[h+1]=g[p+2]+g[p+3]+g[p+i+2]+g[p+i+3]+2>>2;for(;u>2;f+=i<<1,m+=o}}scharr_derivatives(e,t){let n=e.cols,r=e.rows,a=n<<1,o=0,s=0,c=0,l,u,d,f,p,m,h=0,g=0,_=0,v=0,y,b;t.resize(n,r,2);let x=e.data,S=t.data,C=this.cache.get_buffer(n+2<<2),w=this.cache.get_buffer(n+2<<2);for(e.type&i.U8_t||e.type&i.S32_t?(y=C.i32,b=w.i32):(y=C.f32,b=w.f32);s0?s-1:1)*n|0,_=(s0?s-1:1)*n|0,_=(s0;--p)for(u=p+a*s,d=u-s,f=a;f>0;--f,u-=s,d-=s)r[u]+=r[d]+r[d+1]}}equalize_histogram(e,t){let n=e.cols,r=e.rows,i=e.data;t.resize(n,r,e.channel);let a=t.data,o=n*r,s=0,c=0,l,u,d=this.cache.get_buffer(1024);for(l=d.i32;s<256;++s)l[s]=0;for(s=0;sr&&(c=n,n=r,r=c),c=3*(a+2)|0;--c>=0;)T[c]=0;for(c=(o+2)*(a+2)|0;--c>=0;)E[c]=0;for(;u>31)-(g>>31)+((_^_>>31)-(_>>31));for(c=1;c<=o;++c,d+=f){if(c==o)for(u=M+a;--u>=M;)T[u]=0;else for(u=0;u>31)-(g>>31)+((_^_>>31)-(_>>31));for(p=d-f|0,E[P-1]=0,m=0,u=0;un){if(g=O[p],_=O[p+1],v=g^_,g=(g^g>>31)-(g>>31)|0,_=(_^_>>31)-(_>>31)|0,y=g*13573,b=y+(g+g<<15),_<<=15,_T[j+u-1]&&h>=T[j+u+1]){h>r&&!m&&E[P+u-N]!=2?(E[P+u]=2,m=1,D[F++]=P+u):E[P+u]=1;continue}}else if(_>b){if(h>T[A+u]&&h>=T[M+u]){h>r&&!m&&E[P+u-N]!=2?(E[P+u]=2,m=1,D[F++]=P+u):E[P+u]=1;continue}}else if(v=v<0?-1:1,h>T[A+u-v]&&h>T[M+u+v]){h>r&&!m&&E[P+u-N]!=2?(E[P+u]=2,m=1,D[F++]=P+u):E[P+u]=1;continue}}E[P+u]=0,m=0}E[P+a]=0,P+=N,u=A,A=j,j=M,M=u}for(u=P-N-1,c=0;c0;)P=D[--F],P-=N+1,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P),P+=N,E[P]==1&&(E[P]=2,D[F++]=P),P-=2,E[P]==1&&(E[P]=2,D[F++]=P),P+=N,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P);for(P=N+1,A=0,c=0;c0&&g>0&&p=0&&g>=0&&p95&&r>40&&i>20&&n>r&&n>i&&n-Math.min(r,i)>15&&Math.abs(n-r)>15?t[o]=255:t[o]=0}};function g(e,t,n,r){r=e[t],e[t]=e[n],e[n]=r}function _(e,t){return e=Math.abs(e),t=Math.abs(t),e>t?(t/=e,e*Math.sqrt(1+t*t)):t>0?(e/=t,t*Math.sqrt(1+e*e)):0}var v=i.EPSILON,y=class{constructor(){}identity(e,t){t===void 0&&(t=1);let n=e.data,r=e.rows,i=e.cols,a=i+1|0,o=r*i,s=o;for(;--o>=0;)n[o]=0;for(o=s,s=0;s-v?0:1}multiply_3x3(e,t,n){let r=e.data,i=t.data,a=n.data,o=i[0],s=i[1],c=i[2],l=i[3],u=i[4],d=i[5],f=i[6],p=i[7],m=i[8],h=a[0],g=a[1],_=a[2],v=a[3],y=a[4],b=a[5],x=a[6],S=a[7],C=a[8];r[0]=o*h+s*v+c*x,r[1]=o*g+s*y+c*S,r[2]=o*_+s*b+c*C,r[3]=l*h+u*v+d*x,r[4]=l*g+u*y+d*S,r[5]=l*_+u*b+d*C,r[6]=f*h+p*v+m*x,r[7]=f*g+p*y+m*S,r[8]=f*_+p*b+m*C}mat3x3_determinant(e){let t=e.data;return t[0]*t[4]*t[8]-t[0]*t[5]*t[7]-t[3]*t[1]*t[8]+t[3]*t[2]*t[7]+t[6]*t[1]*t[5]-t[6]*t[2]*t[4]}determinant_3x3(e,t,n,r,i,a,o,s,c){return e*i*c-e*a*s-r*t*c+r*n*s+o*t*a-o*n*i}},b=class extends c{constructor(){super(),this.matmath=new y}JacobiImpl(e,t,n,r,a,o){let s=i.EPSILON,c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0,v=0,y=o*o*30,b=0,x=0,S=0,C=0,w=0,T=0,E=0,D=0,O=0,k=this.cache.get_buffer(o<<2),A=this.cache.get_buffer(o<<2),j=k.i32,M=A.i32;if(r)for(;c0){for(d=0,b=Math.abs(e[u]),c=1;c1)for(;v0){for(d=0,b=Math.abs(e[p]),c=1;c>16&256?L:-L,e[d*t+p]=I;for(m=0;m<2;m++)for(f=0;fMath.abs(c[a*s+n])&&(a=r);if(Math.abs(c[a*s+n])=0;n--){for(p=l[n],a=n+1;a=0;s--){for(f=d[s],c=s+1,a=c*l;c=0;)n.data[s]=_.data[s];else n&&this.matmath.transpose(n,_);if(r&&a&i.SVD_V_T)for(s=f*f;--s>=0;)r.data[s]=y.data[s];else r&&this.matmath.transpose(r,y)}else{if(n&&a&i.SVD_U_T)for(s=f*f;--s>=0;)n.data[s]=y.data[s];else n&&this.matmath.transpose(n,y);if(r&&a&i.SVD_V_T)for(s=d*d;--s>=0;)r.data[s]=_.data[s];else r&&this.matmath.transpose(r,_)}this.cache.put_buffer(m),this.cache.put_buffer(h),this.cache.put_buffer(g)}svd_solve(e,t,n){let r=0,a=0,o=0,s=0,c=0,u=e.rows,d=e.cols,f=0,p=0,m=0,h=e.type|i.C1_t,g=this.cache.get_buffer(u*u<<3),_=this.cache.get_buffer(d<<3),v=this.cache.get_buffer(d*d<<3),y=new l(u,u,h,g.data),b=new l(1,d,h,_.data),x=new l(d,d,h,v.data),S=n.data,C=y.data,w=b.data,T=x.data;for(this.svd_decompose(e,b,y,x,0),m=i.EPSILON*w[0]*d;rm){for(o=0,f=0,s=0;op&&(f+=w[s+a]*S[o]/C[a]);x[c]=f}this.cache.put_buffer(h),this.cache.put_buffer(g),this.cache.put_buffer(_)}eigenVV(e,t,n){let r=e.cols,a=r*r,o=e.type|i.C1_t,s=this.cache.get_buffer(r*r<<3),c=this.cache.get_buffer(r<<3),u=new l(r,r,o,s.data),d=new l(1,r,o,c.data);for(;--a>=0;)u.data[a]=e.data[a];if(this.JacobiImpl(u.data,r,d.data,t?t.data:null,r,r),n)for(;--r>=0;)n.data[r]=d.data[r];this.cache.put_buffer(s),this.cache.put_buffer(c)}};function x(e,t,n,r,i){let a=0,o=e[t],s=i,c=0,l=0,u=0;for(;a<25;++a)r[a]=o-e[t+n[a]];for(a=0;a<16;a+=2)c=Math.min(r[a+1],r[a+2]),c=Math.min(c,r[a+3]),!(c<=s)&&(c=Math.min(c,r[a+4]),c=Math.min(c,r[a+5]),c=Math.min(c,r[a+6]),c=Math.min(c,r[a+7]),c=Math.min(c,r[a+8]),s=Math.max(s,Math.min(c,r[a])),s=Math.max(s,Math.min(c,r[a+9])));for(l=-s,a=0;a<16;a+=2)u=Math.max(r[a+1],r[a+2]),u=Math.max(u,r[a+3]),u=Math.max(u,r[a+4]),u=Math.max(u,r[a+5]),!(u>=l)&&(u=Math.max(u,r[a+6]),u=Math.max(u,r[a+7]),u=Math.max(u,r[a+8]),l=Math.min(l,Math.max(u,r[a])),l=Math.min(l,Math.max(u,r[a+9])));return-l-1}var S=class extends c{constructor(){super(),this.offsets16=new Int32Array([0,3,1,3,2,2,3,1,3,0,3,-1,2,-2,1,-3,0,-3,-1,-3,-2,-2,-3,-1,-3,0,-3,1,-2,2,-1,3]),this.threshold_tab=new Uint8Array(512),this._threshold=20,this.pixel_off=new Int32Array(25),this.score_diff=new Int32Array(25)}set_threshold(e){this._threshold=Math.min(Math.max(e,0),255);for(let e=-255;e<=255;++e)this.threshold_tab[e+255]=e<-this._threshold?1:e>this._threshold?2:0;return this._threshold}detect(e,t,n){n===void 0&&(n=3);let r=e.data,i=e.cols,a=e.rows,o=0,s=0,c=0,l=0,u=0,d=0,f=this.cache.get_buffer(3*i),p=this.cache.get_buffer((i+1)*3<<2),m=f.u8,h=p.i32,g=this.pixel_off,_=this.score_diff,v=Math.max(3,n),y=Math.min(a-2,a-n),b=Math.max(3,n),S=Math.min(i-3,i-n),C=0,w=0,T,E=x,D=this.threshold_tab,O=this._threshold,k=0,A=0,j=0,M=0,N=0,P=0,F=0,I=0,L=0,R=0,z=0,B=0;this._cmp_offsets(g,i,16);let V=g[0],ee=g[1],H=g[2],U=g[3],W=g[4],G=g[5],K=g[6],te=g[7],q=g[8],ne=g[9],J=g[10],Y=g[11],X=g[12],Z=g[13],Q=g[14],re=g[15];for(o=0;o8){++M,h[N+M]=s,m[P+s]=E(r,F,g,_,O);break}}else C=0;if(j&2)for(l=k+O,C=0,c=0;c<25;++c)if(u=r[F+g[c]],u>l){if(++C,C>8){++M,h[N+M]=s,m[P+s]=E(r,F,g,_,O);break}}else C=0}}if(h[N+i]=M,o!=v)for(d=(o-4+3)%3,I=d*i|0,N=d*(i+1)|0,d=(o-5+3)%3,L=d*i|0,M=h[N+i],c=0;cm[I+R]&&B>m[I+z]&&B>m[L+z]&&B>m[L+s]&&B>m[L+R]&&B>m[P+z]&&B>m[P+s]&&B>m[P+R]&&(T=t[w],T.x=s,T.y=o-1,T.score=B,w++)}return this.cache.put_buffer(f),this.cache.put_buffer(p),w}_cmp_offsets(e,t,n){let r=0,i=this.offsets16;for(;r=0;)this.data[r]=new l(e>>r,t>>r,n)}build(e,t){t===void 0&&(t=!0);let n=2,r=e,i=this.data[0];if(!t){let t=e.cols*e.rows;for(;--t>=0;)i.data[t]=e.data[t]}for(i=this.data[1],this.pyrdown(r,i);n=0;i--,r++)a=Math.sqrt(n*n-i*i)+.5|0,t[r]=i+e*a;for(;-i=0;a--,r++)i=-Math.sqrt(n*n-a*a)-.5|0,t[r]=i+e*a;for(;a>i;a--,r++)i=-Math.sqrt(n*n-a*a)-.5|0,t[r]=i+e*a;for(i++;i<=0;i++,r++)a=-Math.sqrt(n*n-i*i)-.5|0,t[r]=i+e*a;for(;i<-a;i++,r++)a=-Math.sqrt(n*n-i*i)-.5|0,t[r]=i+e*a;for(a++;a<0;a++,r++)i=Math.sqrt(n*n-a*a)+.5|0,t[r]=i+e*a;return t[r]=t[0],t[r+1]=t[1],r}function A(e,t,n){let r=0;return e[t+1]!=0&&r++,e[t-1]!=0&&r++,e[t+n]!=0&&r++,e[t+n+1]!=0&&r++,e[t+n-1]!=0&&r++,e[t-n]!=0&&r++,e[t-n+1]!=0&&r++,e[t-n-1]!=0&&r++,r}function j(e,t,n,r,i){let a,o;if(n>0)for(t-=r*i,o=-i;o<=i;++o){for(a=-i;a<=i;++a)if(e[t+a]>n)return!1;t+=r}else for(t-=r*i,o=-i;o<=i;++o){for(a=-i;a<=i;++a)if(e[t+a]=r){if(f=e[t+a[u]],f<=i){if(f>=r){n[t]=0;return}if(u++,p=e[t+a[u]],p>i){if(u++,m=e[t+a[u]],m>i)h=3;else if(mi)h=7;else if(mi){if(u++,m=e[t+a[u]],m>i)h=3;else if(mi)h=7;else if(mi){n[t]=0;return}if(u++,p=e[t+a[u]],p>i){n[t]=0;return}if(u++,m=e[t+a[u]],m>i){n[t]=0;return}h=1}}else{if(f=e[t+a[u]],fi){if(p=m,u++,m=e[t+a[u]],mi){n[t]=0;return}if(m>i){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],m>i){n[t]=0;return}c-=d+p,h=8;break}if(p<=i){n[t]=0;return}if(m<=i){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],m>i){c-=d+p,h=3;break}if(mi){n[t]=0;return}c-=d+p,h=1;break}if(d>i){if(p=r){n[t]=0;return}if(m>=r){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],mi){c-=d+p,h=7;break}n[t]=0;return;case 2:if(d>i){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],di){n[t]=0;return}c-=d+p,h=4;break}if(m>i){c-=d+p,h=7;break}if(mi){if(mi){c-=d+p,h=3;break}if(mi){n[t]=0;return}if(di){n[t]=0;return}c-=d+p,h=1;break}if(m>=r){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],mi){c-=d+p,h=7;break}n[t]=0;return;case 5:if(di){if(p=m,u++,m=e[t+a[u]],mi){c-=d+p,h=3;break}if(mi){n[t]=0;return}if(di){c-=d+p,h=3;break}if(mi){n[t]=0;return}if(di){c-=d+p,h=7;break}n[t]=0;return;case 8:if(d>i){if(mi){n[t]=0;return}c-=d+p,h=1;break}n[t]=0;return;case 9:if(di){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],m>i){n[t]=0;return}c-=d+p,h=8;break}if(d>i){if(p=m,u++,m=e[t+a[u]],m>i,t>>i,n)}detect(e,t,n=4){let r=this.level_tables[0],i=r.radius|0,a=i-1|0,o=r.dirs,s=r.dirs_count|0,c=s>>1,l=e.data,u=e.cols|0,d=e.rows|0,f=u>>1,p=r.scores,m=0,h=0,g=0,_=0,v=0,y=0,b=0,x=0,S=this.tau|0,C=0,w,T=Math.max(i+1,n)|0,E=Math.max(i+1,n)|0,D=Math.min(u-i-2,u-n)|0,O=Math.min(d-i-2,d-n)|0;for(g=E*u+T|0,h=E;h=3&&F(p,_,x,f,i)&&(w=t[C],w.x=m,w.y=h,w.score=b,++C,m+=a,_+=a);return C}};function R(e,t,n,r,i,a,o,s,c){let l=0,u=0,d=o*n+a|0,f=d;for(l=o;l=0&&f+i=0?t[f]=-4*e[f]+e[f+r]+e[f-r]+e[f+i]+e[f-i]:t[f]=0}function z(e,t,n,r,i,a,o){let s=-2*e[t]+e[t+r]+e[t-r],c=-2*e[t]+e[t+i]+e[t-i],l=e[t+a]+e[t-a]-e[t+o]-e[t-o],u=Math.sqrt((s-c)*(s-c)+4*l*l)|0;return Math.min(Math.abs(n-u),Math.abs(-(n+u)))}var B=R,V=z,ee=class extends c{constructor(){super(),this.laplacian_threshold=30,this.min_eigen_value_threshold=25}detect(e,t,n){n===void 0&&(n=5);let r=0,i=0,a=e.cols,o=e.rows,s=e.data,c=5*a|0,l=3+3*a|0,u=3-3*a|0,d=this.cache.get_buffer(a*o<<2),f=d.i32,p=0,m=0,h=0,g=0,_,v=0,y=this.laplacian_threshold,b=this.min_eigen_value_threshold,x=Math.max(5,n)|0,S=Math.max(3,n)|0,C=Math.min(a-5,a-n)|0,w=Math.min(o-3,o-n)|0;for(r=a*o;--r>=0;)f[r]=0;for(B(s,f,a,5,c,x,S,C,w),m=S*a+x|0,i=S;iy&&p>f[h-1]&&p>f[h+1]&&p>f[h-a]&&p>f[h+a]&&p>f[h-a-1]&&p>f[h+a-1]&&p>f[h-a+1]&&p>f[h+a+1])&&(g=V(s,h,p,5,c,l,u),g>b&&(_=t[v],_.x=r,_.y=i,_.score=g,++v,++r,++h));return this.cache.put_buffer(d),v}},H=class{constructor(e=0,t=.5,n=.5,r=.99){this.size=e,this.thresh=t,this.eps=n,this.prob=r}update_iters(e,t){let n=Math.log(1-this.prob),r=Math.log(1-Math.pow(1-e,this.size));return(r>=0||-n>=t*-r?t:Math.round(n/r))|0}},U=class extends c{constructor(){super()}get_subset(e,t,n,r,i,a,o){let s=1e3,c=[],l=0,u=0,d=0,f=0,p=!1;for(;d=0;)s.data[a]=1;return this.cache.put_buffer(b),this.cache.put_buffer(x),this.cache.put_buffer(S),!0}for(;fMath.max(T,u-1)&&(C.copy_to(o),T=E,s&&w.copy_to(s),d=e.update_iters((a-E)/a,d),p=!0))}return this.cache.put_buffer(b),this.cache.put_buffer(x),this.cache.put_buffer(S),p}lmeds(e,t,n,r,a,o,s,c){if(c===void 0&&(c=1e3),a=0;)s.data[a]=1;return this.cache.put_buffer(S),this.cache.put_buffer(C),this.cache.put_buffer(w),!0}for(;f=u),this.cache.put_buffer(S),this.cache.put_buffer(C),this.cache.put_buffer(w),p}},W=class extends c{constructor(){super(),this.T0=new l(3,3,i.F32_t|i.C1_t),this.T1=new l(3,3,i.F32_t|i.C1_t),this.AtA=new l(6,6,i.F32_t|i.C1_t),this.AtB=new l(6,1,i.F32_t|i.C1_t)}sqr(e){return e*e}iso_normalize_points(e,t,n,r,i){let a=0,o=0,s=0,c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0;for(;a=0;)u[a]=0;for(a=0;a=0;--X)for(I=1/(1<>X,S=b>>X,A=x<<1,_=h[X].data,v=g[X].data,re=x-o|0,ie=S-o|0,this.scharr_deriv(h[X],E),Z=0;Z=re||G<=0||G>=ie,J!=0){X==0&&(c[Z]=0);continue}for(ae=L-W,oe=R-G,fe=(1-ae)*(1-oe)*le+.5|0,pe=ae*(1-oe)*le+.5|0,me=(1-ae)*oe*le+.5|0,he=le-fe-pe-me,ve=0,ye=0,be=0,Y=0;Y>9,_e=k[M]*fe+k[M+2]*pe+k[M+A]*me+k[M+A+2]*he,_e=_e+ue>>14,$=k[M+1]*fe+k[M+3]*pe+k[M+A+1]*me+k[M+A+3]*he,$=$+ue>>14,D[N]=ge,O[P++]=_e,O[P++]=$,ve+=_e*_e,ye+=_e*$,be+=$*$;if(ve*=de,ye*=de,be*=de,xe=ve*be-ye*ye,Se=(be+ve-Math.sqrt((ve-be)*(ve-be)+4*ye*ye))/m,Se=re||te<=0||te>=ie,J!=0){X==0&&(c[Z]=0);break}for(ae=z-K,oe=B-te,fe=(1-ae)*(1-oe)*le+.5|0,pe=ae*(1-oe)*le+.5|0,me=(1-ae)*oe*le+.5|0,he=le-fe-pe-me,se=0,ce=0,Y=0;Y>9,ge-=D[N],se+=ge*O[P++],ce+=ge*O[P++];if(se*=de,ce*=de,H=(ye*ce-be*se)*xe,U=(ye*se-ve*ce)*xe,z+=H,B+=U,r[q]=z+f,r[ne]=B+f,H*H+U*U<=u)break;if(Q>0&&Math.abs(H+V)<.01&&Math.abs(U+ee)<.01){r[q]-=H*.5,r[ne]-=U*.5;break}V=H,ee=U}}this.cache.put_buffer(C),this.cache.put_buffer(w),this.cache.put_buffer(T)}},q=c;return c.cache=s,c.pyramid_t=C,c.matrix_t=l,c.keypoint_t=T,c.ransac_params_t=H,c.transform=new w,c.fast_corners=new S,c.imgproc=new h,c.math=new m,c.matmath=new y,c.linalg=new b,c.orb=new O,c.yape=new L,c.yape06=new ee,c.motion_estimator=new U,c.affine2d=new G,c.homography2d=new K,c.optical_flow_lk=new te,q}); \ No newline at end of file +(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.jsfeatNext=t())})(this,function(){var e=new class{constructor(){this._data_type_size=new Int32Array([-1,1,4,-1,4,-1,-1,-1,8,-1,-1,-1,-1,-1,-1,-1,8])}_get_data_type(e){return e&65280}_get_channel(e){return e&255}_get_data_type_size(e){return this._data_type_size[(e&65280)>>8]}},t=class{constructor(e,t){this.size=(e+7|0)&-8,t===void 0?this.buffer=new ArrayBuffer(this.size):(this.buffer=t,this.size=t.byteLength),this.u8=new Uint8Array(this.buffer),this.i32=new Int32Array(this.buffer),this.f32=new Float32Array(this.buffer),this.f64=new Float64Array(this.buffer)}},n=class{constructor(e){this.next=null,this.data=new t(e),this.size=this.data.size,this.buffer=this.data.buffer,this.u8=this.data.u8,this.i32=this.data.i32,this.f32=this.data.f32,this.f64=this.data.f64}resize(e){delete this.data,this.data=new t(e),this.size=this.data.size,this.buffer=this.data.buffer,this.u8=this.data.u8,this.i32=this.data.i32,this.f32=this.data.f32,this.f64=this.data.f64}},r=class{constructor(){this._pool_head,this._pool_tail,this._pool_size=0}allocate(e,t){this._pool_head=this._pool_tail=new n(t);for(let r=0;rt.size&&t.resize(e),t}put_buffer(e){this._pool_tail=this._pool_tail.next=e,this._pool_size++}},i={EPSILON:1.192092896e-7,FLT_MIN:1e-37,U8_t:256,S32_t:512,F32_t:1024,S64_t:2048,F64_t:4096,C1_t:1,C2_t:2,C3_t:3,C4_t:4,COLOR_RGBA2GRAY:0,COLOR_RGB2GRAY:1,COLOR_BGRA2GRAY:2,COLOR_BGR2GRAY:3,BOX_BLUR_NOSCALE:1,SVD_U_T:1,SVD_V_T:2,NORM_HAMMING:6,U8C1_t:257,U8C3_t:259,U8C4_t:260,F32C1_t:1025,F32C2_t:1026,S32C1_t:513,S32C2_t:514},a={name:`@webarkit/jsfeat-next`,version:`0.15.0`,description:`Typescript version of jsfeat for WebARKit`,main:`dist/jsfeatNext.js`,module:`dist/jsfeatNext.mjs`,types:`types/src/index.d.ts`,unpkg:`dist/jsfeatNext.js`,jsdelivr:`dist/jsfeatNext.js`,exports:{".":{types:`./types/src/index.d.ts`,import:`./dist/jsfeatNext.mjs`,require:`./dist/jsfeatNext.js`},"./package.json":`./package.json`},files:[`dist`,`types`],scripts:{"build-ts":`vite build`,"dev-ts":`vite build --watch`,"format-check":`prettier --check .`,format:`prettier --write .`,"license-check":`node scripts/check-license-headers.mjs`,typecheck:`tsc --noEmit -p tsconfig.check.json`,"bench:smoke":`vitest bench --run --testNamePattern="__collect_only__"`,test:`vitest run`,"test:coverage":`vitest run --coverage`,bench:`vitest bench`,"bench:ratios":`vitest bench --run --outputJson bench-results/raw.json && node scripts/bench-ratios.mjs bench-results/raw.json --append bench/history.jsonl`,"test:watch":`vitest`,docs:`typedoc`},repository:{type:`git`,url:`git+https://github.com/webarkit/jsfeatNext.git`},keywords:[`jsfeat`,`jsfeatNext`,`WebAR`,`WebARKit`,`AugmentedReality`,`computer`,`vision`],author:`Walter Perdan @kalwalt`,license:`LGPL-3.0-or-later`,bugs:{url:`https://github.com/webarkit/jsfeatNext/issues`},homepage:`https://github.com/webarkit/jsfeatNext#readme`,devDependencies:{"@vitest/coverage-v8":`^4.1.11`,prettier:`~3.9.4`,typedoc:`^0.28.20`,typescript:`^6.0.3`,vite:`^8.1.4`,"vite-plugin-dts":`^5.0.3`,vitest:`^4.1.10`}},o,s=new r;s.allocate(30,2560);var c=class{constructor(){this.dt=e,this.cache=s}get_data_type(e){return this.dt._get_data_type(e)}get_channel(e){return this.dt._get_channel(e)}get_data_type_size(e){return this.dt._get_data_type_size(e)}};o=c,o.VERSION=a.version,o.EPSILON=i.EPSILON,o.FLT_MIN=i.FLT_MIN,o.U8_t=i.U8_t,o.S32_t=i.S32_t,o.F32_t=i.F32_t,o.S64_t=i.S64_t,o.F64_t=i.F64_t,o.C1_t=i.C1_t,o.C2_t=i.C2_t,o.C3_t=i.C3_t,o.C4_t=i.C4_t,o.COLOR_RGBA2GRAY=i.COLOR_RGBA2GRAY,o.COLOR_RGB2GRAY=i.COLOR_RGB2GRAY,o.COLOR_BGRA2GRAY=i.COLOR_BGRA2GRAY,o.COLOR_BGR2GRAY=i.COLOR_BGR2GRAY,o.BOX_BLUR_NOSCALE=i.BOX_BLUR_NOSCALE,o.SVD_U_T=i.SVD_U_T,o.SVD_V_T=i.SVD_V_T,o.NORM_HAMMING=i.NORM_HAMMING,o.U8C1_t=o.U8_t|o.C1_t,o.U8C3_t=o.U8_t|o.C3_t,o.U8C4_t=o.U8_t|o.C4_t,o.F32C1_t=o.F32_t|o.C1_t,o.F32C2_t=o.F32_t|o.C2_t,o.S32C1_t=o.S32_t|o.C1_t,o.S32C2_t=o.S32_t|o.C2_t;var l=class{constructor(t,n,r,a){this.dt=e,this.type=this.dt._get_data_type(r)|0,this.channel=this.dt._get_channel(r)|0,this.cols=t|0,this.rows=n|0,a===void 0?this.allocate():(this.buffer=a,this.data=this.type&i.U8_t?this.buffer.u8:this.type&i.S32_t?this.buffer.i32:this.type&i.F32_t?this.buffer.f32:this.buffer.f64)}allocate(){delete this.data,delete this.buffer,this.buffer=new t(this.cols*this.dt._get_data_type_size(this.type)*this.channel*this.rows),this.data=this.type&i.U8_t?this.buffer.u8:this.type&i.S32_t?this.buffer.i32:this.type&i.F32_t?this.buffer.f32:this.buffer.f64}copy_to(e){let t=e.data,n=this.data,r=0,i=this.cols*this.rows*this.channel|0;for(;rthis.buffer.size?(this.cols=e,this.rows=t,this.channel=n,this.allocate()):(this.cols=e,this.rows=t,this.channel=n)}};function u(e,t,n,r,i){let a=0,o=e.channel,s=e.cols,c=e.rows,l=e.data,u=t.data,d=s/r,f=c/i,p=d*f*65536|0,m=0,h=0,g=0,_=0,v=0,y=0,b=0,x=0,S=0,C=0,w=0,T=0,E=0,D=0,O=0,k=0,A=n.get_buffer(r*o<<2),j=n.get_buffer(r*o<<2),M=n.get_buffer(s*2*3<<2),N=A.i32,P=j.i32,F=M.i32;for(;mS&&(F[x++]=m*o|0,F[x++]=(v-1)*o|0,F[x++]=(v-S)*256|0,a++),g=v;g.001&&(a++,F[x++]=m*o|0,F[x++]=y*o|0,F[x++]=(C-y)*256|0)}for(m=0;mS&&(a++,F[x++]=(v-1)*o|0,F[x++]=m*o|0,F[x++]=(v-S)*p),g=v;g.001&&(a++,F[x++]=y*o|0,F[x++]=m*o|0,F[x++]=(C-y)*p)}for(m=0;m>8,255),n[f+l+1]=Math.min(m>>8,255),n[f+l+2]=Math.min(h>>8,255),n[f+l+3]=Math.min(g>>8,255)}for(;l>8,255)}d+=r,f+=r}for(c=0;c>8,255),n[f+r]=Math.min(m>>8,255),n[f+y]=Math.min(h>>8,255),n[f+b]=Math.min(g>>8,255)}for(;l>8,255)}}}function p(e,t,n,r,i,a,o,s){let c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0,g=0,_=a[0],v=0,y=r<<1,b=r*3,x=r<<2;for(;c>1){case 0:f[0]=1,u=1;break;case 1:f[0]=.25,f[1]=.5,f[2]=.25,u=1;break;case 2:f[0]=.0625,f[1]=.25,f[2]=.375,f[3]=.25,f[4]=.0625,u=1;break;case 3:f[0]=.03125,f[1]=.109375,f[2]=.21875,f[3]=.28125,f[4]=.21875,f[5]=.109375,f[6]=.03125,u=1}else for(c=t>0?t:((e-1)*.5-1)*.3+.8,l=-.5/(c*c);a=0;)for(l=E[c<<1],u=E[(c<<1)+1],c--;;){if(f=u-l+1,f<=7){for(m=l+1;m<=u;m++)for(h=m;h>l&&r(e[h],e[h-1]);h--)i=e[h],e[h]=e[h-1],e[h-1]=i;break}for(T=0,_=l,y=u,x=l+(f>>1),f>40&&(g=f>>3,S=l,C=l+g,w=l+(g<<1),a=e[S],o=e[C],s=e[w],l=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w,S=x-g,C=x,w=x+g,a=e[S],o=e[C],s=e[w],x=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w,S=u-(g<<1),C=u-g,w=u,a=e[S],o=e[C],s=e[w],u=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w),S=l,C=x,w=u,a=e[S],o=e[C],s=e[w],x=r(a,o)?r(o,s)?C:r(a,s)?w:S:r(s,o)?C:r(a,s)?S:w,x!=_&&(i=e[x],e[x]=e[_],e[_]=i,x=_),l=v=_+1,u=b=y,a=e[x];;){for(;l<=u&&!r(a,e[l]);)r(e[l],a)||(l>v&&(i=e[v],e[v]=e[l],e[l]=i),T=1,v++),l++;for(;l<=u&&!r(e[u],a);)r(a,e[u])||(uu)break;i=e[l],e[l]=e[u],e[u]=i,T=1,l++,u--}if(T==0){for(l=_,u=y,m=l+1;m<=u;m++)for(h=m;h>l&&r(e[h],e[h-1]);h--)i=e[h],e[h]=e[h-1],e[h-1]=i;break}for(f=Math.min(v-_,l-v),p=l-f|0,d=0;d1)p>1?f>p?(++c,E[c<<1]=_,E[(c<<1)+1]=_+f-1,l=y-p+1,u=y):(++c,E[c<<1]=y-p+1,E[(c<<1)+1]=y,l=_,u=_+f-1):(l=_,u=_+f-1);else if(p>1)l=y-p+1,u=y;else break}}median(e,t,n){let r,i=0,a=0,o=0,s=t+n>>1;for(;;){if(n<=t)return e[s];if(n==t+1)return e[t]>e[n]&&(r=e[t],e[t]=e[n],e[n]=r),e[s];for(i=t+n>>1,e[i]>e[n]&&(r=e[i],e[i]=e[n],e[n]=r),e[t]>e[n]&&(r=e[t],e[t]=e[n],e[n]=r),e[i]>e[t]&&(r=e[i],e[i]=e[t],e[t]=r),a=t+1,r=e[i],e[i]=e[a],e[a]=r,o=n;;){do++a;while(e[t]>e[a]);do--o;while(e[o]>e[t]);if(o=s&&(n=o-1)}return 0}},h=class extends c{constructor(){super()}grayscale(e,t,n,r,a){a===void 0&&(a=i.COLOR_RGBA2GRAY);let o=0,s=0,c=0,l=0,u=0,d=0,f=4899,p=9617,m=1868,h=4;(a==i.COLOR_BGRA2GRAY||a==i.COLOR_BGR2GRAY)&&(f=1868,m=4899),(a==i.COLOR_RGB2GRAY||a==i.COLOR_BGR2GRAY)&&(h=3);let g=h<<1,_=h*3|0;r.resize(t,n,1);let v=r.data;for(s=0;s>14,v[d+1]=e[u+h]*f+e[u+h+1]*p+e[u+h+2]*m+8192>>14,v[d+2]=e[u+g]*f+e[u+g+1]*p+e[u+g+2]*m+8192>>14,v[d+3]=e[u+_]*f+e[u+_+1]*p+e[u+_+2]*m+8192>>14;for(;o>14}}resample(e,t,n,r){let a=e.rows,o=e.cols;a>r&&o>n&&(t.resize(n,r,e.channel),e.type&i.U8_t&&t.type&i.U8_t&&a*o/(r*n)<256?u(e,t,this.cache,n,r):d(e,t,this.cache,n,r))}box_blur_gray(e,t,n,r){r===void 0&&(r=0),n|=0;let a=e.cols|0,o=e.rows|0,s=n+1|0,c=(n<<1)+1|0,l=c*c,u=(r&i.BOX_BLUR_NOSCALE)!==0,d=this.cache.get_buffer(a*o<<2),f=d.i32;t.resize(a,o,e.channel);let p=0,m=0,h=0,g=0,_=0,v=0,y=0,b=e.data;for(m=0;m0?v:0)]}let x=t.data;for(m=0;m0?v:0)]}this.cache.put_buffer(d)}gaussian_blur(e,t,n,r){let a=new m;r===void 0&&(r=0),n===void 0&&(n=0),n=n==0?Math.max(1,4*r+1-1e-8)*2+1|0:n;let o=n>>1,s=e.cols,c=e.rows,l=e.type,u=l&i.U8_t;t.resize(s,c,e.channel);let d=e.data,h=t.data,g,_,v=n+Math.max(c,s)|0,y=this.cache.get_buffer(v<<2),b=this.cache.get_buffer(n<<2);u?(g=y.i32,_=b.i32):l&i.S32_t?(g=y.i32,_=b.f32):(g=y.f32,_=b.f32),a.get_gaussian_kernel(n,r,_,l),u?f(g,d,h,s,c,_,n,o):p(g,d,h,s,c,_,n,o),this.cache.put_buffer(y),this.cache.put_buffer(b)}hough_transform(e,t,n,r){let i,a,o=e.data,s=e.cols,c=e.rows,l=s,u=Math.round((Math.PI-0)/n),d=Math.round(((s+c)*2+1)/t),f=1/t,p=new Int32Array((u+2)*(d+2)),m=new Float32Array(u),h=new Float32Array(u),g=0,_=0;for(;gr&&p[e]>p[e-1]&&p[e]>=p[e+1]&&p[e]>p[e-d-2]&&p[e]>=p[e+d+2]&&v.push(e)}v.sort(function(e,t){return p[e]>p[t]||p[e]==p[t]&&e>1,s=a>>1,c=o-(n<<1),l=s-(r<<1),u=0,d=0,f=n+r*i,p=0,m=0,h=0;t.resize(o,s,e.channel);let g=e.data,_=t.data;for(d=0;d>2,_[h+1]=g[p+2]+g[p+3]+g[p+i+2]+g[p+i+3]+2>>2;for(;u>2;f+=i<<1,m+=o}}scharr_derivatives(e,t){let n=e.cols,r=e.rows,a=n<<1,o=0,s=0,c=0,l,u,d,f,p,m,h=0,g=0,_=0,v=0,y,b;t.resize(n,r,2);let x=e.data,S=t.data,C=this.cache.get_buffer(n+2<<2),w=this.cache.get_buffer(n+2<<2);for(e.type&i.U8_t||e.type&i.S32_t?(y=C.i32,b=w.i32):(y=C.f32,b=w.f32);s0?s-1:1)*n|0,_=(s0?s-1:1)*n|0,_=(s0;--p)for(u=p+a*s,d=u-s,f=a;f>0;--f,u-=s,d-=s)r[u]+=r[d]+r[d+1]}}equalize_histogram(e,t){let n=e.cols,r=e.rows,i=e.data;t.resize(n,r,e.channel);let a=t.data,o=n*r,s=0,c=0,l,u,d=this.cache.get_buffer(1024);for(l=d.i32;s<256;++s)l[s]=0;for(s=0;sr&&(c=n,n=r,r=c),c=3*(a+2)|0;--c>=0;)T[c]=0;for(c=(o+2)*(a+2)|0;--c>=0;)E[c]=0;for(;u>31)-(g>>31)+((_^_>>31)-(_>>31));for(c=1;c<=o;++c,d+=f){if(c==o)for(u=M+a;--u>=M;)T[u]=0;else for(u=0;u>31)-(g>>31)+((_^_>>31)-(_>>31));for(p=d-f|0,E[P-1]=0,m=0,u=0;un){if(g=O[p],_=O[p+1],v=g^_,g=(g^g>>31)-(g>>31)|0,_=(_^_>>31)-(_>>31)|0,y=g*13573,b=y+(g+g<<15),_<<=15,_T[j+u-1]&&h>=T[j+u+1]){h>r&&!m&&E[P+u-N]!=2?(E[P+u]=2,m=1,D[F++]=P+u):E[P+u]=1;continue}}else if(_>b){if(h>T[A+u]&&h>=T[M+u]){h>r&&!m&&E[P+u-N]!=2?(E[P+u]=2,m=1,D[F++]=P+u):E[P+u]=1;continue}}else if(v=v<0?-1:1,h>T[A+u-v]&&h>T[M+u+v]){h>r&&!m&&E[P+u-N]!=2?(E[P+u]=2,m=1,D[F++]=P+u):E[P+u]=1;continue}}E[P+u]=0,m=0}E[P+a]=0,P+=N,u=A,A=j,j=M,M=u}for(u=P-N-1,c=0;c0;)P=D[--F],P-=N+1,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P),P+=N,E[P]==1&&(E[P]=2,D[F++]=P),P-=2,E[P]==1&&(E[P]=2,D[F++]=P),P+=N,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P),P+=1,E[P]==1&&(E[P]=2,D[F++]=P);for(P=N+1,A=0,c=0;c0&&g>0&&p=0&&g>=0&&p95&&r>40&&i>20&&n>r&&n>i&&n-Math.min(r,i)>15&&Math.abs(n-r)>15?t[o]=255:t[o]=0}};function g(e,t,n,r){r=e[t],e[t]=e[n],e[n]=r}function _(e,t){return e=Math.abs(e),t=Math.abs(t),e>t?(t/=e,e*Math.sqrt(1+t*t)):t>0?(e/=t,t*Math.sqrt(1+e*e)):0}var v=i.EPSILON,y=class{constructor(){}identity(e,t){t===void 0&&(t=1);let n=e.data,r=e.rows,i=e.cols,a=i+1|0,o=r*i,s=o;for(;--o>=0;)n[o]=0;for(o=s,s=0;s-v?0:1}multiply_3x3(e,t,n){let r=e.data,i=t.data,a=n.data,o=i[0],s=i[1],c=i[2],l=i[3],u=i[4],d=i[5],f=i[6],p=i[7],m=i[8],h=a[0],g=a[1],_=a[2],v=a[3],y=a[4],b=a[5],x=a[6],S=a[7],C=a[8];r[0]=o*h+s*v+c*x,r[1]=o*g+s*y+c*S,r[2]=o*_+s*b+c*C,r[3]=l*h+u*v+d*x,r[4]=l*g+u*y+d*S,r[5]=l*_+u*b+d*C,r[6]=f*h+p*v+m*x,r[7]=f*g+p*y+m*S,r[8]=f*_+p*b+m*C}mat3x3_determinant(e){let t=e.data;return t[0]*t[4]*t[8]-t[0]*t[5]*t[7]-t[3]*t[1]*t[8]+t[3]*t[2]*t[7]+t[6]*t[1]*t[5]-t[6]*t[2]*t[4]}determinant_3x3(e,t,n,r,i,a,o,s,c){return e*i*c-e*a*s-r*t*c+r*n*s+o*t*a-o*n*i}},b=class extends c{constructor(){super(),this.matmath=new y}JacobiImpl(e,t,n,r,a,o){let s=i.EPSILON,c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0,v=0,y=o*o*30,b=0,x=0,S=0,C=0,w=0,T=0,E=0,D=0,O=0,k=this.cache.get_buffer(o<<2),A=this.cache.get_buffer(o<<2),j=k.i32,M=A.i32;if(r)for(;c0){for(d=0,b=Math.abs(e[u]),c=1;c1)for(;v0){for(d=0,b=Math.abs(e[p]),c=1;c>16&256?L:-L,e[d*t+p]=I;for(m=0;m<2;m++)for(f=0;fMath.abs(c[a*s+n])&&(a=r);if(Math.abs(c[a*s+n])=0;n--){for(p=l[n],a=n+1;a=0;s--){for(f=d[s],c=s+1,a=c*l;c=0;)n.data[s]=_.data[s];else n&&this.matmath.transpose(n,_);if(r&&a&i.SVD_V_T)for(s=f*f;--s>=0;)r.data[s]=y.data[s];else r&&this.matmath.transpose(r,y)}else{if(n&&a&i.SVD_U_T)for(s=f*f;--s>=0;)n.data[s]=y.data[s];else n&&this.matmath.transpose(n,y);if(r&&a&i.SVD_V_T)for(s=d*d;--s>=0;)r.data[s]=_.data[s];else r&&this.matmath.transpose(r,_)}this.cache.put_buffer(m),this.cache.put_buffer(h),this.cache.put_buffer(g)}svd_solve(e,t,n){let r=0,a=0,o=0,s=0,c=0,u=e.rows,d=e.cols,f=0,p=0,m=0,h=e.type|i.C1_t,g=this.cache.get_buffer(u*u<<3),_=this.cache.get_buffer(d<<3),v=this.cache.get_buffer(d*d<<3),y=new l(u,u,h,g.data),b=new l(1,d,h,_.data),x=new l(d,d,h,v.data),S=n.data,C=y.data,w=b.data,T=x.data;for(this.svd_decompose(e,b,y,x,0),m=i.EPSILON*w[0]*d;rm){for(o=0,f=0,s=0;op&&(f+=w[s+a]*S[o]/C[a]);x[c]=f}this.cache.put_buffer(h),this.cache.put_buffer(g),this.cache.put_buffer(_)}eigenVV(e,t,n){let r=e.cols,a=r*r,o=e.type|i.C1_t,s=this.cache.get_buffer(r*r<<3),c=this.cache.get_buffer(r<<3),u=new l(r,r,o,s.data),d=new l(1,r,o,c.data);for(;--a>=0;)u.data[a]=e.data[a];if(this.JacobiImpl(u.data,r,d.data,t?t.data:null,r,r),n)for(;--r>=0;)n.data[r]=d.data[r];this.cache.put_buffer(s),this.cache.put_buffer(c)}};function x(e,t,n,r,i){let a=0,o=e[t],s=i,c=0,l=0,u=0;for(;a<25;++a)r[a]=o-e[t+n[a]];for(a=0;a<16;a+=2)c=Math.min(r[a+1],r[a+2]),c=Math.min(c,r[a+3]),!(c<=s)&&(c=Math.min(c,r[a+4]),c=Math.min(c,r[a+5]),c=Math.min(c,r[a+6]),c=Math.min(c,r[a+7]),c=Math.min(c,r[a+8]),s=Math.max(s,Math.min(c,r[a])),s=Math.max(s,Math.min(c,r[a+9])));for(l=-s,a=0;a<16;a+=2)u=Math.max(r[a+1],r[a+2]),u=Math.max(u,r[a+3]),u=Math.max(u,r[a+4]),u=Math.max(u,r[a+5]),!(u>=l)&&(u=Math.max(u,r[a+6]),u=Math.max(u,r[a+7]),u=Math.max(u,r[a+8]),l=Math.min(l,Math.max(u,r[a])),l=Math.min(l,Math.max(u,r[a+9])));return-l-1}var S=class extends c{constructor(){super(),this.offsets16=new Int32Array([0,3,1,3,2,2,3,1,3,0,3,-1,2,-2,1,-3,0,-3,-1,-3,-2,-2,-3,-1,-3,0,-3,1,-2,2,-1,3]),this.threshold_tab=new Uint8Array(512),this._threshold=20,this.pixel_off=new Int32Array(25),this.score_diff=new Int32Array(25)}set_threshold(e){this._threshold=Math.min(Math.max(e,0),255);for(let e=-255;e<=255;++e)this.threshold_tab[e+255]=e<-this._threshold?1:e>this._threshold?2:0;return this._threshold}detect(e,t,n){n===void 0&&(n=3);let r=e.data,i=e.cols,a=e.rows,o=0,s=0,c=0,l=0,u=0,d=0,f=this.cache.get_buffer(3*i),p=this.cache.get_buffer((i+1)*3<<2),m=f.u8,h=p.i32,g=this.pixel_off,_=this.score_diff,v=Math.max(3,n),y=Math.min(a-2,a-n),b=Math.max(3,n),S=Math.min(i-3,i-n),C=0,w=0,T,E=x,D=this.threshold_tab,O=this._threshold,k=0,A=0,j=0,M=0,N=0,P=0,F=0,I=0,L=0,R=0,z=0,B=0;this._cmp_offsets(g,i,16);let V=g[0],ee=g[1],H=g[2],U=g[3],W=g[4],G=g[5],K=g[6],te=g[7],q=g[8],J=g[9],Y=g[10],X=g[11],Z=g[12],ne=g[13],Q=g[14],re=g[15];for(o=0;o8){++M,h[N+M]=s,m[P+s]=E(r,F,g,_,O);break}}else C=0;if(j&2)for(l=k+O,C=0,c=0;c<25;++c)if(u=r[F+g[c]],u>l){if(++C,C>8){++M,h[N+M]=s,m[P+s]=E(r,F,g,_,O);break}}else C=0}}if(h[N+i]=M,o!=v)for(d=(o-4+3)%3,I=d*i|0,N=d*(i+1)|0,d=(o-5+3)%3,L=d*i|0,M=h[N+i],c=0;cm[I+R]&&B>m[I+z]&&B>m[L+z]&&B>m[L+s]&&B>m[L+R]&&B>m[P+z]&&B>m[P+s]&&B>m[P+R]&&(T=t[w],T.x=s,T.y=o-1,T.score=B,w++)}return this.cache.put_buffer(f),this.cache.put_buffer(p),w}_cmp_offsets(e,t,n){let r=0,i=this.offsets16;for(;r=0;)this.data[r]=new l(e>>r,t>>r,n)}build(e,t){t===void 0&&(t=!0);let n=2,r=e,i=this.data[0];if(!t){let t=e.cols*e.rows;for(;--t>=0;)i.data[t]=e.data[t]}for(i=this.data[1],this.pyrdown(r,i);n=0;i--,r++)a=Math.sqrt(n*n-i*i)+.5|0,t[r]=i+e*a;for(;-i=0;a--,r++)i=-Math.sqrt(n*n-a*a)-.5|0,t[r]=i+e*a;for(;a>i;a--,r++)i=-Math.sqrt(n*n-a*a)-.5|0,t[r]=i+e*a;for(i++;i<=0;i++,r++)a=-Math.sqrt(n*n-i*i)-.5|0,t[r]=i+e*a;for(;i<-a;i++,r++)a=-Math.sqrt(n*n-i*i)-.5|0,t[r]=i+e*a;for(a++;a<0;a++,r++)i=Math.sqrt(n*n-a*a)+.5|0,t[r]=i+e*a;return t[r]=t[0],t[r+1]=t[1],r}function j(e,t,n){let r=0;return e[t+1]!=0&&r++,e[t-1]!=0&&r++,e[t+n]!=0&&r++,e[t+n+1]!=0&&r++,e[t+n-1]!=0&&r++,e[t-n]!=0&&r++,e[t-n+1]!=0&&r++,e[t-n-1]!=0&&r++,r}function M(e,t,n,r,i){let a,o;if(n>0)for(t-=r*i,o=-i;o<=i;++o){for(a=-i;a<=i;++a)if(e[t+a]>n)return!1;t+=r}else for(t-=r*i,o=-i;o<=i;++o){for(a=-i;a<=i;++a)if(e[t+a]=r){if(f=e[t+a[u]],f<=i){if(f>=r){n[t]=0;return}if(u++,p=e[t+a[u]],p>i){if(u++,m=e[t+a[u]],m>i)h=3;else if(mi)h=7;else if(mi){if(u++,m=e[t+a[u]],m>i)h=3;else if(mi)h=7;else if(mi){n[t]=0;return}if(u++,p=e[t+a[u]],p>i){n[t]=0;return}if(u++,m=e[t+a[u]],m>i){n[t]=0;return}h=1}}else{if(f=e[t+a[u]],fi){if(p=m,u++,m=e[t+a[u]],mi){n[t]=0;return}if(m>i){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],m>i){n[t]=0;return}c-=d+p,h=8;break}if(p<=i){n[t]=0;return}if(m<=i){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],m>i){c-=d+p,h=3;break}if(mi){n[t]=0;return}c-=d+p,h=1;break}if(d>i){if(p=r){n[t]=0;return}if(m>=r){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],mi){c-=d+p,h=7;break}n[t]=0;return;case 2:if(d>i){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],di){n[t]=0;return}c-=d+p,h=4;break}if(m>i){c-=d+p,h=7;break}if(mi){if(mi){c-=d+p,h=3;break}if(mi){n[t]=0;return}if(di){n[t]=0;return}c-=d+p,h=1;break}if(m>=r){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],mi){c-=d+p,h=7;break}n[t]=0;return;case 5:if(di){if(p=m,u++,m=e[t+a[u]],mi){c-=d+p,h=3;break}if(mi){n[t]=0;return}if(di){c-=d+p,h=3;break}if(mi){n[t]=0;return}if(di){c-=d+p,h=7;break}n[t]=0;return;case 8:if(d>i){if(mi){n[t]=0;return}c-=d+p,h=1;break}n[t]=0;return;case 9:if(di){n[t]=0;return}if(p=m,u++,m=e[t+a[u]],m>i){n[t]=0;return}c-=d+p,h=8;break}if(d>i){if(p=m,u++,m=e[t+a[u]],m>i,t>>i,n)}detect(e,t,n=4){let r=this.level_tables[0],i=r.radius|0,a=i-1|0,o=r.dirs,s=r.dirs_count|0,c=s>>1,l=e.data,u=e.cols|0,d=e.rows|0,f=u>>1,p=r.scores,m=0,h=0,g=0,_=0,v=0,y=0,b=0,x=0,S=this.tau|0,C=0,w,T=Math.max(i+1,n)|0,E=Math.max(i+1,n)|0,D=Math.min(u-i-2,u-n)|0,O=Math.min(d-i-2,d-n)|0;for(g=E*u+T|0,h=E;h=3&&I(p,_,x,f,i)&&(w=t[C],w.x=m,w.y=h,w.score=b,++C,m+=a,_+=a);return C}};function z(e,t,n,r,i,a,o,s,c){let l=0,u=0,d=o*n+a|0,f=d;for(l=o;l=0&&f+i=0?t[f]=-4*e[f]+e[f+r]+e[f-r]+e[f+i]+e[f-i]:t[f]=0}function B(e,t,n,r,i,a,o){let s=-2*e[t]+e[t+r]+e[t-r],c=-2*e[t]+e[t+i]+e[t-i],l=e[t+a]+e[t-a]-e[t+o]-e[t-o],u=Math.sqrt((s-c)*(s-c)+4*l*l)|0;return Math.min(Math.abs(n-u),Math.abs(-(n+u)))}var V=z,ee=B,H=class extends c{constructor(){super(),this.laplacian_threshold=30,this.min_eigen_value_threshold=25}detect(e,t,n){n===void 0&&(n=5);let r=0,i=0,a=e.cols,o=e.rows,s=e.data,c=5*a|0,l=3+3*a|0,u=3-3*a|0,d=this.cache.get_buffer(a*o<<2),f=d.i32,p=0,m=0,h=0,g=0,_,v=0,y=this.laplacian_threshold,b=this.min_eigen_value_threshold,x=Math.max(5,n)|0,S=Math.max(3,n)|0,C=Math.min(a-5,a-n)|0,w=Math.min(o-3,o-n)|0;for(r=a*o;--r>=0;)f[r]=0;for(V(s,f,a,5,c,x,S,C,w),m=S*a+x|0,i=S;iy&&p>f[h-1]&&p>f[h+1]&&p>f[h-a]&&p>f[h+a]&&p>f[h-a-1]&&p>f[h+a-1]&&p>f[h-a+1]&&p>f[h+a+1])&&(g=ee(s,h,p,5,c,l,u),g>b&&(_=t[v],_.x=r,_.y=i,_.score=g,++v,++r,++h));return this.cache.put_buffer(d),v}},U=class{constructor(e=0,t=.5,n=.5,r=.99){this.size=e,this.thresh=t,this.eps=n,this.prob=r}update_iters(e,t){let n=Math.log(1-this.prob),r=Math.log(1-Math.pow(1-e,this.size));return(r>=0||-n>=t*-r?t:Math.round(n/r))|0}},W=class extends c{constructor(){super()}get_subset(e,t,n,r,i,a,o){let s=1e3,c=[],l=0,u=0,d=0,f=0,p=!1;for(;d=0;)s.data[a]=1;return this.cache.put_buffer(b),this.cache.put_buffer(x),this.cache.put_buffer(S),!0}for(;fMath.max(T,u-1)&&(C.copy_to(o),T=E,s&&w.copy_to(s),d=e.update_iters((a-E)/a,d),p=!0))}return this.cache.put_buffer(b),this.cache.put_buffer(x),this.cache.put_buffer(S),p}lmeds(e,t,n,r,a,o,s,c){if(c===void 0&&(c=1e3),a=0;)s.data[a]=1;return this.cache.put_buffer(S),this.cache.put_buffer(C),this.cache.put_buffer(w),!0}for(;f=u),this.cache.put_buffer(S),this.cache.put_buffer(C),this.cache.put_buffer(w),p}},G=class extends c{constructor(){super(),this.T0=new l(3,3,i.F32_t|i.C1_t),this.T1=new l(3,3,i.F32_t|i.C1_t),this.AtA=new l(6,6,i.F32_t|i.C1_t),this.AtB=new l(6,1,i.F32_t|i.C1_t)}sqr(e){return e*e}iso_normalize_points(e,t,n,r,i){let a=0,o=0,s=0,c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0;for(;a=0;)u[a]=0;for(a=0;a=0;--Z)for(I=1/(1<>Z,S=b>>Z,A=x<<1,_=h[Z].data,v=g[Z].data,re=x-o|0,ie=S-o|0,this.scharr_deriv(h[Z],E),ne=0;ne=re||G<=0||G>=ie,Y!=0){Z==0&&(c[ne]=0);continue}for(ae=L-W,oe=R-G,fe=(1-ae)*(1-oe)*le+.5|0,pe=ae*(1-oe)*le+.5|0,me=(1-ae)*oe*le+.5|0,he=le-fe-pe-me,ve=0,ye=0,be=0,X=0;X>9,_e=k[M]*fe+k[M+2]*pe+k[M+A]*me+k[M+A+2]*he,_e=_e+ue>>14,$=k[M+1]*fe+k[M+3]*pe+k[M+A+1]*me+k[M+A+3]*he,$=$+ue>>14,D[N]=ge,O[P++]=_e,O[P++]=$,ve+=_e*_e,ye+=_e*$,be+=$*$;if(ve*=de,ye*=de,be*=de,xe=ve*be-ye*ye,Se=(be+ve-Math.sqrt((ve-be)*(ve-be)+4*ye*ye))/m,Se=re||te<=0||te>=ie,Y!=0){Z==0&&(c[ne]=0);break}for(ae=z-K,oe=B-te,fe=(1-ae)*(1-oe)*le+.5|0,pe=ae*(1-oe)*le+.5|0,me=(1-ae)*oe*le+.5|0,he=le-fe-pe-me,se=0,ce=0,X=0;X>9,ge-=D[N],se+=ge*O[P++],ce+=ge*O[P++];if(se*=de,ce*=de,H=(ye*ce-be*se)*xe,U=(ye*se-ve*ce)*xe,z+=H,B+=U,r[q]=z+f,r[J]=B+f,H*H+U*U<=u)break;if(Q>0&&Math.abs(H+V)<.01&&Math.abs(U+ee)<.01){r[q]-=H*.5,r[J]-=U*.5;break}V=H,ee=U}}this.cache.put_buffer(C),this.cache.put_buffer(w),this.cache.put_buffer(T)}},J=class{constructor(e=0,t=0,n=0){this.queryIdx=e,this.trainIdx=t,this.distance=n}},Y=class t extends c{constructor(e=i.NORM_HAMMING,t=!1){super(),this.norm_type=e,this.cross_check=t}static popcnt32(e){return e-=e>>1&1431655765,e=(e&858993459)+(e>>2&858993459),(e+(e>>4)&252645135)*16843009>>24}static rowBytes(t){return t.cols*t.channel*e._get_data_type_size(t.type)}static words(e){if(!(e.type&i.U8_t))throw Error(`jsfeatNext.bfmatcher: descriptors must be U8`);let n=t.rowBytes(e);if(n&3)throw Error(`jsfeatNext.bfmatcher: descriptor width must be a multiple of 4 bytes, got ${n}`);return e.buffer.i32}static pairWords(e,n){let r=t.words(e),i=t.words(n),a=t.rowBytes(e),o=t.rowBytes(n);if(a!==o)throw Error(`jsfeatNext.bfmatcher: query and train descriptors must have the same row width, got ${a} and ${o} bytes`);return{qw:r,tw:i,word_len:a>>2}}static hamming(e,n,r,i,a){let o=0;for(let s=0;s=0&&i<=r&&l.push(new J(e,u,i))}return l}let u=this.cache.get_buffer(i<<2),d=u.i32;for(let e=0;ee.distance-t.distance);else if(ae.distance-t.distance)}}l.push(i)}return l}ratio_test(e,t=.75){let n=[];for(let r=0;r=2?i[0].distance=0?1:-1,m=[p*s[0]/u,p*s[1]/u,p*s[2]/u],h=[p*c[0]/d,p*c[1]/d,p*c[2]/d],g=[p*l[0]*f,p*l[1]*f,p*l[2]*f],_=e.normalize([m[0]+h[0],m[1]+h[1],m[2]+h[2]]),v=e.cross(m,h),y=e.normalize(e.cross(_,v)),b=Math.SQRT1_2,x=[(_[0]+y[0])*b,(_[1]+y[1])*b,(_[2]+y[2])*b],S=[(_[0]-y[0])*b,(_[1]-y[1])*b,(_[2]-y[2])*b],C=e.cross(x,S),w=r.R.data;return w[0]=x[0],w[1]=S[0],w[2]=C[0],w[3]=x[1],w[4]=S[1],w[5]=C[1],w[6]=x[2],w[7]=S[2],w[8]=C[2],r.t[0]=g[0],r.t[1]=g[1],r.t[2]=g[2],r.good=!0,r}static cross(e,t){return[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]]}static normalize(e){let t=Math.hypot(e[0],e[1],e[2])||1;return[e[0]/t,e[1]/t,e[2]/t]}},ne=c;return c.cache=s,c.pyramid_t=C,c.matrix_t=l,c.keypoint_t=T,c.ransac_params_t=U,c.match_t=J,c.pose_estimator=Z,c.pose_t=X,c.transform=new w,c.fast_corners=new S,c.imgproc=new h,c.math=new m,c.matmath=new y,c.linalg=new b,c.orb=new k,c.yape=new R,c.yape06=new H,c.motion_estimator=new W,c.affine2d=new K,c.homography2d=new te,c.optical_flow_lk=new q,c.bfmatcher=new Y,ne}); \ No newline at end of file diff --git a/dist/jsfeatNext.mjs b/dist/jsfeatNext.mjs index 62469dc..d5cd16e 100644 --- a/dist/jsfeatNext.mjs +++ b/dist/jsfeatNext.mjs @@ -1,5 +1,5 @@ /*! - * jsfeatNext v0.14.0 โ€” https://github.com/webarkit/jsfeatNext + * jsfeatNext v0.15.0 โ€” https://github.com/webarkit/jsfeatNext * * SPDX-License-Identifier: LGPL-3.0-or-later * Copyright 2026 WebARKit. Author(s): Walter Perdan @kalwalt @@ -90,6 +90,7 @@ var e = new class { BOX_BLUR_NOSCALE: 1, SVD_U_T: 1, SVD_V_T: 2, + NORM_HAMMING: 6, U8C1_t: 257, U8C3_t: 259, U8C4_t: 260, @@ -99,7 +100,7 @@ var e = new class { S32C2_t: 514 }, a = { name: "@webarkit/jsfeat-next", - version: "0.14.0", + version: "0.15.0", description: "Typescript version of jsfeat for WebARKit", main: "dist/jsfeatNext.js", module: "dist/jsfeatNext.mjs", @@ -172,7 +173,7 @@ var c = class { return this.dt._get_data_type_size(e); } }; -o = c, o.VERSION = a.version, o.EPSILON = i.EPSILON, o.FLT_MIN = i.FLT_MIN, o.U8_t = i.U8_t, o.S32_t = i.S32_t, o.F32_t = i.F32_t, o.S64_t = i.S64_t, o.F64_t = i.F64_t, o.C1_t = i.C1_t, o.C2_t = i.C2_t, o.C3_t = i.C3_t, o.C4_t = i.C4_t, o.COLOR_RGBA2GRAY = i.COLOR_RGBA2GRAY, o.COLOR_RGB2GRAY = i.COLOR_RGB2GRAY, o.COLOR_BGRA2GRAY = i.COLOR_BGRA2GRAY, o.COLOR_BGR2GRAY = i.COLOR_BGR2GRAY, o.BOX_BLUR_NOSCALE = i.BOX_BLUR_NOSCALE, o.SVD_U_T = i.SVD_U_T, o.SVD_V_T = i.SVD_V_T, o.U8C1_t = o.U8_t | o.C1_t, o.U8C3_t = o.U8_t | o.C3_t, o.U8C4_t = o.U8_t | o.C4_t, o.F32C1_t = o.F32_t | o.C1_t, o.F32C2_t = o.F32_t | o.C2_t, o.S32C1_t = o.S32_t | o.C1_t, o.S32C2_t = o.S32_t | o.C2_t; +o = c, o.VERSION = a.version, o.EPSILON = i.EPSILON, o.FLT_MIN = i.FLT_MIN, o.U8_t = i.U8_t, o.S32_t = i.S32_t, o.F32_t = i.F32_t, o.S64_t = i.S64_t, o.F64_t = i.F64_t, o.C1_t = i.C1_t, o.C2_t = i.C2_t, o.C3_t = i.C3_t, o.C4_t = i.C4_t, o.COLOR_RGBA2GRAY = i.COLOR_RGBA2GRAY, o.COLOR_RGB2GRAY = i.COLOR_RGB2GRAY, o.COLOR_BGRA2GRAY = i.COLOR_BGRA2GRAY, o.COLOR_BGR2GRAY = i.COLOR_BGR2GRAY, o.BOX_BLUR_NOSCALE = i.BOX_BLUR_NOSCALE, o.SVD_U_T = i.SVD_U_T, o.SVD_V_T = i.SVD_V_T, o.NORM_HAMMING = i.NORM_HAMMING, o.U8C1_t = o.U8_t | o.C1_t, o.U8C3_t = o.U8_t | o.C3_t, o.U8C4_t = o.U8_t | o.C4_t, o.F32C1_t = o.F32_t | o.C1_t, o.F32C2_t = o.F32_t | o.C2_t, o.S32C1_t = o.S32_t | o.C1_t, o.S32C2_t = o.S32_t | o.C2_t; //#endregion //#region src/matrix_t/matrix_t.ts var l = class { @@ -320,16 +321,16 @@ var m = class extends c { } perspective_4point_transform(e, t, n, r, i, a, o, s, c, l, u, d, f, p, m, h, g) { console.warn("โš ๏ธโš ๏ธโš ๏ธ This method is deprecated ad will be removed in the next releases, use transform.perspective_4point_transform() instead. โš ๏ธโš ๏ธโš ๏ธ"); - let _ = t, v = l, y = o, b = _ * v * y, x = m, S = _ * x, C = v * S, w = u, T = _ * w, E = a, D = n, O = p, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, K = x * D, te = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, q = (b - C - z * y + z * w + A - v * B + I * v - j) * R, ne = _, J = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, Y = (-ee + V * w - K * v + U - W + K * E + G - M * w) * R, X = D, Z = (-T + V + H - B + N - M - F + I) * R, Q = (-S + T + k - H + I - L - M + P) * R; - _ = r, v = d, y = c, b = _ * v * y, x = g, S = _ * x, C = v * S, w = f, T = _ * w, E = s, D = i, O = h, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, K = x * D; - let re = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, ie = (b - C - z * y + z * w + A - v * B + I * v - j) * R, ae = _, oe = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, se = (-ee + V * w - K * v + U - W + K * E + G - M * w) * R, ce = D, le = (-T + V + H - B + N - M - F + I) * R, ue = (-S + T + k - H + I - L - M + P) * R; - v = Y - Q * X, y = te * Y, b = te * X, S = J * q, C = ne * J, T = q * Z; - let de = ne * Z; + let _ = t, v = l, y = o, b = _ * v * y, x = m, S = _ * x, C = v * S, w = u, T = _ * w, E = a, D = n, O = p, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, te = x * D, ne = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, K = (b - C - z * y + z * w + A - v * B + I * v - j) * R, q = _, J = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, Y = (-ee + V * w - te * v + U - W + te * E + G - M * w) * R, X = D, Z = (-T + V + H - B + N - M - F + I) * R, Q = (-S + T + k - H + I - L - M + P) * R; + _ = r, v = d, y = c, b = _ * v * y, x = g, S = _ * x, C = v * S, w = f, T = _ * w, E = s, D = i, O = h, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, te = x * D; + let re = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, ie = (b - C - z * y + z * w + A - v * B + I * v - j) * R, ae = _, oe = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, se = (-ee + V * w - te * v + U - W + te * E + G - M * w) * R, ce = D, le = (-T + V + H - B + N - M - F + I) * R, ue = (-S + T + k - H + I - L - M + P) * R; + v = Y - Q * X, y = ne * Y, b = ne * X, S = J * K, C = q * J, T = K * Z; + let de = q * Z; O = 1 / (y - b * Q - S + C * Q + T * X - de * Y), A = -J + X * Z; let fe = -J * Q + Y * Z; - L = -q + ne * Q; - let pe = te - de; - B = te * Q - T, V = -q * X + ne * Y; + L = -K + q * Q; + let pe = ne - de; + B = ne * Q - T, V = -K * X + q * Y; let me = b - C, he = y - S; W = v * O; let ge = L * O, _e = V * O, $ = e.data; @@ -895,13 +896,13 @@ var S = class extends c { n === void 0 && (n = 3); let r = e.data, i = e.cols, a = e.rows, o = 0, s = 0, c = 0, l = 0, u = 0, d = 0, f = this.cache.get_buffer(3 * i), p = this.cache.get_buffer((i + 1) * 3 << 2), m = f.u8, h = p.i32, g = this.pixel_off, _ = this.score_diff, v = Math.max(3, n), y = Math.min(a - 2, a - n), b = Math.max(3, n), S = Math.min(i - 3, i - n), C = 0, w = 0, T, E = x, D = this.threshold_tab, O = this._threshold, k = 0, A = 0, j = 0, M = 0, N = 0, P = 0, F = 0, I = 0, L = 0, R = 0, z = 0, B = 0; this._cmp_offsets(g, i, 16); - let V = g[0], ee = g[1], H = g[2], U = g[3], W = g[4], G = g[5], K = g[6], te = g[7], q = g[8], ne = g[9], J = g[10], Y = g[11], X = g[12], Z = g[13], Q = g[14], re = g[15]; + let V = g[0], ee = g[1], H = g[2], U = g[3], W = g[4], G = g[5], te = g[6], ne = g[7], K = g[8], q = g[9], J = g[10], Y = g[11], X = g[12], Z = g[13], Q = g[14], re = g[15]; for (o = 0; o < i * 3; ++o) m[o] = 0; for (o = v; o < y; ++o) { for (F = o * i + b | 0, d = (o - 3) % 3, P = d * i | 0, N = d * (i + 1) | 0, s = 0; s < i; ++s) m[P + s] = 0; if (M = 0, o < y - 1) { - for (s = b; s < S; ++s, ++F) if (k = r[F], A = -k + 255, j = D[A + r[F + V]] | D[A + r[F + q]], j != 0 && (j &= D[A + r[F + H]] | D[A + r[F + J]], j &= D[A + r[F + W]] | D[A + r[F + X]], j &= D[A + r[F + K]] | D[A + r[F + Q]], j != 0)) { - if (j &= D[A + r[F + ee]] | D[A + r[F + ne]], j &= D[A + r[F + U]] | D[A + r[F + Y]], j &= D[A + r[F + G]] | D[A + r[F + Z]], j &= D[A + r[F + te]] | D[A + r[F + re]], j & 1) for (l = k - O, C = 0, c = 0; c < 25; ++c) if (u = r[F + g[c]], u < l) { + for (s = b; s < S; ++s, ++F) if (k = r[F], A = -k + 255, j = D[A + r[F + V]] | D[A + r[F + K]], j != 0 && (j &= D[A + r[F + H]] | D[A + r[F + J]], j &= D[A + r[F + W]] | D[A + r[F + X]], j &= D[A + r[F + te]] | D[A + r[F + Q]], j != 0)) { + if (j &= D[A + r[F + ee]] | D[A + r[F + q]], j &= D[A + r[F + U]] | D[A + r[F + Y]], j &= D[A + r[F + G]] | D[A + r[F + Z]], j &= D[A + r[F + ne]] | D[A + r[F + re]], j & 1) for (l = k - O, C = 0, c = 0; c < 25; ++c) if (u = r[F + g[c]], u < l) { if (++C, C > 8) { ++M, h[N + M] = s, m[P + s] = E(r, F, g, _, O); break; @@ -946,16 +947,16 @@ var S = class extends c { }, w = class { constructor() {} perspective_4point_transform(e, t, n, r, i, a, o, s, c, l, u, d, f, p, m, h, g) { - let _ = t, v = l, y = o, b = _ * v * y, x = m, S = _ * x, C = v * S, w = u, T = _ * w, E = a, D = n, O = p, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, K = x * D, te = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, q = (b - C - z * y + z * w + A - v * B + I * v - j) * R, ne = _, J = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, Y = (-ee + V * w - K * v + U - W + K * E + G - M * w) * R, X = D, Z = (-T + V + H - B + N - M - F + I) * R, Q = (-S + T + k - H + I - L - M + P) * R; - _ = r, v = d, y = c, b = _ * v * y, x = g, S = _ * x, C = v * S, w = f, T = _ * w, E = s, D = i, O = h, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, K = x * D; - let re = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, ie = (b - C - z * y + z * w + A - v * B + I * v - j) * R, ae = _, oe = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, se = (-ee + V * w - K * v + U - W + K * E + G - M * w) * R, ce = D, le = (-T + V + H - B + N - M - F + I) * R, ue = (-S + T + k - H + I - L - M + P) * R; - v = Y - Q * X, y = te * Y, b = te * X, S = J * q, C = ne * J, T = q * Z; - let de = ne * Z; + let _ = t, v = l, y = o, b = _ * v * y, x = m, S = _ * x, C = v * S, w = u, T = _ * w, E = a, D = n, O = p, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, te = x * D, ne = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, K = (b - C - z * y + z * w + A - v * B + I * v - j) * R, q = _, J = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, Y = (-ee + V * w - te * v + U - W + te * E + G - M * w) * R, X = D, Z = (-T + V + H - B + N - M - F + I) * R, Q = (-S + T + k - H + I - L - M + P) * R; + _ = r, v = d, y = c, b = _ * v * y, x = g, S = _ * x, C = v * S, w = f, T = _ * w, E = s, D = i, O = h, k = D * O, A = k * E, j = O * E * w, M = O * y, N = O * w, P = v * y, F = x * v, I = x * E, L = w * E, R = 1 / (M - N - P + F - I + L), z = _ * O, B = D * E, V = y * _, ee = x * V, H = D * v, U = k * w, W = D * w * E, G = y * x * v, te = x * D; + let re = -(C - b + T * E - E * S - k * v + A - j + M * v) * R, ie = (b - C - z * y + z * w + A - v * B + I * v - j) * R, ae = _, oe = (-w * S + ee + H * y - k * y + U - W + I * w - G) * R, se = (-ee + V * w - te * v + U - W + te * E + G - M * w) * R, ce = D, le = (-T + V + H - B + N - M - F + I) * R, ue = (-S + T + k - H + I - L - M + P) * R; + v = Y - Q * X, y = ne * Y, b = ne * X, S = J * K, C = q * J, T = K * Z; + let de = q * Z; O = 1 / (y - b * Q - S + C * Q + T * X - de * Y), A = -J + X * Z; let fe = -J * Q + Y * Z; - L = -q + ne * Q; - let pe = te - de; - B = te * Q - T, V = -q * X + ne * Y; + L = -K + q * Q; + let pe = ne - de; + B = ne * Q - T, V = -K * X + q * Y; let me = b - C, he = y - S; W = v * O; let ge = L * O, _e = V * O, $ = e.data; @@ -2007,10 +2008,37 @@ function D(e, t, n, r, i, a, o, s) { } //#endregion //#region src/orb/orb.ts -var O = class extends c { +var O = new Int32Array([ + 15, + 15, + 15, + 15, + 14, + 14, + 14, + 13, + 13, + 12, + 11, + 10, + 9, + 8, + 6, + 3, + 0 +]), k = class extends c { constructor() { super(), this.bit_pattern_31_ = new Int32Array(E), this.H = new l(3, 3, i.F32_t | i.C1_t), this.patch_img = new l(32, 32, i.U8_t | i.C1_t), this.imgproc = new h(); } + ic_angle(e, t, n) { + let r = 0, i = 0, a = e.data, o = e.cols, s = 0, c = 0, l = n * o + t | 0, u = 0, d = 0, f = 0, p = 0; + for (s = -15; s <= 15; ++s) i += s * a[l + s]; + for (c = 1; c <= 15; ++c) { + for (u = 0, d = O[c], s = -d; s <= d; ++s) f = a[l + s + c * o], p = a[l + s - c * o], u += f - p, i += s * (f + p); + r += c * u; + } + return Math.atan2(r, i); + } describe(e, t, n, r) { let a = 0, o = 0, s = 0, c = 0, l = 0, u = 0, d = 0, f = 0, p = this.patch_img.data, m = 0; r.type & i.U8_t ? r.resize(32, n, 1) : (r.type = i.U8_t, r.cols = 32, r.rows = n, r.channel = 1, r.allocate()); @@ -2023,7 +2051,7 @@ var O = class extends c { }; //#endregion //#region src/yape/yape_utils.ts -function k(e, t, n) { +function A(e, t, n) { let r = 0, i, a; for (i = n, a = 0; a < i; a++, r++) i = Math.sqrt(n * n - a * a) + .5 | 0, t[r] = i + e * a; for (i--; i < a && i >= 0; i--, r++) a = Math.sqrt(n * n - i * i) + .5 | 0, t[r] = i + e * a; @@ -2035,11 +2063,11 @@ function k(e, t, n) { for (a++; a < 0; a++, r++) i = Math.sqrt(n * n - a * a) + .5 | 0, t[r] = i + e * a; return t[r] = t[0], t[r + 1] = t[1], r; } -function A(e, t, n) { +function j(e, t, n) { let r = 0; return e[t + 1] != 0 && r++, e[t - 1] != 0 && r++, e[t + n] != 0 && r++, e[t + n + 1] != 0 && r++, e[t + n - 1] != 0 && r++, e[t - n] != 0 && r++, e[t - n + 1] != 0 && r++, e[t - n - 1] != 0 && r++, r; } -function j(e, t, n, r, i) { +function M(e, t, n, r, i) { let a, o; if (n > 0) for (t -= r * i, o = -i; o <= i; ++o) { for (a = -i; a <= i; ++a) if (e[t + a] > n) return !1; @@ -2051,7 +2079,7 @@ function j(e, t, n, r, i) { } return !0; } -function M(e, t, n, r, i, a, o, s) { +function N(e, t, n, r, i, a, o, s) { let c = 0, l = 0, u = o - 1 | 0, d = 0, f = 0, p = 0, m = 0, h = 0; if (d = e[t + a[l]], d <= i) { if (d >= r) { @@ -2395,38 +2423,38 @@ function M(e, t, n, r, i, a, o, s) { } n[t] = c + s * e[t]; } -var N = class { +var P = class { constructor(e, t, n) { - this.dirs = /* @__PURE__ */ new Int32Array(1024), this.dirs_count = k(e, this.dirs, n) | 0, this.scores = new Int32Array(e * t), this.radius = n | 0; + this.dirs = /* @__PURE__ */ new Int32Array(1024), this.dirs_count = A(e, this.dirs, n) | 0, this.scores = new Int32Array(e * t), this.radius = n | 0; } -}, P = A, F = j, I = M, L = class { +}, F = j, I = M, L = N, R = class { constructor() { this.level_tables = [], this.tau = 7; } init(e, t, n, r = 1) { n = Math.min(n, 7), n = Math.max(n, 3); - for (let i = 0; i < r; ++i) this.level_tables[i] = new N(e >> i, t >> i, n); + for (let i = 0; i < r; ++i) this.level_tables[i] = new P(e >> i, t >> i, n); } detect(e, t, n = 4) { let r = this.level_tables[0], i = r.radius | 0, a = i - 1 | 0, o = r.dirs, s = r.dirs_count | 0, c = s >> 1, l = e.data, u = e.cols | 0, d = e.rows | 0, f = u >> 1, p = r.scores, m = 0, h = 0, g = 0, _ = 0, v = 0, y = 0, b = 0, x = 0, S = this.tau | 0, C = 0, w, T = Math.max(i + 1, n) | 0, E = Math.max(i + 1, n) | 0, D = Math.min(u - i - 2, u - n) | 0, O = Math.min(d - i - 2, d - n) | 0; - for (g = E * u + T | 0, h = E; h < O; ++h, g += u) for (m = T, _ = g; m < D; ++m, ++_) v = l[_] + S, y = l[_] - S, y < l[_ + i] && l[_ + i] < v && y < l[_ - i] && l[_ - i] < v ? p[_] = 0 : I(l, _, p, y, v, o, c, s); - for (g = E * u + T | 0, h = E; h < O; ++h, g += u) for (m = T, _ = g; m < D; ++m, ++_) x = p[_], b = Math.abs(x), b < 5 ? (++m, ++_) : P(p, _, u) >= 3 && F(p, _, x, f, i) && (w = t[C], w.x = m, w.y = h, w.score = b, ++C, m += a, _ += a); + for (g = E * u + T | 0, h = E; h < O; ++h, g += u) for (m = T, _ = g; m < D; ++m, ++_) v = l[_] + S, y = l[_] - S, y < l[_ + i] && l[_ + i] < v && y < l[_ - i] && l[_ - i] < v ? p[_] = 0 : L(l, _, p, y, v, o, c, s); + for (g = E * u + T | 0, h = E; h < O; ++h, g += u) for (m = T, _ = g; m < D; ++m, ++_) x = p[_], b = Math.abs(x), b < 5 ? (++m, ++_) : F(p, _, u) >= 3 && I(p, _, x, f, i) && (w = t[C], w.x = m, w.y = h, w.score = b, ++C, m += a, _ += a); return C; } }; //#endregion //#region src/yape06/yape06_utils.ts -function R(e, t, n, r, i, a, o, s, c) { +function z(e, t, n, r, i, a, o, s, c) { let l = 0, u = 0, d = o * n + a | 0, f = d; for (l = o; l < c; ++l, d += n, f = d) for (u = a; u < s; ++u, ++f) f + r < e.length && f - r >= 0 && f + i < e.length && f - i >= 0 ? t[f] = -4 * e[f] + e[f + r] + e[f - r] + e[f + i] + e[f - i] : t[f] = 0; } -function z(e, t, n, r, i, a, o) { +function B(e, t, n, r, i, a, o) { let s = -2 * e[t] + e[t + r] + e[t - r], c = -2 * e[t] + e[t + i] + e[t - i], l = e[t + a] + e[t - a] - e[t + o] - e[t - o], u = Math.sqrt((s - c) * (s - c) + 4 * l * l) | 0; return Math.min(Math.abs(n - u), Math.abs(-(n + u))); } //#endregion //#region src/yape06/yape06.ts -var B = R, V = z, ee = class extends c { +var V = z, ee = B, H = class extends c { constructor() { super(), this.laplacian_threshold = 30, this.min_eigen_value_threshold = 25; } @@ -2434,10 +2462,10 @@ var B = R, V = z, ee = class extends c { n === void 0 && (n = 5); let r = 0, i = 0, a = e.cols, o = e.rows, s = e.data, c = 5 * a | 0, l = 3 + 3 * a | 0, u = 3 - 3 * a | 0, d = this.cache.get_buffer(a * o << 2), f = d.i32, p = 0, m = 0, h = 0, g = 0, _, v = 0, y = this.laplacian_threshold, b = this.min_eigen_value_threshold, x = Math.max(5, n) | 0, S = Math.max(3, n) | 0, C = Math.min(a - 5, a - n) | 0, w = Math.min(o - 3, o - n) | 0; for (r = a * o; --r >= 0;) f[r] = 0; - for (B(s, f, a, 5, c, x, S, C, w), m = S * a + x | 0, i = S; i < w; ++i, m += a) for (r = x, h = m; r < C; ++r, ++h) p = f[h], (p < -y && p < f[h - 1] && p < f[h + 1] && p < f[h - a] && p < f[h + a] && p < f[h - a - 1] && p < f[h + a - 1] && p < f[h - a + 1] && p < f[h + a + 1] || p > y && p > f[h - 1] && p > f[h + 1] && p > f[h - a] && p > f[h + a] && p > f[h - a - 1] && p > f[h + a - 1] && p > f[h - a + 1] && p > f[h + a + 1]) && (g = V(s, h, p, 5, c, l, u), g > b && (_ = t[v], _.x = r, _.y = i, _.score = g, ++v, ++r, ++h)); + for (V(s, f, a, 5, c, x, S, C, w), m = S * a + x | 0, i = S; i < w; ++i, m += a) for (r = x, h = m; r < C; ++r, ++h) p = f[h], (p < -y && p < f[h - 1] && p < f[h + 1] && p < f[h - a] && p < f[h + a] && p < f[h - a - 1] && p < f[h + a - 1] && p < f[h - a + 1] && p < f[h + a + 1] || p > y && p > f[h - 1] && p > f[h + 1] && p > f[h - a] && p > f[h + a] && p > f[h - a - 1] && p > f[h + a - 1] && p > f[h - a + 1] && p > f[h + a + 1]) && (g = ee(s, h, p, 5, c, l, u), g > b && (_ = t[v], _.x = r, _.y = i, _.score = g, ++v, ++r, ++h)); return this.cache.put_buffer(d), v; } -}, H = class { +}, U = class { constructor(e = 0, t = .5, n = .5, r = .99) { this.size = e, this.thresh = t, this.eps = n, this.prob = r; } @@ -2445,7 +2473,7 @@ var B = R, V = z, ee = class extends c { let n = Math.log(1 - this.prob), r = Math.log(1 - Math.pow(1 - e, this.size)); return (r >= 0 || -n >= t * -r ? t : Math.round(n / r)) | 0; } -}, U = class extends c { +}, W = class extends c { constructor() { super(); } @@ -2506,7 +2534,7 @@ var B = R, V = z, ee = class extends c { } return p && (j = 2.5 * 1.4826 * (1 + 5 / (a - u)) * Math.sqrt(A), j = Math.max(j, .001), D = this.find_inliers(t, o, n, r, a, j, k, E.data), s && E.copy_to(s), p = D >= u), this.cache.put_buffer(S), this.cache.put_buffer(C), this.cache.put_buffer(w), p; } -}, W = class extends c { +}, G = class extends c { constructor() { super(), this.T0 = new l(3, 3, i.F32_t | i.C1_t), this.T1 = new l(3, 3, i.F32_t | i.C1_t), this.AtA = new l(6, 6, i.F32_t | i.C1_t), this.AtB = new l(6, 1, i.F32_t | i.C1_t); } @@ -2524,7 +2552,7 @@ var B = R, V = z, ee = class extends c { for (; n < a; ++n) for (o = e[n].x - e[a].x, s = e[n].y - e[a].y, r = 0; r < n; ++r) if (c = e[r].x - e[a].x, l = e[r].y - e[a].y, Math.abs(c * s - l * o) <= i.EPSILON * (Math.abs(o) + Math.abs(s) + Math.abs(c) + Math.abs(l))) return !0; return !1; } -}, G = class extends W { +}, te = class extends G { constructor() { super(); } @@ -2542,7 +2570,7 @@ var B = R, V = z, ee = class extends c { check_subset(e, t, n) { return !0; } -}, K = class extends W { +}, ne = class extends G { constructor() { super(), this.mLtL = new l(9, 9, i.F32_t | i.C1_t), this.Evec = new l(9, 9, i.F32_t | i.C1_t); } @@ -2568,7 +2596,7 @@ var B = R, V = z, ee = class extends c { } return !0; } -}, te = class extends c { +}, K = class extends c { constructor() { super(); let e = new h(); @@ -2576,11 +2604,11 @@ var B = R, V = z, ee = class extends c { } track(e, t, n, r, a, o, s, c, u, d) { s === void 0 && (s = 30), c === void 0 && (c = new Uint8Array(a)), u === void 0 && (u = .01), d === void 0 && (d = 1e-4); - let f = (o - 1) * .5, p = o * o | 0, m = p << 1, h = e.data, g = t.data, _ = h[0].data, v = g[0].data, y = h[0].cols, b = h[0].rows, x = 0, S = 0, C = this.cache.get_buffer(p << 2), w = this.cache.get_buffer(m << 2), T = this.cache.get_buffer(b * (y << 1) << 2), E = new l(y, b, i.S32C2_t, T.data), D = C.i32, O = w.i32, k = T.i32, A = 0, j = 0, M = 0, N = 0, P = 0, F = 0, I = 0, L = 0, R = 0, z = 0, B = 0, V = 0, ee = 0, H = 0, U = 0, W = 0, G = 0, K = 0, te = 0, q = 0, ne = 0, J = 0, Y = 0, X = 0, Z = 0, Q = 0, re = 0, ie = 0, ae = 0, oe = 0, se = 0, ce = 0, le = 16384, ue = 8192, de = 1 / (1 << 20), fe = 0, pe = 0, me = 0, he = 0, ge = 0, _e = 0, $ = 0, ve = 0, ye = 0, be = 0, xe = 0, Se = 0; - for (u *= u; q < a; ++q) c[q] = 1; + let f = (o - 1) * .5, p = o * o | 0, m = p << 1, h = e.data, g = t.data, _ = h[0].data, v = g[0].data, y = h[0].cols, b = h[0].rows, x = 0, S = 0, C = this.cache.get_buffer(p << 2), w = this.cache.get_buffer(m << 2), T = this.cache.get_buffer(b * (y << 1) << 2), E = new l(y, b, i.S32C2_t, T.data), D = C.i32, O = w.i32, k = T.i32, A = 0, j = 0, M = 0, N = 0, P = 0, F = 0, I = 0, L = 0, R = 0, z = 0, B = 0, V = 0, ee = 0, H = 0, U = 0, W = 0, G = 0, te = 0, ne = 0, K = 0, q = 0, J = 0, Y = 0, X = 0, Z = 0, Q = 0, re = 0, ie = 0, ae = 0, oe = 0, se = 0, ce = 0, le = 16384, ue = 8192, de = 1 / (1 << 20), fe = 0, pe = 0, me = 0, he = 0, ge = 0, _e = 0, $ = 0, ve = 0, ye = 0, be = 0, xe = 0, Se = 0; + for (u *= u; K < a; ++K) c[K] = 1; let Ce = e.levels - 1 | 0; for (X = Ce; X >= 0; --X) for (I = 1 / (1 << X), x = y >> X, S = b >> X, A = x << 1, _ = h[X].data, v = g[X].data, re = x - o | 0, ie = S - o | 0, this.scharr_deriv(h[X], E), Z = 0; Z < a; ++Z) { - if (q = Z << 1, ne = q + 1, L = n[q] * I, R = n[ne] * I, X == Ce ? (z = L, B = R) : (z = r[q] * 2, B = r[ne] * 2), r[q] = z, r[ne] = B, L -= f, R -= f, W = L | 0, G = R | 0, J = W <= 0 || W >= re || G <= 0 || G >= ie, J != 0) { + if (K = Z << 1, q = K + 1, L = n[K] * I, R = n[q] * I, X == Ce ? (z = L, B = R) : (z = r[K] * 2, B = r[q] * 2), r[K] = z, r[q] = B, L -= f, R -= f, W = L | 0, G = R | 0, J = W <= 0 || W >= re || G <= 0 || G >= ie, J != 0) { X == 0 && (c[Z] = 0); continue; } @@ -2590,14 +2618,14 @@ var B = R, V = z, ee = class extends c { continue; } for (xe = 1 / xe, z -= f, B -= f, V = 0, ee = 0, Q = 0; Q < s; ++Q) { - if (K = z | 0, te = B | 0, J = K <= 0 || K >= re || te <= 0 || te >= ie, J != 0) { + if (te = z | 0, ne = B | 0, J = te <= 0 || te >= re || ne <= 0 || ne >= ie, J != 0) { X == 0 && (c[Z] = 0); break; } - for (ae = z - K, oe = B - te, fe = (1 - ae) * (1 - oe) * le + .5 | 0, pe = ae * (1 - oe) * le + .5 | 0, me = (1 - ae) * oe * le + .5 | 0, he = le - fe - pe - me, se = 0, ce = 0, Y = 0; Y < o; ++Y) for (F = (Y + te) * x + K | 0, N = Y * o | 0, P = N << 1, J = 0; J < o; ++J, ++F, ++N) ge = v[F] * fe + v[F + 1] * pe + v[F + x] * me + v[F + x + 1] * he, ge = ge + 256 >> 9, ge -= D[N], se += ge * O[P++], ce += ge * O[P++]; - if (se *= de, ce *= de, H = (ye * ce - be * se) * xe, U = (ye * se - ve * ce) * xe, z += H, B += U, r[q] = z + f, r[ne] = B + f, H * H + U * U <= u) break; + for (ae = z - te, oe = B - ne, fe = (1 - ae) * (1 - oe) * le + .5 | 0, pe = ae * (1 - oe) * le + .5 | 0, me = (1 - ae) * oe * le + .5 | 0, he = le - fe - pe - me, se = 0, ce = 0, Y = 0; Y < o; ++Y) for (F = (Y + ne) * x + te | 0, N = Y * o | 0, P = N << 1, J = 0; J < o; ++J, ++F, ++N) ge = v[F] * fe + v[F + 1] * pe + v[F + x] * me + v[F + x + 1] * he, ge = ge + 256 >> 9, ge -= D[N], se += ge * O[P++], ce += ge * O[P++]; + if (se *= de, ce *= de, H = (ye * ce - be * se) * xe, U = (ye * se - ve * ce) * xe, z += H, B += U, r[K] = z + f, r[q] = B + f, H * H + U * U <= u) break; if (Q > 0 && Math.abs(H + V) < .01 && Math.abs(U + ee) < .01) { - r[q] -= H * .5, r[ne] -= U * .5; + r[K] -= H * .5, r[q] -= U * .5; break; } V = H, ee = U; @@ -2605,10 +2633,190 @@ var B = R, V = z, ee = class extends c { } this.cache.put_buffer(C), this.cache.put_buffer(w), this.cache.put_buffer(T); } -}, q = c; -c.cache = s, c.pyramid_t = C, c.matrix_t = l, c.keypoint_t = T, c.ransac_params_t = H, c.transform = new w(), c.fast_corners = new S(), c.imgproc = new h(), c.math = new m(), c.matmath = new y(), c.linalg = new b(), c.orb = new O(), c.yape = new L(), c.yape06 = new ee(), c.motion_estimator = new U(), c.affine2d = new G(), c.homography2d = new K(), c.optical_flow_lk = new te(); +}, q = class { + constructor(e = 0, t = 0, n = 0) { + this.queryIdx = e, this.trainIdx = t, this.distance = n; + } +}, J = class t extends c { + constructor(e = i.NORM_HAMMING, t = !1) { + super(), this.norm_type = e, this.cross_check = t; + } + static popcnt32(e) { + return e -= e >> 1 & 1431655765, e = (e & 858993459) + (e >> 2 & 858993459), (e + (e >> 4) & 252645135) * 16843009 >> 24; + } + static rowBytes(t) { + return t.cols * t.channel * e._get_data_type_size(t.type); + } + static words(e) { + if (!(e.type & i.U8_t)) throw Error("jsfeatNext.bfmatcher: descriptors must be U8"); + let n = t.rowBytes(e); + if (n & 3) throw Error(`jsfeatNext.bfmatcher: descriptor width must be a multiple of 4 bytes, got ${n}`); + return e.buffer.i32; + } + static pairWords(e, n) { + let r = t.words(e), i = t.words(n), a = t.rowBytes(e), o = t.rowBytes(n); + if (a !== o) throw Error(`jsfeatNext.bfmatcher: query and train descriptors must have the same row width, got ${a} and ${o} bytes`); + return { + qw: r, + tw: i, + word_len: a >> 2 + }; + } + static hamming(e, n, r, i, a) { + let o = 0; + for (let s = 0; s < a; ++s) o += t.popcnt32(e[n + s] ^ r[i + s]); + return o; + } + match(e, n, r = 256) { + let i = e.rows, a = n.rows, { qw: o, tw: s, word_len: c } = t.pairWords(e, n), l = []; + if (!this.cross_check) { + for (let e = 0; e < i; ++e) { + let n = e * c, i = 2147483647, u = -1; + for (let e = 0; e < a; ++e) { + let r = t.hamming(o, n, s, e * c, c); + r < i && (i = r, u = e); + } + u >= 0 && i <= r && l.push(new q(e, u, i)); + } + return l; + } + let u = this.cache.get_buffer(i << 2), d = u.i32; + for (let e = 0; e < i; ++e) { + let n = e * c, r = 2147483647, i = -1; + for (let e = 0; e < a; ++e) { + let a = t.hamming(o, n, s, e * c, c); + a < r && (r = a, i = e); + } + d[e] = i; + } + for (let e = 0; e < i; ++e) { + let n = d[e]; + if (n < 0) continue; + let a = n * c, u = 2147483647, f = -1; + for (let e = 0; e < i; ++e) { + let n = t.hamming(o, e * c, s, a, c); + n < u && (u = n, f = e); + } + f === e && u <= r && l.push(new q(e, n, u)); + } + return this.cache.put_buffer(u), l; + } + knnMatch(e, n, r = 2) { + let i = e.rows, a = n.rows, { qw: o, tw: s, word_len: c } = t.pairWords(e, n), l = []; + for (let e = 0; e < i; ++e) { + let n = e * c, i = []; + for (let l = 0; l < a; ++l) { + let a = t.hamming(o, n, s, l * c, c); + if (i.length < r) i.push(new q(e, l, a)), i.sort((e, t) => e.distance - t.distance); + else if (a < i[i.length - 1].distance) { + let t = i[i.length - 1]; + t.queryIdx = e, t.trainIdx = l, t.distance = a, i.sort((e, t) => e.distance - t.distance); + } + } + l.push(i); + } + return l; + } + ratio_test(e, t = .75) { + let n = []; + for (let r = 0; r < e.length; ++r) { + let i = e[r]; + i.length >= 2 ? i[0].distance < t * i[1].distance && n.push(i[0]) : i.length === 1 && n.push(i[0]); + } + return n; + } +}, Y = class { + constructor() { + this.R = new l(3, 3, i.F64_t | i.C1_t), this.t = /* @__PURE__ */ new Float64Array(3), this.good = !1; + } +}, X = class e { + constructor(t) { + this.Kinv = e.invertIntrinsics(t), this.B = /* @__PURE__ */ new Float64Array(9); + } + setIntrinsics(t) { + this.Kinv = e.invertIntrinsics(t); + } + static intrinsics(e, t, n = 60) { + let r = new l(3, 3, i.F64_t | i.C1_t), a = .5 * e / Math.tan(.5 * n * Math.PI / 180), o = r.data; + return o[0] = a, o[1] = 0, o[2] = .5 * e, o[3] = 0, o[4] = a, o[5] = .5 * t, o[6] = 0, o[7] = 0, o[8] = 1, r; + } + static invertIntrinsics(e) { + let t = e.data, n = t[0], r = t[2], i = t[4], a = t[5]; + return new Float64Array([ + 1 / n, + 0, + -r / n, + 0, + 1 / i, + -a / i, + 0, + 0, + 1 + ]); + } + estimate(t, n) { + let r = n || new Y(), i = t.data, a = this.Kinv, o = this.B; + for (let e = 0; e < 3; ++e) for (let t = 0; t < 3; ++t) o[e * 3 + t] = a[e * 3] * i[t] + a[e * 3 + 1] * i[3 + t] + a[e * 3 + 2] * i[6 + t]; + let s = [ + o[0], + o[3], + o[6] + ], c = [ + o[1], + o[4], + o[7] + ], l = [ + o[2], + o[5], + o[8] + ], u = Math.hypot(s[0], s[1], s[2]), d = Math.hypot(c[0], c[1], c[2]); + if (u < 1e-12 || d < 1e-12) return r.good = !1, r; + let f = 2 / (u + d), p = l[2] >= 0 ? 1 : -1, m = [ + p * s[0] / u, + p * s[1] / u, + p * s[2] / u + ], h = [ + p * c[0] / d, + p * c[1] / d, + p * c[2] / d + ], g = [ + p * l[0] * f, + p * l[1] * f, + p * l[2] * f + ], _ = e.normalize([ + m[0] + h[0], + m[1] + h[1], + m[2] + h[2] + ]), v = e.cross(m, h), y = e.normalize(e.cross(_, v)), b = Math.SQRT1_2, x = [ + (_[0] + y[0]) * b, + (_[1] + y[1]) * b, + (_[2] + y[2]) * b + ], S = [ + (_[0] - y[0]) * b, + (_[1] - y[1]) * b, + (_[2] - y[2]) * b + ], C = e.cross(x, S), w = r.R.data; + return w[0] = x[0], w[1] = S[0], w[2] = C[0], w[3] = x[1], w[4] = S[1], w[5] = C[1], w[6] = x[2], w[7] = S[2], w[8] = C[2], r.t[0] = g[0], r.t[1] = g[1], r.t[2] = g[2], r.good = !0, r; + } + static cross(e, t) { + return [ + e[1] * t[2] - e[2] * t[1], + e[2] * t[0] - e[0] * t[2], + e[0] * t[1] - e[1] * t[0] + ]; + } + static normalize(e) { + let t = Math.hypot(e[0], e[1], e[2]) || 1; + return [ + e[0] / t, + e[1] / t, + e[2] / t + ]; + } +}, Z = c; +c.cache = s, c.pyramid_t = C, c.matrix_t = l, c.keypoint_t = T, c.ransac_params_t = U, c.match_t = q, c.pose_estimator = X, c.pose_t = Y, c.transform = new w(), c.fast_corners = new S(), c.imgproc = new h(), c.math = new m(), c.matmath = new y(), c.linalg = new b(), c.orb = new k(), c.yape = new R(), c.yape06 = new H(), c.motion_estimator = new W(), c.affine2d = new te(), c.homography2d = new ne(), c.optical_flow_lk = new K(), c.bfmatcher = new J(); //#endregion //#region src/index.ts -var ne = q; +var Q = Z; //#endregion -export { ne as default }; +export { Q as default }; diff --git a/package-lock.json b/package-lock.json index 219d556..e63e6e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@webarkit/jsfeat-next", - "version": "0.14.0", + "version": "0.15.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@webarkit/jsfeat-next", - "version": "0.14.0", + "version": "0.15.0", "license": "LGPL-3.0-or-later", "devDependencies": { "@vitest/coverage-v8": "^4.1.11", diff --git a/package.json b/package.json index eaa72e8..608355f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@webarkit/jsfeat-next", - "version": "0.14.0", + "version": "0.15.0", "description": "Typescript version of jsfeat for WebARKit", "main": "dist/jsfeatNext.js", "module": "dist/jsfeatNext.mjs", diff --git a/src/orb/orb.ts b/src/orb/orb.ts index 40e9838..4f45c4e 100644 --- a/src/orb/orb.ts +++ b/src/orb/orb.ts @@ -48,16 +48,6 @@ import { imgproc } from "../imgproc/imgproc"; import { bit_pattern_31 } from "./bit_pattern_31"; import { rectify_patch } from "./rectify_patch"; -/** - * ORB binary descriptor extractor (Oriented FAST and Rotated BRIEF): for - * each keypoint a rotation-rectified 32ร—32 patch is sampled and 256 - * pixel-pair comparisons from the learned {@link bit_pattern_31} pattern are - * packed into a 32-byte binary descriptor. Descriptors are matched with - * Hamming distance. - * - * Mirrors `jsfeat.orb` from the original library. - * (Moved out of the src/jsfeatNext.ts monolith in issue #47.) - */ /** * Per-row half-widths of the circular patch used by {@link orb.ic_angle}, * indexed by `|v|` for `v` in `[-15, 15]`: row `v` spans `u โˆˆ [-u_max[v], u_max[v]]`. @@ -68,6 +58,16 @@ import { rectify_patch } from "./rectify_patch"; */ const u_max = new Int32Array([15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 6, 3, 0]); +/** + * ORB binary descriptor extractor (Oriented FAST and Rotated BRIEF): for + * each keypoint a rotation-rectified 32ร—32 patch is sampled and 256 + * pixel-pair comparisons from the learned {@link bit_pattern_31} pattern are + * packed into a 32-byte binary descriptor. Descriptors are matched with + * Hamming distance. + * + * Mirrors `jsfeat.orb` from the original library. + * (Moved out of the src/jsfeatNext.ts monolith in issue #47.) + */ export class orb extends jsfeatNext { /** The learned 256-pair sampling pattern (flat `[x1,y1,x2,y2,โ€ฆ]`). */ public bit_pattern_31_: Int32Array; @@ -93,7 +93,7 @@ export class orb extends jsfeatNext { * * The angle points from the patch centre toward its intensity centroid, * computed from the first-order image moments `m01`/`m10` over a circular - * patch of radius 15 (see {@link u_max}), then `atan2(m01, m10)`. + * patch of radius 15 (see the module-level `u_max` table), then `atan2(m01, m10)`. * * @remarks * **This is a required step before {@link describe}, not an optional one.** diff --git a/types/src/bfmatcher/bfmatcher.d.ts b/types/src/bfmatcher/bfmatcher.d.ts new file mode 100644 index 0000000..040563a --- /dev/null +++ b/types/src/bfmatcher/bfmatcher.d.ts @@ -0,0 +1,98 @@ +import { default as jsfeatNext } from '../core/core'; +import { matrix_t } from '../matrix_t/matrix_t'; +import { match_t } from './match_t'; +/** + * Brute-force Hamming matcher for binary descriptors (ORB today; TEBLID/FREAK + * once ported). Ported from the inline `match_pattern()`/`popcnt32()` helpers + * in `examples/sample_orb_pinball.html` โ€” the only matcher jsfeatNext had + * before this module, duplicated across the ORB samples. + * + * The population-count routine is bit-identical to the sample's `popcnt32`, + * and descriptor rows are read the same way the sample does + * (`matrix_t.buffer.i32`, the full backing buffer reinterpreted as 32-bit + * words) โ€” so this can serve as PureCV's numeric reference oracle the same + * way the rest of jsfeatNext does (see issue #96). + * + * Descriptor width must be a multiple of 4 bytes: 32 (ORB) and 64 (TEBLID + * p512) both qualify. Unlike `svd_invert`'s non-square guard (#102), this is + * not a jsfeat divergence โ€” original jsfeat never shipped a matcher at all โ€” + * so there is no parity obligation, only an explicit failure instead of a + * silently wrong read past the buffer's actual word count. + */ +export declare class bfmatcher extends jsfeatNext { + /** Distance norm in use. Only `JSFEAT_CONSTANTS.NORM_HAMMING` (exposed as `jsfeatNext.NORM_HAMMING`) is implemented. */ + norm_type: number; + /** When true, {@link match} keeps only mutually-best (query, train) pairs. */ + cross_check: boolean; + constructor(norm_type?: number, cross_check?: boolean); + /** SWAR population count โ€” identical to the sample's `popcnt32`. */ + private static popcnt32; + /** + * Physical width of one descriptor row, in bytes. + * + * NOT `cols`. `matrix_t.allocate` sizes its buffer as + * `cols * sizeof(type) * channel * rows`, so a row's storage depends on all + * three. Two matrices can share a `cols` and still have different row + * widths โ€” a U8/C1 and a U8/C2 with `cols = 32` occupy 32 and 64 bytes โ€” + * which is why the stride check below compares this rather than `cols`. + */ + private static rowBytes; + /** + * Int32-word view over a descriptor matrix's full backing buffer, matching + * `matrix_t.buffer.i32` โ€” the same access the original sample uses. + * + * @throws {Error} if the descriptors are not `U8`, or if a row is not a + * whole number of 4-byte words. + */ + private static words; + /** + * Int32 views over a query/train PAIR, plus the row stride in words. + * + * Both matrices are addressed with a single stride, so a width mismatch is + * not a mild inconsistency: `train` rows would be read at `ti * word_len`, + * an offset computed from the QUERY width. The reads walk across train row + * boundaries and, past the end, an out-of-range `Int32Array` index yields + * `undefined`, which XOR coerces to 0. The result is a full set of + * confident, silently wrong Hamming distances rather than any error โ€” the + * matcher would report its best guess over garbage. + * + * Compares {@link rowBytes}, not `cols`, so a channel or element-type + * difference cannot slip past a matching column count. + * + * @throws {Error} if the row widths differ, or either matrix is rejected by + * {@link words}. + */ + private static pairWords; + private static hamming; + /** + * Nearest-neighbour match between two descriptor sets. + * + * With {@link cross_check} set, a pair is only kept when it is mutually + * best: `query[i]`'s nearest neighbour is `train[j]`, AND `train[j]`'s + * nearest neighbour (searched back over `query`) is `query[i]`. + * + * @param query Query descriptors (U8, one row per descriptor). + * @param train Train descriptors, same row width as `query`. + * @param max_distance Maximum Hamming distance to accept a pair. + */ + match(query: matrix_t, train: matrix_t, max_distance?: number): match_t[]; + /** + * k-nearest matches per query descriptor, each row sorted ascending by + * distance. + */ + knnMatch(query: matrix_t, train: matrix_t, k?: number): match_t[][]; + /** + * Lowe's ratio test over the output of `knnMatch(query, train, 2)`: keeps + * a query's best match only when it is meaningfully closer than the + * second-best (guards against ambiguous, repeated-texture matches). + * + * An instance method, not `static`, even though it reads no instance + * state: static methods are unreachable through a singleton instance + * (`jsfeatNext.bfmatcher.ratio_test(...)` โ€” this repo's calling + * convention since 0.9.0 โ€” would be `undefined` on a static declaration). + * Confirmed empirically before fixing: an earlier draft declared this + * `static`, following the #83 prototype literally, and the singleton + * simply had no such method at runtime. + */ + ratio_test(knn: match_t[][], ratio?: number): match_t[]; +} diff --git a/types/src/bfmatcher/match_t.d.ts b/types/src/bfmatcher/match_t.d.ts new file mode 100644 index 0000000..01fd41c --- /dev/null +++ b/types/src/bfmatcher/match_t.d.ts @@ -0,0 +1,19 @@ +/** Public shape of {@link match_t}. */ +export interface IMatch_T { + /** Index into the query descriptor set. */ + queryIdx: number; + /** Index into the train descriptor set. */ + trainIdx: number; + /** Hamming distance between the two descriptors. */ + distance: number; +} +/** + * One descriptor correspondence โ€” the equivalent of OpenCV's `cv::DMatch`. + * Produced by {@link bfmatcher.match} / {@link bfmatcher.knnMatch}. + */ +export declare class match_t implements IMatch_T { + queryIdx: number; + trainIdx: number; + distance: number; + constructor(queryIdx?: number, trainIdx?: number, distance?: number); +} diff --git a/types/src/constants/constants.d.ts b/types/src/constants/constants.d.ts index 73b9156..68b6487 100644 --- a/types/src/constants/constants.d.ts +++ b/types/src/constants/constants.d.ts @@ -48,6 +48,8 @@ export declare const JSFEAT_CONSTANTS: { SVD_U_T: number; /** `linalg.svd_decompose` option: return V transposed. */ SVD_V_T: number; + /** `bfmatcher`'s distance norm. Mirrors OpenCV's `cv::NORM_HAMMING` value; the only norm implemented. */ + NORM_HAMMING: number; /** 8-bit unsigned, 1 channel (`U8_t | C1_t`) โ€” grayscale images. */ U8C1_t: number; /** 8-bit unsigned, 3 channels (`U8_t | C3_t`) โ€” RGB images. */ diff --git a/types/src/core/core.d.ts b/types/src/core/core.d.ts index 23a254c..ac1611b 100644 --- a/types/src/core/core.d.ts +++ b/types/src/core/core.d.ts @@ -15,6 +15,9 @@ import { motion_estimator } from '../motion_estimator/motion_estimator'; import { optical_flow_lk } from '../optical_flow_lk/optical_flow_lk'; import { orb } from '../orb/orb'; import { affine2d, homography2d } from '../motion_model/motion_model'; +import { bfmatcher } from '../bfmatcher/bfmatcher'; +import { match_t } from '../bfmatcher/match_t'; +import { pose_estimator, pose_t } from '../pose_estimator/pose_estimator'; /** * The ONE shared scratch-buffer pool of the library (30 buffers of 2560 * bytes, growable), matching original jsfeat's design where every module @@ -60,6 +63,10 @@ export default class jsfeatNext { static motion_estimator: motion_estimator; static optical_flow_lk: optical_flow_lk; static orb: orb; + static bfmatcher: bfmatcher; + static match_t: typeof match_t; + static pose_estimator: typeof pose_estimator; + static pose_t: typeof pose_t; constructor(); /** Library version, read from package.json at build time. */ static VERSION: string; @@ -81,6 +88,7 @@ export default class jsfeatNext { static BOX_BLUR_NOSCALE: number; static SVD_U_T: number; static SVD_V_T: number; + static NORM_HAMMING: number; static U8C1_t: number; static U8C3_t: number; static U8C4_t: number; diff --git a/types/src/index.d.ts b/types/src/index.d.ts index ff59db6..39d9a92 100644 --- a/types/src/index.d.ts +++ b/types/src/index.d.ts @@ -31,5 +31,7 @@ export type { keypoint_t } from './keypoint_t/keypoint_t'; export type { pyramid_t } from './pyramid_t/pyramid_t'; export type { point_t, IPoint_t } from './point_t/point_t'; export type { ransac_params_t } from './motion_estimator/ransac_params_t'; +export type { match_t, IMatch_T } from './bfmatcher/match_t'; +export type { pose_t, IPose_T } from './pose_estimator/pose_estimator'; export type { ICache } from './cache/cache'; export type { TypedArray, NumericArray, MotionKernel } from './types'; diff --git a/types/src/orb/orb.d.ts b/types/src/orb/orb.d.ts index 975301c..3a535e3 100644 --- a/types/src/orb/orb.d.ts +++ b/types/src/orb/orb.d.ts @@ -22,6 +22,42 @@ export declare class orb extends jsfeatNext { /** Image-processing helper used for the affine patch warp. */ imgproc: imgproc; constructor(); + /** + * Dominant orientation of the patch around `(px, py)`, in radians โ€” the + * "intensity centroid" measure ORB uses to make its descriptors + * rotation-invariant. + * + * The angle points from the patch centre toward its intensity centroid, + * computed from the first-order image moments `m01`/`m10` over a circular + * patch of radius 15 (see the module-level `u_max` table), then `atan2(m01, m10)`. + * + * @remarks + * **This is a required step before {@link describe}, not an optional one.** + * `describe` reads each keypoint's `angle` and rotates the sampling patch by + * it; it does *not* compute the orientation itself. A `keypoint_t` left at + * the default `angle = -1` is therefore described with the patch rotated by + * โˆ’1 **radian** (โ‰ˆ โˆ’57ยฐ), not "unrotated" โ€” so detectors, which never set + * `angle`, must be followed by a pass through this method: + * + * ```ts + * const count = jsfeatNext.yape06.detect(img, corners, 17); + * for (let i = 0; i < count; ++i) { + * corners[i].angle = jsfeatNext.orb.ic_angle(img, corners[i].x, corners[i].y); + * } + * jsfeatNext.orb.describe(img, corners, count, descriptors); + * ``` + * + * **Keep `(px, py)` at least 15 px from every image edge.** The patch is + * read directly from `src` with no bounds check (matching the original + * implementation, and mirroring {@link describe}'s own margin requirement โ€” + * pass a detector `border` of โ‰ฅ 20 and both are satisfied at once). + * + * @param src Source grayscale image (single-channel `U8`). + * @param px Keypoint X (column) coordinate, in pixels. + * @param py Keypoint Y (row) coordinate, in pixels. + * @returns Orientation in radians, in `(-ฯ€, ฯ€]`. + */ + ic_angle(src: matrix_t, px: number, py: number): number; /** * Computes 256-bit (32-byte) binary descriptors for `count` keypoints. * Each keypoint's `angle` is used to rotation-rectify its patch, making diff --git a/types/src/pose_estimator/pose_estimator.d.ts b/types/src/pose_estimator/pose_estimator.d.ts new file mode 100644 index 0000000..f556210 --- /dev/null +++ b/types/src/pose_estimator/pose_estimator.d.ts @@ -0,0 +1,112 @@ +import { matrix_t } from '../matrix_t/matrix_t'; +/** A recovered camera pose. */ +export interface IPose_T { + /** 3ร—3 rotation, row-major, OpenCV camera frame (`F64_t | C1_t`). */ + R: matrix_t; + /** Translation, length 3, camera frame. */ + t: Float64Array; + /** `false` when the homography/intrinsics were degenerate. */ + good: boolean; +} +/** + * Output of {@link pose_estimator.estimate}: a rigid camera pose `(R, t)` in + * the OpenCV camera frame. A data-structure class (like `matrix_t`), not a + * singleton โ€” construct one and reuse it across frames to avoid per-frame + * allocation. + */ +export declare class pose_t implements IPose_T { + /** Rotation as a 3ร—3 `matrix_t`: the type the rest of jsfeatNext's matrix + * math and any downstream consumer expects. */ + R: matrix_t; + /** Translation as a bare `Float64Array(3)` rather than a 3ร—1 `matrix_t`: + * jsfeatNext has no 1-column matrix consumer for it, and a plain vector is + * what the renderer adapters up in #97 will read. */ + t: Float64Array; + good: boolean; + constructor(); +} +/** + * Closed-form planar pose from a homography plus camera intrinsics โ€” the + * `H โ†’ [R | t]` decomposition the ORB samples stop short of, completing the + * natural-feature AR pipeline (issue #83). + * + * ## Why this is a constructor class, not a namespace singleton + * + * The 14 algorithm modules (`imgproc`, `orb`, โ€ฆ) are stateless singletons on + * the namespace. This one is **stateful** โ€” it holds the inverted intrinsics + * `Kโปยน` โ€” and the public API constructs it with a `K` + * (`new jsfeatNext.pose_estimator(K)`). So it lives with the constructor + * data-structs (`matrix_t`, `keypoint_t`, `ransac_params_t`) instead. That + * also makes {@link intrinsics} reachable as + * `jsfeatNext.pose_estimator.intrinsics(...)`: it is `static`, and the class + * (not an instance) is what sits on the namespace. + * + * ## Why closed-form, not SVD + * + * The decomposition normalises the first two columns of `KโปยนH`, then + * re-orthonormalises them with a closed-form quaternion-free trick rather than + * an SVD of `[r1 r2]`. This keeps the algorithm free of `linalg`'s SVD, which + * matters for the PureCV Rust port: the same routine must run `no_std`. + * + * The math mirrors OpenCV / the ARToolKit-lineage planar-pose decomposition so + * it cross-validates 1:1 against the Rust port and can serve as its numeric + * reference oracle (issue #96). All geometry is `Float64` per the #96 precision + * hierarchy. + * + * @example + * ```ts + * const K = jsfeatNext.pose_estimator.intrinsics(640, 480); + * const estimator = new jsfeatNext.pose_estimator(K); + * const pose = new jsfeatNext.pose_t(); + * estimator.estimate(homography3x3, pose); + * if (pose.good) { ... } + * ``` + */ +export declare class pose_estimator { + /** Inverse intrinsics `Kโปยน`, row-major, assuming zero skew. */ + private Kinv; + /** + * Scratch for `B = KโปยนยทH` in {@link estimate}. + * + * An instance field rather than a per-call allocation: an estimator is + * built once and reused across frames, so at 30-60 fps a local would be a + * fresh array every frame for no benefit. It is not borrowed from the + * shared cache either โ€” that pool exists for image-sized buffers, and + * balancing a get/put across the degenerate early return to save 72 bytes + * would cost more in bookkeeping than it saves. + * + * Overwritten in full on every call, so no state carries between frames. + */ + private readonly B; + constructor(K: matrix_t); + /** Replace the intrinsics (e.g. after a resolution change). */ + setIntrinsics(K: matrix_t): void; + /** + * Rough pinhole `K` from image size and horizontal field of view, for the + * uncalibrated bootstrap case. Camera geometry, not rendering, so it stays + * in jsfeatNext (unlike the renderer glue, which moves up to #97's AR + * layer). + * + * `static`, so it is called on the namespace class directly: + * `jsfeatNext.pose_estimator.intrinsics(w, h)`. + * + * @param width Image width in pixels. + * @param height Image height in pixels. + * @param fovXdeg Horizontal field of view in degrees (default 60). + */ + static intrinsics(width: number, height: number, fovXdeg?: number): matrix_t; + /** Analytic inverse of an upper-triangular, zero-skew pinhole `K`. */ + private static invertIntrinsics; + /** + * Recover the camera pose from a homography mapping model-plane points + * (z = 0) to image pixels. + * + * @param H 3ร—3 homography (any single-channel numeric `matrix_t`). + * @param out Optional pose to write into; a fresh {@link pose_t} otherwise. + * @returns The pose. `out.good` is `false` โ€” and `R`/`t` untouched โ€” when + * `H`/`K` are degenerate (a near-zero mapped column). + */ + estimate(H: matrix_t, out?: pose_t): pose_t; + private static cross; + private static normalize; +}