Skip to content

Commit 3180753

Browse files
committed
init model
1 parent fea783c commit 3180753

27 files changed

+1953
-0
lines changed

add.test.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const add = require('./index.js').add;
2+
3+
test('adds 1 + 2 to equal 3', () => {
4+
expect(add(1,2)).toBe(3);
5+
})

index.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export * from "./lib/fr_detect";
2+
export * from "./lib/fr_expression";
3+
export * from "./lib/fr_eye";
4+
export * from "./lib/fr_landmark";
5+
export * from "./lib/fr_liveness";
6+
export * from "./lib/fr_pose";
7+
export * from "./lib/fr_age";
8+
export * from "./lib/fr_gender";
9+
export * from "./lib/fr_feature";
10+
export * from "./lib/load_opencv";

js/opencv.js

+36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/opencv_js.js

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/opencv_js.wasm

3.04 MB
Binary file not shown.

lib/download.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
export const download = (url, logger = null) => {
2+
return new Promise((resolve, reject) => {
3+
const request = new XMLHttpRequest();
4+
request.open("GET", url, true);
5+
request.responseType = "arraybuffer";
6+
if (logger) {
7+
const [log, setState] = logger;
8+
request.onprogress = (e) => {
9+
const progress = (e.loaded / e.total) * 100;
10+
setState({ text: log, progress: progress.toFixed(2) });
11+
};
12+
}
13+
request.onload = function () {
14+
if (this.status >= 200 && this.status < 300) {
15+
resolve(request.response);
16+
} else {
17+
reject({
18+
status: this.status,
19+
statusText: request.statusText,
20+
});
21+
}
22+
resolve(request.response);
23+
};
24+
request.onerror = function () {
25+
reject({
26+
status: this.status,
27+
statusText: request.statusText,
28+
});
29+
};
30+
request.send();
31+
});
32+
};

