feat: 完善淘宝小程序拍照、报告与登录流程
接入本地实时识别和自动三连拍,调整报告裁切、商品跳转、分享标题及居中页眉;完善游客会话、后台渠道隔离、部署脚本与回归测试。
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
// Reproducible CPU/no-DOM benchmark. Prints timings/counts, never pixels/points.
|
||||
const fs = require('node:fs'), path = require('node:path'), vm = require('node:vm'), zlib = require('node:zlib');
|
||||
const root = path.resolve(__dirname, '..'), cache = {};
|
||||
const context = vm.createContext({ console: { log() {}, warn() {}, error() {} }, setTimeout, clearTimeout });
|
||||
function load(file) {
|
||||
file = path.resolve(file); if (cache[file]) return cache[file].exports;
|
||||
const module = { exports: {} }; cache[file] = module;
|
||||
const run = vm.runInContext('(function(exports,require,module){' + fs.readFileSync(file, 'utf8') + '\n})', context, { filename: file });
|
||||
run(module.exports, name => { if (!name.startsWith('.')) throw new Error('Unexpected runtime dependency'); return load(path.resolve(path.dirname(file), name + '.js')); }, module);
|
||||
return module.exports;
|
||||
}
|
||||
const fixture = JSON.parse(fs.readFileSync(path.join(root, 'test/fixtures/native-face-c3.json'), 'utf8'));
|
||||
const source = new Uint8Array(zlib.gunzipSync(Buffer.from(fixture.gzipBase64, 'base64')));
|
||||
const portrait = { width: 540, height: 960, data: new Uint8Array(540 * 960 * 4) };
|
||||
for (let at = 3; at < portrait.data.length; at += 4) portrait.data[at] = 255;
|
||||
for (let y = 0; y < 405; y++) for (let x = 0; x < 540; x++) {
|
||||
const at = (Math.floor(y * fixture.height / 405) * fixture.width + Math.floor(x * fixture.width / 540)) * 4;
|
||||
portrait.data.set(source.subarray(at, at + 4), ((y + 277) * 540 + x) * 4);
|
||||
}
|
||||
const repeatArg = process.argv.find(value => value.startsWith('--repeats='));
|
||||
const repeats = repeatArg ? Math.max(1, Math.min(10, Number(repeatArg.split('=')[1]) || 2)) : 2;
|
||||
const cpuOptimization = !process.argv.includes('--baseline-cpu');
|
||||
const maxSideArg = process.argv.find(value => value.startsWith('--max-side='));
|
||||
const maxSide = maxSideArg ? Number(maxSideArg.split('=')[1]) : 320;
|
||||
const sizesArg = process.argv.find(value => value.startsWith('--input-sizes='));
|
||||
const sizes = sizesArg ? sizesArg.split('=')[1].split(',').map(Number) : [256, 192, 160, 128];
|
||||
const api = load(path.join(root, 'utils/native-face.js'));
|
||||
(async () => {
|
||||
if (process.argv.includes('--guided')) {
|
||||
const seed = api.create({ inputSize: 256, landmarkModel: 'full' });
|
||||
const originalPortrait = await seed.detect(portrait);
|
||||
const reference = await seed.detect({ width: fixture.width, height: fixture.height, data: source });
|
||||
seed.dispose();
|
||||
const box = reference.detections[0].detection.box, scale = 960 * 0.45 / box.height;
|
||||
const centerX = box.x + box.width / 2, centerY = box.y + box.height / 2;
|
||||
for (let y = 0; y < 960; y++) for (let x = 0; x < 540; x++) {
|
||||
const sx = Math.floor((x - 270) / scale + centerX), sy = Math.floor((y - 480) / scale + centerY), to = (y * 540 + x) * 4;
|
||||
portrait.data.fill(0, to, to + 3); portrait.data[to + 3] = 255;
|
||||
if (sx >= 0 && sx < fixture.width && sy >= 0 && sy < fixture.height) portrait.data.set(source.subarray((sy * fixture.width + sx) * 4, (sy * fixture.width + sx) * 4 + 4), to);
|
||||
}
|
||||
process.stdout.write(JSON.stringify({ setup: 'guided-portrait', originalPortraitFaceHeightRatio: originalPortrait.detections[0].detection.box.height / 960, requestedFaceHeightRatio: 0.45 }) + '\n');
|
||||
}
|
||||
for (const landmarkModel of ['full', 'tiny']) for (const inputSize of sizes) {
|
||||
const engine = api.create({ defaultPixelFormat: 'RGBA', maxSide, inputSize, landmarkModel, cpuOptimization });
|
||||
const initialized = Date.now(); await engine.init(); const initMs = Date.now() - initialized;
|
||||
const samples = [];
|
||||
for (let index = 0; index < repeats; index++) {
|
||||
const result = await engine.detect(portrait);
|
||||
samples.push({ ...result.timings, faces: result.faceCount, landmarks: result.detections[0] ? result.detections[0].landmarks.positions.length : 0,
|
||||
faceHeightRatio: result.detections[0] ? result.detections[0].detection.box.height / result.height : 0 });
|
||||
}
|
||||
const mean = {};
|
||||
for (const key of ['snapshotMs', 'modelMs', 'tensorMs', 'detectorMs', 'landmarkMs', 'totalMs']) mean[key] = Math.round(samples.reduce((sum, item) => sum + item[key], 0) / samples.length);
|
||||
const memory = engine.stats(); engine.dispose();
|
||||
process.stdout.write(JSON.stringify({ landmarkModel, inputSize, maxSide, cpuOptimization, frame: '540x960', initMs, mean,
|
||||
allSamplesDetected: samples.every(item => item.faces > 0 && item.landmarks === 68), samples,
|
||||
modelBytes: memory.numBytes, modelTensors: memory.numTensors, afterDisposeTensors: engine.stats().numTensors }) + '\n');
|
||||
}
|
||||
})().catch(error => { process.stderr.write(error.message + '\n'); process.exitCode = 1; });
|
||||
Reference in New Issue
Block a user