@dxo/vision 0.0.0 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/dist/basic-block.d.ts +27 -0
- package/dist/basic-block.d.ts.map +1 -0
- package/dist/basic-block.js +88 -0
- package/dist/basic-block.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -0
- package/dist/heads.d.ts +36 -0
- package/dist/heads.d.ts.map +1 -0
- package/dist/heads.js +77 -0
- package/dist/heads.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/labels.d.ts +30 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +47 -0
- package/dist/labels.js.map +1 -0
- package/dist/neural.d.ts +19 -0
- package/dist/neural.d.ts.map +1 -0
- package/dist/neural.js +2 -0
- package/dist/neural.js.map +1 -0
- package/dist/resnet.d.ts +44 -0
- package/dist/resnet.d.ts.map +1 -0
- package/dist/resnet.js +190 -0
- package/dist/resnet.js.map +1 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -8
package/README.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
1
|
# @dxo/vision
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Developer preview — API unstable.** Not a closed `vision-classify` gate.
|
|
4
|
+
|
|
5
|
+
Composable vision surface: `ResNet` (backbone / features), `LinearHead` / `Classifier` / `compose` (logits), `defineLabelSpace` / `decodeClassification` (labels).
|
|
6
|
+
|
|
7
|
+
ResNet-18 uses **DXO-native** state keys (`stem.*`, `stage{n}.block{i}.*`). Preview `forward` supports `32×32` NCHW → `[N,512]` features.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @dxo/vision
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { ResNet, LinearHead, compose } from '@dxo/vision';
|
|
15
|
+
|
|
16
|
+
const backbone = new ResNet({ depth: 18 });
|
|
17
|
+
const model = compose(backbone, new LinearHead({ output: 10 }));
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Pretrained weight assets / torch→DXO conversion live in the separate `@dxo/resnet` package.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Tensor } from '@dxo/core';
|
|
2
|
+
import type { TensorStateSlice } from '@dxo/nn';
|
|
3
|
+
import { BatchNorm2d, Conv2d, Module, Relu } from '@dxo/nn';
|
|
4
|
+
/**
|
|
5
|
+
* DXO-native BasicBlock (not a torchvision key mirror).
|
|
6
|
+
* Keys: `{prefix}.conv1|bn1|conv2|bn2[.weight|.bias]` and optional `{prefix}.down.conv|bn`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class BasicBlock extends Module {
|
|
9
|
+
readonly conv1: Conv2d;
|
|
10
|
+
readonly bn1: BatchNorm2d;
|
|
11
|
+
readonly conv2: Conv2d;
|
|
12
|
+
readonly bn2: BatchNorm2d;
|
|
13
|
+
readonly relu: Relu;
|
|
14
|
+
readonly downConv: Conv2d | null;
|
|
15
|
+
readonly downBn: BatchNorm2d | null;
|
|
16
|
+
readonly prefix: string;
|
|
17
|
+
constructor(prefix: string, inChannels: number, outChannels: number, opts?: {
|
|
18
|
+
stride?: number;
|
|
19
|
+
requiresGrad?: boolean;
|
|
20
|
+
});
|
|
21
|
+
forward(x: Tensor): Tensor;
|
|
22
|
+
state(): Promise<Record<string, TensorStateSlice>>;
|
|
23
|
+
loadState(saved: Record<string, TensorStateSlice>, opts?: {
|
|
24
|
+
requiresGrad?: boolean;
|
|
25
|
+
}): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=basic-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic-block.d.ts","sourceRoot":"","sources":["../src/basic-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5D;;;GAGG;AACH,qBAAa,UAAW,SAAQ,MAAM;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAO;IAmB3H,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAUpB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IA2BxD,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;CAiBlG"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { BatchNorm2d, Conv2d, Module, Relu } from '@dxo/nn';
|
|
2
|
+
/**
|
|
3
|
+
* DXO-native BasicBlock (not a torchvision key mirror).
|
|
4
|
+
* Keys: `{prefix}.conv1|bn1|conv2|bn2[.weight|.bias]` and optional `{prefix}.down.conv|bn`.
|
|
5
|
+
*/
|
|
6
|
+
export class BasicBlock extends Module {
|
|
7
|
+
conv1;
|
|
8
|
+
bn1;
|
|
9
|
+
conv2;
|
|
10
|
+
bn2;
|
|
11
|
+
relu;
|
|
12
|
+
downConv;
|
|
13
|
+
downBn;
|
|
14
|
+
prefix;
|
|
15
|
+
constructor(prefix, inChannels, outChannels, opts = {}) {
|
|
16
|
+
super();
|
|
17
|
+
this.prefix = prefix;
|
|
18
|
+
const stride = opts.stride ?? 1;
|
|
19
|
+
const rg = opts.requiresGrad ?? true;
|
|
20
|
+
this.conv1 = new Conv2d(inChannels, outChannels, 3, { stride, padding: 1, requiresGrad: rg });
|
|
21
|
+
this.bn1 = new BatchNorm2d(outChannels, { requiresGrad: rg });
|
|
22
|
+
this.conv2 = new Conv2d(outChannels, outChannels, 3, { padding: 1, requiresGrad: rg });
|
|
23
|
+
this.bn2 = new BatchNorm2d(outChannels, { requiresGrad: rg });
|
|
24
|
+
this.relu = new Relu();
|
|
25
|
+
if (stride !== 1 || inChannels !== outChannels) {
|
|
26
|
+
this.downConv = new Conv2d(inChannels, outChannels, 1, { stride, requiresGrad: rg });
|
|
27
|
+
this.downBn = new BatchNorm2d(outChannels, { requiresGrad: rg });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.downConv = null;
|
|
31
|
+
this.downBn = null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
forward(x) {
|
|
35
|
+
let h = this.relu.forward(this.bn1.forward(this.conv1.forward(x)));
|
|
36
|
+
h = this.bn2.forward(this.conv2.forward(h));
|
|
37
|
+
let skip = x;
|
|
38
|
+
if (this.downConv && this.downBn) {
|
|
39
|
+
skip = this.downBn.forward(this.downConv.forward(x));
|
|
40
|
+
}
|
|
41
|
+
return this.relu.forward(h.add(skip));
|
|
42
|
+
}
|
|
43
|
+
async state() {
|
|
44
|
+
const p = this.prefix;
|
|
45
|
+
const c1 = await this.conv1.state();
|
|
46
|
+
const b1 = await this.bn1.state();
|
|
47
|
+
const c2 = await this.conv2.state();
|
|
48
|
+
const b2 = await this.bn2.state();
|
|
49
|
+
const out = {
|
|
50
|
+
[`${p}.conv1.weight`]: c1.weight,
|
|
51
|
+
[`${p}.conv1.bias`]: c1.bias,
|
|
52
|
+
[`${p}.bn1.weight`]: b1.weight,
|
|
53
|
+
[`${p}.bn1.bias`]: b1.bias,
|
|
54
|
+
[`${p}.conv2.weight`]: c2.weight,
|
|
55
|
+
[`${p}.conv2.bias`]: c2.bias,
|
|
56
|
+
[`${p}.bn2.weight`]: b2.weight,
|
|
57
|
+
[`${p}.bn2.bias`]: b2.bias,
|
|
58
|
+
};
|
|
59
|
+
if (this.downConv && this.downBn) {
|
|
60
|
+
const dc = await this.downConv.state();
|
|
61
|
+
const db = await this.downBn.state();
|
|
62
|
+
out[`${p}.down.conv.weight`] = dc.weight;
|
|
63
|
+
out[`${p}.down.conv.bias`] = dc.bias;
|
|
64
|
+
out[`${p}.down.bn.weight`] = db.weight;
|
|
65
|
+
out[`${p}.down.bn.bias`] = db.bias;
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
loadState(saved, opts = {}) {
|
|
70
|
+
const p = this.prefix;
|
|
71
|
+
const rg = opts.requiresGrad ?? true;
|
|
72
|
+
const need = (k) => {
|
|
73
|
+
const s = saved[k];
|
|
74
|
+
if (!s)
|
|
75
|
+
throw new Error(`BasicBlock.loadState: missing '${k}'`);
|
|
76
|
+
return s;
|
|
77
|
+
};
|
|
78
|
+
this.conv1.loadState({ weight: need(`${p}.conv1.weight`), bias: need(`${p}.conv1.bias`) }, { requiresGrad: rg });
|
|
79
|
+
this.bn1.loadState({ weight: need(`${p}.bn1.weight`), bias: need(`${p}.bn1.bias`) }, { requiresGrad: rg });
|
|
80
|
+
this.conv2.loadState({ weight: need(`${p}.conv2.weight`), bias: need(`${p}.conv2.bias`) }, { requiresGrad: rg });
|
|
81
|
+
this.bn2.loadState({ weight: need(`${p}.bn2.weight`), bias: need(`${p}.bn2.bias`) }, { requiresGrad: rg });
|
|
82
|
+
if (this.downConv && this.downBn) {
|
|
83
|
+
this.downConv.loadState({ weight: need(`${p}.down.conv.weight`), bias: need(`${p}.down.conv.bias`) }, { requiresGrad: rg });
|
|
84
|
+
this.downBn.loadState({ weight: need(`${p}.down.bn.weight`), bias: need(`${p}.down.bn.bias`) }, { requiresGrad: rg });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=basic-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic-block.js","sourceRoot":"","sources":["../src/basic-block.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Structured vision error with stable `code` for callers / verify. */
|
|
2
|
+
export declare class VisionError extends Error {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
constructor(code: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function unsupported(op: string, detail?: string): never;
|
|
7
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,qBAAa,WAAY,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAG9D"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Structured vision error with stable `code` for callers / verify. */
|
|
2
|
+
export class VisionError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'VisionError';
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function unsupported(op, detail) {
|
|
11
|
+
const suffix = detail ? `: ${detail}` : '';
|
|
12
|
+
throw new VisionError('UNSUPPORTED', `@dxo/vision ${op} is not implemented yet${suffix}`);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,OAAO,WAAY,SAAQ,KAAK;IACzB,IAAI,CAAS;IAEtB,YAAY,IAAY,EAAE,OAAe;QACrC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;CACJ;AAED,MAAM,UAAU,WAAW,CAAC,EAAU,EAAE,MAAe;IACnD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,MAAM,IAAI,WAAW,CAAC,aAAa,EAAE,eAAe,EAAE,0BAA0B,MAAM,EAAE,CAAC,CAAC;AAC9F,CAAC"}
|
package/dist/heads.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Tensor } from '@dxo/core';
|
|
2
|
+
import { Module } from '@dxo/nn';
|
|
3
|
+
import type { ResNet } from './resnet.js';
|
|
4
|
+
import type { TensorPort } from './types.js';
|
|
5
|
+
export type LinearHeadOptions = {
|
|
6
|
+
/** Feature dim; inferred from `input` port or by `compose` when omitted. */
|
|
7
|
+
input?: number | TensorPort;
|
|
8
|
+
/** Logits dim — class count for the head only, not ResNet. */
|
|
9
|
+
output: number;
|
|
10
|
+
bias?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/** Feature → logits only; no label names / language. */
|
|
13
|
+
export declare class LinearHead extends Module {
|
|
14
|
+
#private;
|
|
15
|
+
readonly outFeatures: number;
|
|
16
|
+
constructor(options: LinearHeadOptions);
|
|
17
|
+
get inFeatures(): number | undefined;
|
|
18
|
+
/** Wire feature size (used by `compose` when ctor omitted `input`). */
|
|
19
|
+
bindInput(inFeatures: number): void;
|
|
20
|
+
forward(features: Tensor): Tensor;
|
|
21
|
+
parameters(): Tensor[];
|
|
22
|
+
}
|
|
23
|
+
export type ClassifierOptions = {
|
|
24
|
+
backbone: ResNet;
|
|
25
|
+
head: LinearHead;
|
|
26
|
+
};
|
|
27
|
+
/** Backbone + head; `forward` returns logits Tensor. */
|
|
28
|
+
export declare class Classifier extends Module {
|
|
29
|
+
readonly backbone: ResNet;
|
|
30
|
+
readonly head: LinearHead;
|
|
31
|
+
constructor(options: ClassifierOptions);
|
|
32
|
+
forward(image: Tensor): Tensor;
|
|
33
|
+
}
|
|
34
|
+
/** Compose ResNet + LinearHead into a Classifier. */
|
|
35
|
+
export declare function compose(backbone: ResNet, head: LinearHead): Classifier;
|
|
36
|
+
//# sourceMappingURL=heads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heads.d.ts","sourceRoot":"","sources":["../src/heads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAU,MAAM,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,MAAM,iBAAiB,GAAG;IAC5B,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC5B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AASF,wDAAwD;AACxD,qBAAa,UAAW,SAAQ,MAAM;;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAIjB,OAAO,EAAE,iBAAiB;IAQtC,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAED,uEAAuE;IACvE,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IASnC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAWxB,UAAU,IAAI,MAAM,EAAE;CAGlC;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,wDAAwD;AACxD,qBAAa,UAAW,SAAQ,MAAM;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;gBAEd,OAAO,EAAE,iBAAiB;IAMtC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAIjC;AAED,qDAAqD;AACrD,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAWtE"}
|
package/dist/heads.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Linear, Module } from '@dxo/nn';
|
|
2
|
+
import { VisionError } from './errors.js';
|
|
3
|
+
function resolveInFeatures(input) {
|
|
4
|
+
if (typeof input === 'number')
|
|
5
|
+
return input;
|
|
6
|
+
const last = input.shape[input.shape.length - 1];
|
|
7
|
+
if (typeof last === 'number')
|
|
8
|
+
return last;
|
|
9
|
+
throw new VisionError('INVALID_HEAD_INPUT', 'LinearHead input port must end with a fixed feature dimension');
|
|
10
|
+
}
|
|
11
|
+
/** Feature → logits only; no label names / language. */
|
|
12
|
+
export class LinearHead extends Module {
|
|
13
|
+
outFeatures;
|
|
14
|
+
#inFeatures;
|
|
15
|
+
#linear;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
super();
|
|
18
|
+
this.outFeatures = options.output;
|
|
19
|
+
if (options.input !== undefined) {
|
|
20
|
+
this.bindInput(resolveInFeatures(options.input));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
get inFeatures() {
|
|
24
|
+
return this.#inFeatures;
|
|
25
|
+
}
|
|
26
|
+
/** Wire feature size (used by `compose` when ctor omitted `input`). */
|
|
27
|
+
bindInput(inFeatures) {
|
|
28
|
+
if (this.#inFeatures !== undefined && this.#inFeatures !== inFeatures) {
|
|
29
|
+
throw new VisionError('HEAD_FEATURE_MISMATCH', `LinearHead already bound to inFeatures=${this.#inFeatures}, got ${inFeatures}`);
|
|
30
|
+
}
|
|
31
|
+
if (this.#linear && this.#inFeatures === inFeatures)
|
|
32
|
+
return;
|
|
33
|
+
this.#inFeatures = inFeatures;
|
|
34
|
+
this.#linear = new Linear(inFeatures, this.outFeatures);
|
|
35
|
+
}
|
|
36
|
+
forward(features) {
|
|
37
|
+
if (!this.#linear) {
|
|
38
|
+
const last = features.shape[features.shape.length - 1];
|
|
39
|
+
if (typeof last !== 'number') {
|
|
40
|
+
throw new VisionError('INVALID_HEAD_INPUT', 'cannot infer LinearHead input from features');
|
|
41
|
+
}
|
|
42
|
+
this.bindInput(last);
|
|
43
|
+
}
|
|
44
|
+
return this.#linear.forward(features);
|
|
45
|
+
}
|
|
46
|
+
parameters() {
|
|
47
|
+
return this.#linear ? this.#linear.parameters() : [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Backbone + head; `forward` returns logits Tensor. */
|
|
51
|
+
export class Classifier extends Module {
|
|
52
|
+
backbone;
|
|
53
|
+
head;
|
|
54
|
+
constructor(options) {
|
|
55
|
+
super();
|
|
56
|
+
this.backbone = options.backbone;
|
|
57
|
+
this.head = options.head;
|
|
58
|
+
}
|
|
59
|
+
forward(image) {
|
|
60
|
+
const features = this.backbone.forward(image);
|
|
61
|
+
return this.head.forward(features);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Compose ResNet + LinearHead into a Classifier. */
|
|
65
|
+
export function compose(backbone, head) {
|
|
66
|
+
const expected = backbone.features();
|
|
67
|
+
const last = expected.shape[expected.shape.length - 1];
|
|
68
|
+
if (typeof last !== 'number') {
|
|
69
|
+
throw new VisionError('INVALID_BACKBONE', 'backbone features port must end with a fixed dim');
|
|
70
|
+
}
|
|
71
|
+
if (head.inFeatures !== undefined && head.inFeatures !== last) {
|
|
72
|
+
throw new VisionError('HEAD_FEATURE_MISMATCH', `LinearHead inFeatures=${head.inFeatures} does not match backbone features=${last}`);
|
|
73
|
+
}
|
|
74
|
+
head.bindInput(last);
|
|
75
|
+
return new Classifier({ backbone, head });
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=heads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heads.js","sourceRoot":"","sources":["../src/heads.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dxo/vision — developer preview (API unstable).
|
|
3
|
+
* Image types + ResNet backbone / heads / label decode.
|
|
4
|
+
* Not a closed vision-classify gate. Weights live in external `@dxo/resnet`.
|
|
5
|
+
*/
|
|
6
|
+
import type { ImageBuffer, Tensor } from '@dxo/core';
|
|
7
|
+
export type { TensorStateSlice } from '@dxo/nn';
|
|
8
|
+
export { VisionError } from './errors.js';
|
|
9
|
+
export { Classifier, type ClassifierOptions, compose, LinearHead, type LinearHeadOptions, } from './heads.js';
|
|
10
|
+
export { type ClassificationDecode, type ClassificationTopK, type DecodeClassificationOptions, decodeClassification, defineLabelSpace, type LabelSpace, type LabelSpaceOptions, } from './labels.js';
|
|
11
|
+
export type { Neural, NeuralSignature } from './neural.js';
|
|
12
|
+
export { defineResNet, ResNet } from './resnet.js';
|
|
13
|
+
export type { Device, ResNetDepth, ResNetOptions, ResNetSignature, TensorPort, WeightSource, } from './types.js';
|
|
14
|
+
export { resnetFeatureChannels } from './types.js';
|
|
15
|
+
export type ColorSpace = 'rgb' | 'rgba' | 'gray' | 'bgr';
|
|
16
|
+
export type ImageLayout = 'HWC' | 'CHW' | 'nchw' | 'nhwc';
|
|
17
|
+
export type ImageDtype = 'u8' | 'u16' | 'f32';
|
|
18
|
+
export type ImageTensorSpec = {
|
|
19
|
+
layout: 'nchw' | 'nhwc';
|
|
20
|
+
dtype: 'f32';
|
|
21
|
+
channels: 1 | 3 | 4;
|
|
22
|
+
};
|
|
23
|
+
export type ImageToTensorOptions = {
|
|
24
|
+
device?: 'cpu' | 'cuda' | 'metal';
|
|
25
|
+
copy?: boolean;
|
|
26
|
+
/** Target model layout; vision may transpose/cast before buffer view. */
|
|
27
|
+
layout?: 'nchw' | 'nhwc';
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* User-facing image with vision metadata. Does not own a parallel native engine.
|
|
31
|
+
* Pixel carrier is `@dxo/core` ImageBuffer (colorSpace/alphaMode on the buffer).
|
|
32
|
+
*/
|
|
33
|
+
export interface Image {
|
|
34
|
+
readonly width: number;
|
|
35
|
+
readonly height: number;
|
|
36
|
+
readonly channels: number;
|
|
37
|
+
readonly colorSpace: ColorSpace;
|
|
38
|
+
readonly layout: ImageLayout;
|
|
39
|
+
readonly dtype: ImageDtype;
|
|
40
|
+
readonly alpha: boolean;
|
|
41
|
+
readonly source?: {
|
|
42
|
+
kind: string;
|
|
43
|
+
uri?: string;
|
|
44
|
+
};
|
|
45
|
+
/** Underlying typed host buffer when available (no domain semantics). */
|
|
46
|
+
buffer(): ImageBuffer | undefined;
|
|
47
|
+
toTensor(options?: ImageToTensorOptions): Tensor;
|
|
48
|
+
dispose(): void;
|
|
49
|
+
ready(): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export interface ImageBatch {
|
|
52
|
+
readonly size: number;
|
|
53
|
+
readonly images: readonly Image[];
|
|
54
|
+
toTensor(options?: ImageToTensorOptions): Tensor;
|
|
55
|
+
dispose(): void;
|
|
56
|
+
}
|
|
57
|
+
/** @deprecated Prefer {@link ImageTensorSpec} + {@link Image}. */
|
|
58
|
+
export type LegacyImageTensorSpec = ImageTensorSpec;
|
|
59
|
+
export declare function visionVersion(): string;
|
|
60
|
+
export declare function unsupportedVisionApi(name: string): never;
|
|
61
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dxo/vision — developer preview (API unstable).
|
|
3
|
+
* Image types + ResNet backbone / heads / label decode.
|
|
4
|
+
* Not a closed vision-classify gate. Weights live in external `@dxo/resnet`.
|
|
5
|
+
*/
|
|
6
|
+
export { VisionError } from './errors.js';
|
|
7
|
+
export { Classifier, compose, LinearHead, } from './heads.js';
|
|
8
|
+
export { decodeClassification, defineLabelSpace, } from './labels.js';
|
|
9
|
+
export { defineResNet, ResNet } from './resnet.js';
|
|
10
|
+
export { resnetFeatureChannels } from './types.js';
|
|
11
|
+
export function visionVersion() {
|
|
12
|
+
return 'dxo-vision@developer-preview';
|
|
13
|
+
}
|
|
14
|
+
export function unsupportedVisionApi(name) {
|
|
15
|
+
throw new Error(`@dxo/vision ${name} is not wired yet on this developer preview surface`);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACH,UAAU,EAEV,OAAO,EACP,UAAU,GAEb,MAAM,YAAY,CAAC;AACpB,OAAO,EAIH,oBAAoB,EACpB,gBAAgB,GAGnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAkDnD,MAAM,UAAU,aAAa;IACzB,OAAO,8BAA8B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC7C,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,qDAAqD,CAAC,CAAC;AAC9F,CAAC"}
|
package/dist/labels.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Tensor } from '@dxo/core';
|
|
2
|
+
export type LabelSpace = {
|
|
3
|
+
id: string;
|
|
4
|
+
labels: readonly string[];
|
|
5
|
+
size: number;
|
|
6
|
+
};
|
|
7
|
+
export type LabelSpaceOptions = {
|
|
8
|
+
id: string;
|
|
9
|
+
labels: readonly string[];
|
|
10
|
+
};
|
|
11
|
+
export declare function defineLabelSpace(options: LabelSpaceOptions): LabelSpace;
|
|
12
|
+
export type ClassificationTopK = {
|
|
13
|
+
index: number;
|
|
14
|
+
score: number;
|
|
15
|
+
label: string;
|
|
16
|
+
};
|
|
17
|
+
export type ClassificationDecode = {
|
|
18
|
+
labelSpaceId: string;
|
|
19
|
+
topK: ClassificationTopK[];
|
|
20
|
+
};
|
|
21
|
+
export type DecodeClassificationOptions = {
|
|
22
|
+
labels: LabelSpace;
|
|
23
|
+
topK?: number;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Decode logits with an external label space.
|
|
27
|
+
* Same logits may be decoded with different LabelSpaces (e.g. EN vs ZH).
|
|
28
|
+
*/
|
|
29
|
+
export declare function decodeClassification(logits: Tensor, options: DecodeClassificationOptions): Promise<ClassificationDecode>;
|
|
30
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGxC,MAAM,MAAM,UAAU,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAYvE;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,kBAAkB,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACtC,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6B9H"}
|
package/dist/labels.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { VisionError } from './errors.js';
|
|
2
|
+
export function defineLabelSpace(options) {
|
|
3
|
+
if (!options.id) {
|
|
4
|
+
throw new VisionError('INVALID_LABEL_SPACE', 'defineLabelSpace requires a non-empty id');
|
|
5
|
+
}
|
|
6
|
+
if (!Array.isArray(options.labels) || options.labels.length === 0) {
|
|
7
|
+
throw new VisionError('INVALID_LABEL_SPACE', 'defineLabelSpace requires a non-empty labels array');
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
id: options.id,
|
|
11
|
+
labels: Object.freeze([...options.labels]),
|
|
12
|
+
size: options.labels.length,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decode logits with an external label space.
|
|
17
|
+
* Same logits may be decoded with different LabelSpaces (e.g. EN vs ZH).
|
|
18
|
+
*/
|
|
19
|
+
export async function decodeClassification(logits, options) {
|
|
20
|
+
const { labels } = options;
|
|
21
|
+
const k = Math.max(1, Math.min(options.topK ?? 5, labels.size));
|
|
22
|
+
const shape = logits.shape;
|
|
23
|
+
if (shape.length < 1) {
|
|
24
|
+
throw new VisionError('INVALID_LOGITS', 'logits must be at least rank 1');
|
|
25
|
+
}
|
|
26
|
+
const classDim = shape[shape.length - 1];
|
|
27
|
+
if (classDim !== labels.size) {
|
|
28
|
+
throw new VisionError('LABEL_SIZE_MISMATCH', `logits class dim=${classDim} does not match labelSpace size=${labels.size}`);
|
|
29
|
+
}
|
|
30
|
+
const data = await logits.toArray();
|
|
31
|
+
// Use last row for batched [N, C]; full vector for [C].
|
|
32
|
+
const offset = shape.length === 1 ? 0 : (shape[0] - 1) * classDim;
|
|
33
|
+
const scores = data.slice(offset, offset + classDim);
|
|
34
|
+
const order = scores
|
|
35
|
+
.map((score, index) => ({ score, index }))
|
|
36
|
+
.sort((a, b) => b.score - a.score)
|
|
37
|
+
.slice(0, k);
|
|
38
|
+
return {
|
|
39
|
+
labelSpaceId: labels.id,
|
|
40
|
+
topK: order.map(({ score, index }) => ({
|
|
41
|
+
index,
|
|
42
|
+
score,
|
|
43
|
+
label: labels.labels[index],
|
|
44
|
+
})),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa1C,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACvD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,qBAAqB,EAAE,0CAA0C,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,WAAW,CAAC,qBAAqB,EAAE,oDAAoD,CAAC,CAAC;IACvG,CAAC;IACD,OAAO;QACH,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM;KAC9B,CAAC;AACN,CAAC;AAkBD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAc,EAAE,OAAoC;IAC3F,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,WAAW,CAAC,gBAAgB,EAAE,gCAAgC,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAC1C,IAAI,QAAQ,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,WAAW,CAAC,qBAAqB,EAAE,oBAAoB,QAAQ,mCAAmC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/H,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACpC,wDAAwD;IACxD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM;SACf,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;SACzC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SACjC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEjB,OAAO;QACH,YAAY,EAAE,MAAM,CAAC,EAAE;QACvB,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YACnC,KAAK;YACL,KAAK;YACL,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAE;SAC/B,CAAC,CAAC;KACN,CAAC;AACN,CAAC"}
|
package/dist/neural.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Tensor } from '@dxo/core';
|
|
2
|
+
import type { TensorStateSlice } from '@dxo/nn';
|
|
3
|
+
import type { TensorPort } from './types.js';
|
|
4
|
+
/** Soft ports for graph connectivity — no labels / language. */
|
|
5
|
+
export type NeuralSignature = {
|
|
6
|
+
input: Record<string, TensorPort>;
|
|
7
|
+
output: Record<string, TensorPort>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Public DXO compute contract (Living `14`).
|
|
11
|
+
* `@dxo/nn` `Module` may remain as an implementation base; cross-package APIs use Neural.
|
|
12
|
+
*/
|
|
13
|
+
export interface Neural<I = Tensor, O = Tensor> {
|
|
14
|
+
forward(input: I): O;
|
|
15
|
+
readonly signature: NeuralSignature;
|
|
16
|
+
parameters(): Iterable<Tensor>;
|
|
17
|
+
state(): Promise<Record<string, TensorStateSlice>>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=neural.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neural.d.ts","sourceRoot":"","sources":["../src/neural.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACtC,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM;IAC1C,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,UAAU,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACtD"}
|
package/dist/neural.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neural.js","sourceRoot":"","sources":["../src/neural.ts"],"names":[],"mappings":""}
|
package/dist/resnet.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Tensor } from '@dxo/core';
|
|
2
|
+
import { BatchNorm2d, Conv2d, MaxPool2d, Module, Relu, type TensorStateSlice } from '@dxo/nn';
|
|
3
|
+
import { BasicBlock } from './basic-block.js';
|
|
4
|
+
import type { Neural } from './neural.js';
|
|
5
|
+
import { type ResNetDepth, type ResNetOptions, type ResNetSignature, type TensorPort, type WeightSource } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* ResNet backbone Neural — `forward` yields feature Tensor, never labels.
|
|
8
|
+
* DXO-native parameter names (`stem.*` / `stageN.blockM.*`); not a torchvision key mirror.
|
|
9
|
+
* depth=18 is wired; other depths throw `UNSUPPORTED` on forward/state.
|
|
10
|
+
* Extends `@dxo/nn` Module for parameter walk; public contract is Neural.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ResNet extends Module implements Neural<Tensor, Tensor> {
|
|
13
|
+
#private;
|
|
14
|
+
readonly depth: ResNetDepth;
|
|
15
|
+
readonly inChannels: number;
|
|
16
|
+
readonly zeroInitResidual: boolean;
|
|
17
|
+
readonly norm: 'batchnorm';
|
|
18
|
+
readonly device: ResNetOptions['device'];
|
|
19
|
+
readonly signature: ResNetSignature;
|
|
20
|
+
/** Present only when depth === 18. */
|
|
21
|
+
stemConv: Conv2d | null;
|
|
22
|
+
stemBn: BatchNorm2d | null;
|
|
23
|
+
stemRelu: Relu | null;
|
|
24
|
+
stemPool: MaxPool2d | null;
|
|
25
|
+
stages: BasicBlock[][] | null;
|
|
26
|
+
constructor(options?: ResNetOptions);
|
|
27
|
+
features(): TensorPort;
|
|
28
|
+
freeze(): void;
|
|
29
|
+
unfreeze(): void;
|
|
30
|
+
get trainable(): boolean;
|
|
31
|
+
/** Flat DXO state keys (depth=18 only). */
|
|
32
|
+
parameterNames(): string[];
|
|
33
|
+
state(): Promise<Record<string, TensorStateSlice>>;
|
|
34
|
+
loadState(saved: Record<string, TensorStateSlice>, opts?: {
|
|
35
|
+
requiresGrad?: boolean;
|
|
36
|
+
}): void;
|
|
37
|
+
forward(image: Tensor): Tensor;
|
|
38
|
+
load(_weights: WeightSource, _options?: {
|
|
39
|
+
scope?: 'all' | 'backbone';
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
ready(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
export declare function defineResNet(options?: ResNetOptions): ResNet;
|
|
44
|
+
//# sourceMappingURL=resnet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resnet.d.ts","sourceRoot":"","sources":["../src/resnet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC9F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,eAAe,EAEpB,KAAK,UAAU,EACf,KAAK,YAAY,EACpB,MAAM,YAAY,CAAC;AA0BpB;;;;;GAKG;AACH,qBAAa,MAAO,SAAQ,MAAO,YAAW,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;IAChE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IAIpC,sCAAsC;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC/B,MAAM,EAAE,WAAW,GAAG,IAAI,CAAQ;IAClC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAQ;IAC7B,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAQ;IAClC,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,IAAI,CAAQ;gBAEzB,OAAO,GAAE,aAAkB;IAuCvC,QAAQ,IAAI,UAAU;IAItB,MAAM,IAAI,IAAI;IAId,QAAQ,IAAI,IAAI;IAIhB,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,2CAA2C;IAC3C,cAAc,IAAI,MAAM,EAAE;IA2BpB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAoBxD,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAmB/F,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IA2BxB,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,GAAG,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAItF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B;AAED,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAE5D"}
|
package/dist/resnet.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { BatchNorm2d, Conv2d, MaxPool2d, Module, Relu } from '@dxo/nn';
|
|
2
|
+
import { BasicBlock } from './basic-block.js';
|
|
3
|
+
import { unsupported, VisionError } from './errors.js';
|
|
4
|
+
import { resnetFeatureChannels, } from './types.js';
|
|
5
|
+
/** DXO-native ResNet-18 layout: stages [2,2,2,2], channels 64→512. No classification `fc`. */
|
|
6
|
+
const RESNET18_BLOCKS = [2, 2, 2, 2];
|
|
7
|
+
const RESNET18_CHANNELS = [64, 128, 256, 512];
|
|
8
|
+
function buildSignature(depth, inChannels) {
|
|
9
|
+
const features = resnetFeatureChannels(depth);
|
|
10
|
+
return {
|
|
11
|
+
input: {
|
|
12
|
+
image: {
|
|
13
|
+
name: 'image',
|
|
14
|
+
dtype: 'f32',
|
|
15
|
+
shape: ['batch', inChannels, 'height', 'width'],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
output: {
|
|
19
|
+
features: {
|
|
20
|
+
name: 'features',
|
|
21
|
+
dtype: 'f32',
|
|
22
|
+
shape: ['batch', features],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* ResNet backbone Neural — `forward` yields feature Tensor, never labels.
|
|
29
|
+
* DXO-native parameter names (`stem.*` / `stageN.blockM.*`); not a torchvision key mirror.
|
|
30
|
+
* depth=18 is wired; other depths throw `UNSUPPORTED` on forward/state.
|
|
31
|
+
* Extends `@dxo/nn` Module for parameter walk; public contract is Neural.
|
|
32
|
+
*/
|
|
33
|
+
export class ResNet extends Module {
|
|
34
|
+
depth;
|
|
35
|
+
inChannels;
|
|
36
|
+
zeroInitResidual;
|
|
37
|
+
norm;
|
|
38
|
+
device;
|
|
39
|
+
signature;
|
|
40
|
+
#trainable;
|
|
41
|
+
#ready = true;
|
|
42
|
+
/** Present only when depth === 18. */
|
|
43
|
+
stemConv = null;
|
|
44
|
+
stemBn = null;
|
|
45
|
+
stemRelu = null;
|
|
46
|
+
stemPool = null;
|
|
47
|
+
stages = null;
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
super();
|
|
50
|
+
this.depth = options.depth ?? 18;
|
|
51
|
+
this.inChannels = options.inChannels ?? 3;
|
|
52
|
+
this.zeroInitResidual = options.zeroInitResidual ?? false;
|
|
53
|
+
this.norm = options.norm ?? 'batchnorm';
|
|
54
|
+
this.device = options.device ?? 'cpu';
|
|
55
|
+
this.#trainable = options.trainable ?? true;
|
|
56
|
+
this.signature = buildSignature(this.depth, this.inChannels);
|
|
57
|
+
if (options.weights && options.weights !== 'none') {
|
|
58
|
+
this.#ready = false;
|
|
59
|
+
}
|
|
60
|
+
if (this.depth === 18) {
|
|
61
|
+
this.#buildResNet18(options.trainable ?? true);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
#buildResNet18(requiresGrad) {
|
|
65
|
+
const rg = requiresGrad;
|
|
66
|
+
this.stemConv = new Conv2d(this.inChannels, 64, 7, { stride: 2, padding: 3, requiresGrad: rg });
|
|
67
|
+
this.stemBn = new BatchNorm2d(64, { requiresGrad: rg });
|
|
68
|
+
this.stemRelu = new Relu();
|
|
69
|
+
this.stemPool = new MaxPool2d(3, { stride: 2, padding: 1 });
|
|
70
|
+
const stages = [];
|
|
71
|
+
let inCh = 64;
|
|
72
|
+
for (let s = 0; s < RESNET18_BLOCKS.length; s++) {
|
|
73
|
+
const outCh = RESNET18_CHANNELS[s];
|
|
74
|
+
const nBlocks = RESNET18_BLOCKS[s];
|
|
75
|
+
const stage = [];
|
|
76
|
+
for (let b = 0; b < nBlocks; b++) {
|
|
77
|
+
const stride = s > 0 && b === 0 ? 2 : 1;
|
|
78
|
+
stage.push(new BasicBlock(`stage${s + 1}.block${b}`, inCh, outCh, { stride, requiresGrad: rg }));
|
|
79
|
+
inCh = outCh;
|
|
80
|
+
}
|
|
81
|
+
stages.push(stage);
|
|
82
|
+
}
|
|
83
|
+
this.stages = stages;
|
|
84
|
+
}
|
|
85
|
+
features() {
|
|
86
|
+
return this.signature.output.features;
|
|
87
|
+
}
|
|
88
|
+
freeze() {
|
|
89
|
+
this.#trainable = false;
|
|
90
|
+
}
|
|
91
|
+
unfreeze() {
|
|
92
|
+
this.#trainable = true;
|
|
93
|
+
}
|
|
94
|
+
get trainable() {
|
|
95
|
+
return this.#trainable;
|
|
96
|
+
}
|
|
97
|
+
/** Flat DXO state keys (depth=18 only). */
|
|
98
|
+
parameterNames() {
|
|
99
|
+
if (this.depth !== 18 || !this.stages) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
// Synchronous name list without reading tensor data.
|
|
103
|
+
const names = ['stem.conv.weight', 'stem.conv.bias', 'stem.bn.weight', 'stem.bn.bias'];
|
|
104
|
+
for (const stage of this.stages) {
|
|
105
|
+
for (const block of stage) {
|
|
106
|
+
const p = block.prefix;
|
|
107
|
+
names.push(`${p}.conv1.weight`, `${p}.conv1.bias`, `${p}.bn1.weight`, `${p}.bn1.bias`, `${p}.conv2.weight`, `${p}.conv2.bias`, `${p}.bn2.weight`, `${p}.bn2.bias`);
|
|
108
|
+
if (block.downConv) {
|
|
109
|
+
names.push(`${p}.down.conv.weight`, `${p}.down.conv.bias`, `${p}.down.bn.weight`, `${p}.down.bn.bias`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return names;
|
|
114
|
+
}
|
|
115
|
+
async state() {
|
|
116
|
+
if (this.depth !== 18 || !this.stemConv || !this.stemBn || !this.stages) {
|
|
117
|
+
unsupported('ResNet.state', `depth=${this.depth}; only depth=18 state schema is wired`);
|
|
118
|
+
}
|
|
119
|
+
const c = await this.stemConv.state();
|
|
120
|
+
const b = await this.stemBn.state();
|
|
121
|
+
const out = {
|
|
122
|
+
'stem.conv.weight': c.weight,
|
|
123
|
+
'stem.conv.bias': c.bias,
|
|
124
|
+
'stem.bn.weight': b.weight,
|
|
125
|
+
'stem.bn.bias': b.bias,
|
|
126
|
+
};
|
|
127
|
+
for (const stage of this.stages) {
|
|
128
|
+
for (const block of stage) {
|
|
129
|
+
Object.assign(out, await block.state());
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
loadState(saved, opts = {}) {
|
|
135
|
+
if (this.depth !== 18 || !this.stemConv || !this.stemBn || !this.stages) {
|
|
136
|
+
unsupported('ResNet.loadState', `depth=${this.depth}; only depth=18 state schema is wired`);
|
|
137
|
+
}
|
|
138
|
+
const rg = opts.requiresGrad ?? true;
|
|
139
|
+
const need = (k) => {
|
|
140
|
+
const s = saved[k];
|
|
141
|
+
if (!s)
|
|
142
|
+
throw new VisionError('MISSING_STATE_KEY', `ResNet.loadState: missing '${k}'`);
|
|
143
|
+
return s;
|
|
144
|
+
};
|
|
145
|
+
this.stemConv.loadState({ weight: need('stem.conv.weight'), bias: need('stem.conv.bias') }, { requiresGrad: rg });
|
|
146
|
+
this.stemBn.loadState({ weight: need('stem.bn.weight'), bias: need('stem.bn.bias') }, { requiresGrad: rg });
|
|
147
|
+
for (const stage of this.stages) {
|
|
148
|
+
for (const block of stage) {
|
|
149
|
+
block.loadState(saved, { requiresGrad: rg });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
forward(image) {
|
|
154
|
+
if (this.depth !== 18 || !this.stemConv || !this.stemBn || !this.stemRelu || !this.stemPool || !this.stages) {
|
|
155
|
+
unsupported('ResNet.forward', `depth=${this.depth}; only depth=18 forward is wired`);
|
|
156
|
+
}
|
|
157
|
+
if (image.shape.length !== 4) {
|
|
158
|
+
throw new VisionError('MODEL_INPUT_SHAPE_MISMATCH', `ResNet.forward expects NCHW rank 4, got [${image.shape.join(',')}]`);
|
|
159
|
+
}
|
|
160
|
+
if (image.shape[1] !== this.inChannels) {
|
|
161
|
+
throw new VisionError('MODEL_INPUT_SHAPE_MISMATCH', `ResNet.forward expected ${this.inChannels} channels, got ${image.shape[1]}`);
|
|
162
|
+
}
|
|
163
|
+
let h = this.stemRelu.forward(this.stemBn.forward(this.stemConv.forward(image)));
|
|
164
|
+
h = this.stemPool.forward(h);
|
|
165
|
+
for (const stage of this.stages) {
|
|
166
|
+
for (const block of stage) {
|
|
167
|
+
h = block.forward(h);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const n = h.shape[0];
|
|
171
|
+
const c = h.shape[1];
|
|
172
|
+
const spatial = (h.shape[2] ?? 1) * (h.shape[3] ?? 1);
|
|
173
|
+
if (spatial !== 1) {
|
|
174
|
+
unsupported('ResNet.forward', `final spatial ${h.shape[2]}x${h.shape[3]} != 1x1 (use 32x32 input for depth=18 without avgPool)`);
|
|
175
|
+
}
|
|
176
|
+
return h.reshape([n, c]);
|
|
177
|
+
}
|
|
178
|
+
async load(_weights, _options) {
|
|
179
|
+
unsupported('ResNet.load', 'use loadWeights in a later preview; remote sources not wired');
|
|
180
|
+
}
|
|
181
|
+
async ready() {
|
|
182
|
+
if (!this.#ready) {
|
|
183
|
+
unsupported('ResNet.ready', 'deferred weight load not wired');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
export function defineResNet(options) {
|
|
188
|
+
return new ResNet(options);
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=resnet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resnet.js","sourceRoot":"","sources":["../src/resnet.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Device } from '@dxo/core';
|
|
2
|
+
import type { NeuralSignature } from './neural.js';
|
|
3
|
+
/** Soft graph port — connectivity only; no labels / language. */
|
|
4
|
+
export type TensorPort = {
|
|
5
|
+
name: string;
|
|
6
|
+
dtype: 'f32';
|
|
7
|
+
/** Symbolic dims; numbers are fixed, strings are dynamic axes. */
|
|
8
|
+
shape: ReadonlyArray<number | string>;
|
|
9
|
+
};
|
|
10
|
+
/** External weight locator (resolved by hub / external `@dxo/resnet` later). */
|
|
11
|
+
export type WeightSource = {
|
|
12
|
+
provider: string;
|
|
13
|
+
repo: string;
|
|
14
|
+
revision?: string;
|
|
15
|
+
path: string;
|
|
16
|
+
} | {
|
|
17
|
+
path: string;
|
|
18
|
+
};
|
|
19
|
+
export type { Device };
|
|
20
|
+
export type ResNetDepth = 18 | 34 | 50 | 101 | 152;
|
|
21
|
+
/**
|
|
22
|
+
* ResNet constructor options.
|
|
23
|
+
* Intentionally has **no** `classes` / `numClasses` / label fields.
|
|
24
|
+
*/
|
|
25
|
+
export type ResNetOptions = {
|
|
26
|
+
depth?: ResNetDepth;
|
|
27
|
+
inChannels?: number;
|
|
28
|
+
zeroInitResidual?: boolean;
|
|
29
|
+
norm?: 'batchnorm';
|
|
30
|
+
weights?: WeightSource | 'none';
|
|
31
|
+
device?: Device;
|
|
32
|
+
trainable?: boolean;
|
|
33
|
+
};
|
|
34
|
+
export type ResNetSignature = NeuralSignature & {
|
|
35
|
+
input: {
|
|
36
|
+
image: TensorPort;
|
|
37
|
+
};
|
|
38
|
+
output: {
|
|
39
|
+
features: TensorPort;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
/** Feature channel count after GAP for classic ResNet depths. */
|
|
43
|
+
export declare function resnetFeatureChannels(depth: ResNetDepth): number;
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;CACzC,CAAC;AAEF,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAClB;IACI,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvB,YAAY,EAAE,MAAM,EAAE,CAAC;AAEvB,MAAM,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC5C,KAAK,EAAE;QAAE,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IAC7B,MAAM,EAAE;QAAE,QAAQ,EAAE,UAAU,CAAA;KAAE,CAAC;CACpC,CAAC;AAEF,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAchE"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Feature channel count after GAP for classic ResNet depths. */
|
|
2
|
+
export function resnetFeatureChannels(depth) {
|
|
3
|
+
switch (depth) {
|
|
4
|
+
case 18:
|
|
5
|
+
case 34:
|
|
6
|
+
return 512;
|
|
7
|
+
case 50:
|
|
8
|
+
case 101:
|
|
9
|
+
case 152:
|
|
10
|
+
return 2048;
|
|
11
|
+
default: {
|
|
12
|
+
const _exhaustive = depth;
|
|
13
|
+
return _exhaustive;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA4CA,iEAAiE;AACjE,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACpD,QAAQ,KAAK,EAAE,CAAC;QACZ,KAAK,EAAE,CAAC;QACR,KAAK,EAAE;YACH,OAAO,GAAG,CAAC;QACf,KAAK,EAAE,CAAC;QACR,KAAK,GAAG,CAAC;QACT,KAAK,GAAG;YACJ,OAAO,IAAI,CAAC;QAChB,OAAO,CAAC,CAAC,CAAC;YACN,MAAM,WAAW,GAAU,KAAK,CAAC;YACjC,OAAO,WAAW,CAAC;QACvB,CAAC;IACL,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
|
|
2
|
+
"name": "@dxo/vision",
|
|
3
|
+
"version": "0.0.12",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "DXO vision models and task adapters (developer preview, API unstable)",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@dxo/core": "0.0.12",
|
|
24
|
+
"@dxo/nn": "0.0.12"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"dxo",
|
|
28
|
+
"vision",
|
|
29
|
+
"resnet",
|
|
30
|
+
"image",
|
|
31
|
+
"typescript",
|
|
32
|
+
"deep-learning",
|
|
33
|
+
"developer-preview"
|
|
34
|
+
],
|
|
35
|
+
"homepage": "https://github.com/ai4waifu/dxo-framework#readme",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/ai4waifu/dxo-framework.git",
|
|
39
|
+
"directory": "projects/runtimes/dxo-vision"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/ai4waifu/dxo-framework/issues"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
10
47
|
}
|