lib/fr_age.js

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import {InferenceSession, Tensor} from "onnxruntime-web";
2+
import ndarray from "ndarray";
3+
import ops from "ndarray-ops";
4+
5+
async function loadAgeModel() {
6+
var feature_session = null;
7+
await InferenceSession.create("../model/fr_age.onnx", {executionProviders: ['wasm']})
8+
.then((session) => {
9+
feature_session = session
10+
const input_tensor = new Tensor("float32", new Float32Array(64 * 64 * 3), [1, 3, 64, 64]);
11+
for (let i = 0; i < 64 * 64 * 3; i++) {
12+
input_tensor.data[i] = Math.random() * 2.0 - 1.0;
13+
}
14+
const feeds = {"input": input_tensor};
15+
const output_tensor = feature_session.run(feeds)
16+
console.log("initialize the age session.")
17+
})
18+
return feature_session;
19+
}
20+
21+
function alignAgeImage(image, bbox, scale_value) {
22+
var src_h = image.rows,
23+
src_w = image.cols;
24+
25+
var x = bbox[0]
26+
var y = bbox[1]
27+
var box_w = bbox[2]
28+
var box_h = bbox[3]
29+
30+
var scale = Math.min((src_h - 1) / box_h, Math.min((src_w - 1) / box_w, scale_value))
31+
32+
var new_width = box_w * scale
33+
var new_height = box_h * scale
34+
var center_x = box_w / 2 + x,
35+
center_y = box_h / 2 + y
36+
37+
var left_top_x = center_x - new_width / 2
38+
var left_top_y = center_y - new_height / 2
39+
var right_bottom_x = center_x + new_width / 2
40+
var right_bottom_y = center_y + new_height / 2
41+
42+
if (left_top_x < 0) {
43+
right_bottom_x -= left_top_x
44+
left_top_x = 0
45+
}
46+
47+
if (left_top_y < 0) {
48+
right_bottom_y -= left_top_y
49+
left_top_y = 0
50+
}
51+
52+
if (right_bottom_x > src_w - 1) {
53+
left_top_x -= right_bottom_x - src_w + 1
54+
right_bottom_x = src_w - 1
55+
}
56+
57+
if (right_bottom_y > src_h - 1) {
58+
left_top_y -= right_bottom_y - src_h + 1
59+
right_bottom_y = src_h - 1
60+
}
61+
var rect = new cv.Rect(Math.max(parseInt(left_top_x), 0), Math.max(parseInt(left_top_y), 0),
62+
Math.min(parseInt(right_bottom_x - left_top_x), src_w - 1), Math.min(parseInt(right_bottom_y - left_top_y), src_h - 1))
63+
64+
var face_image = new cv.Mat()
65+
face_image = image.roi(rect)
66+
67+
var dsize = new cv.Size(64, 64);
68+
var resize_image = new cv.Mat();
69+
cv.resize(face_image, resize_image, dsize);
70+
71+
face_image.delete()
72+
return resize_image
73+
}
74+
75+
function mergeAge(x, s1, s2, s3, lambda_local, lambda_d) {
76+
let a = 0;
77+
let b = 0;
78+
let c = 0;
79+
80+
const V = 101;
81+
82+
for (let i = 0; i < s1; i++)
83+
a = a + (i + lambda_local * x[12 + i]) * x[i];
84+
// console.log("a = ", a)
85+
86+
a = a / (s1 * (1 + lambda_d * x[9]));
87+
88+
for (let i = 0; i < s2; i++)
89+
b = b + (i + lambda_local * x[15 + i]) * x[3 + i];
90+
//console.log("b = ", b)
91+
92+
b = b / (s1 * (1 + lambda_d * x[9])) / (s2 * (1 + lambda_d * x[10]));
93+
94+
for (let i = 0; i < s3; i++)
95+
c = c + (i + lambda_local * x[18 + i]) * x[6 + i];
96+
//console.log("c = ", c)
97+
98+
c = c / (s1 * (1 + lambda_d * x[9])) / (s2 * (1 + lambda_d * x[10])) / (s3 * (1 + lambda_d * x[11]));
99+
return (a + b + c) * V;
100+
}
101+
102+
function preprocessAge(img) {
103+
var cols = img.cols;
104+
var rows = img.rows;
105+
var channels = 3;
106+
107+
var img_data = ndarray(new Float32Array(rows * cols * channels), [rows, cols, channels]);
108+
109+
for (var y = 0; y < rows; y++)
110+
for (var x = 0; x < cols; x++) {
111+
let pixel = img.ucharPtr(y, x);
112+
// if(x == 0 && y == 0)
113+
// console.log(pixel);
114+
for (var c = 0; c < channels; c++) {
115+
var pixel_value = 0
116+
if (c === 0) // R
117+
pixel_value = (pixel[c] / 255.0 - 0.485) / 0.229
118+
if (c === 1) // G
119+
pixel_value = (pixel[c] / 255.0 - 0.456) / 0.224
120+
if (c === 2) // B
121+
pixel_value = (pixel[c] / 255.0 - 0.406) / 0.225
122+
123+
img_data.set(y, x, c, pixel_value)
124+
}
125+
}
126+
127+
var preprocesed = ndarray(new Float32Array(3 * 64 * 64), [1, 3, 64, 64])
128+
ops.assign(preprocesed.pick(0, 0, null, null), img_data.pick(null, null, 0));
129+
ops.assign(preprocesed.pick(0, 1, null, null), img_data.pick(null, null, 1));
130+
ops.assign(preprocesed.pick(0, 2, null, null), img_data.pick(null, null, 2));
131+
132+
return preprocesed
133+
}
134+
135+
async function predictAge(session, canvas_id, bbox) {
136+
var img = cv.imread(canvas_id);
137+
138+
var face_size = bbox.shape[0];
139+
var bbox_size = bbox.shape[1];
140+
141+
const result = [];
142+
for (let i = 0; i < face_size; i++) {
143+
var x1 = parseInt(bbox.data[i * bbox_size]),
144+
y1 = parseInt(bbox.data[i * bbox_size + 1]),
145+
x2 = parseInt(bbox.data[i * bbox_size + 2]),
146+
y2 = parseInt(bbox.data[i * bbox_size + 3]),
147+
width = Math.abs(x2 - x1),
148+
height = Math.abs(y2 - y1);
149+
150+
var face_img = alignAgeImage(img, [x1, y1, width, height], 1.4);
151+
//cv.imshow("live-temp", face_img);
152+
var input_image = preprocessAge(face_img);
153+
face_img.delete();
154+
155+
const input_tensor = new Tensor("float32", new Float32Array(64 * 64 * 3), [1, 3, 64, 64]);
156+
input_tensor.data.set(input_image.data);
157+
const feeds = {"input": input_tensor};
158+
159+
const output_tensor = await session.run(feeds);
160+
const outputLayers = ["prob_stage_1", "prob_stage_2", "prob_stage_3", "stage1_delta_k", "stage2_delta_k", "stage3_delta_k",
161+
"index_offset_stage1", "index_offset_stage2", "index_offset_stage3"];
162+
163+
const outputFeat = [];
164+
for (let i = 0; i < outputLayers.length; i++) {
165+
const result = output_tensor[outputLayers[i]];
166+
// console.log(outputLayers[i], ": ", result.size);
167+
for (let j = 0; j < result.size; j++)
168+
outputFeat.push(result.data[j]);
169+
}
170+
171+
let age = mergeAge(outputFeat, 3, 3, 3, 1, 1);
172+
console.log("output age: ", age);
173+
result.push([x1, y1, x2, y2, age]);
174+
}
175+
176+
img.delete();
177+
return result;
178+
}
179+
180+
export {loadAgeModel, predictAge}

0 commit comments

Comments
 (0)