forked from webmachinelearning/webnn-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathface_landmark_nhwc.js
115 lines (97 loc) · 3.57 KB
/
face_landmark_nhwc.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';
import {buildConstantByNpy} from '../common/utils.js';
// SimpleCNN model with 'nhwc' layout.
export class FaceLandmarkNhwc {
constructor() {
this.context_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/face_landmark_nhwc/weights';
this.inputOptions = {
inputLayout: 'nhwc',
inputDimensions: [1, 128, 128, 3],
};
}
async buildConv_(input, indice) {
const prefix = `${this.weightsUrl_}/conv2d`;
let weightSuffix = '_kernel.npy';
let biasSuffix = `_Conv2D_bias.npy`;
if (indice > 0) {
weightSuffix = `_${indice}${weightSuffix}`;
biasSuffix = `_${indice + 1}${biasSuffix}`;
}
const weightsName = prefix + weightSuffix;
const weights = await buildConstantByNpy(this.builder_, weightsName);
const biasName = prefix + biasSuffix;
const bias = await buildConstantByNpy(this.builder_, biasName);
const options = {
inputLayout: 'nhwc',
filterLayout: 'ohwi',
bias: bias,
activation: this.builder_.relu(),
};
return this.builder_.conv2d(input, weights, options);
}
async buildFullyConnected_(input, namePrefix, relu = false, reshapeSize) {
const weights = await buildConstantByNpy(this.builder_,
`${this.weightsUrl_}/${namePrefix}_kernel_transpose.npy`);
const bias = await buildConstantByNpy(this.builder_,
`${this.weightsUrl_}/${namePrefix}_MatMul_bias.npy`);
const options = {
aTranspose: false,
bTranspose: true,
c: bias,
};
let fc;
if (reshapeSize !== undefined) {
fc = this.builder_.gemm(this.builder_.reshape(
input, [null, reshapeSize]), weights, options);
} else {
fc = this.builder_.gemm(input, weights, options);
}
if (relu) {
fc = this.builder_.relu(fc);
}
return fc;
}
async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.builder_ = new MLGraphBuilder(this.context_);
const input = this.builder_.input('input',
{type: 'float32', dimensions: this.inputOptions.inputDimensions});
const poolOptions =
{windowDimensions: [2, 2], strides: [2, 2], layout: 'nhwc'};
const conv0 = await this.buildConv_(input, 0);
const pool0 = await this.builder_.maxPool2d(conv0, poolOptions);
const conv1 = await this.buildConv_(pool0, 1);
const conv2 = await this.buildConv_(conv1, 2);
const pool1 = await this.builder_.maxPool2d(conv2, poolOptions);
const conv3 = await this.buildConv_(pool1, 3);
const conv4 = await this.buildConv_(conv3, 4);
const pool2 = await this.builder_.maxPool2d(conv4, poolOptions);
const conv5 = await this.buildConv_(pool2, 5);
const conv6 = await this.buildConv_(conv5, 6);
const pool3 = await this.builder_.maxPool2d(
conv6, {windowDimensions: [2, 2], layout: 'nhwc'});
const conv7 = await this.buildConv_(pool3, 7);
const fc0 = await this.buildFullyConnected_(
conv7, 'dense', true, 6400);
const fc1 = await this.buildFullyConnected_(fc0, 'logits');
return fc1;
}
async build(outputOperand) {
this.graph_ = await this.builder_.build({'output': outputOperand});
}
// Release the constant tensors of a model
dispose() {
// dispose() is only available in webnn-polyfill
if (this.graph_ !== null && 'dispose' in this.graph_) {
this.graph_.dispose();
}
}
async compute(inputBuffer, outputs) {
const inputs = {'input': inputBuffer};
const results = await this.context_.compute(this.graph_, inputs, outputs);
return results;
}
}