83 lines
5.5 KiB
JavaScript
83 lines
5.5 KiB
JavaScript
'use strict';
|
|
const assert = require('assert/strict');
|
|
const fs = require('fs');
|
|
const vm = require('vm');
|
|
const path = require('path');
|
|
const SkinScore = require('../js/skin-score');
|
|
const ReportUI = require('../js/report-ui');
|
|
const result = JSON.parse(fs.readFileSync(path.join(__dirname, '../../reference/facepp-skinanalyze/examples/ref_3view_raw.json'))).result;
|
|
const details = ReportUI.wrinkleDetails(result);
|
|
assert.equal(details.length, 12);
|
|
assert.equal(new Set(details.map(row => row.key)).size, 12);
|
|
assert.equal(details[0].name, '抬头纹(额头纹)');
|
|
assert.deepEqual(details[0].metrics, {
|
|
wrinkle_score: 13, wrinkle_severity_level: 1, wrinkle_deep_num: 22, wrinkle_shallow_num: 18,
|
|
wrinkle_norm_length: result.forehead_wrinkle_info.wrinkle_norm_length,
|
|
wrinkle_norm_depth: result.forehead_wrinkle_info.wrinkle_norm_depth,
|
|
wrinkle_pixel_density: result.forehead_wrinkle_info.wrinkle_pixel_density,
|
|
wrinkle_area_ratio: result.forehead_wrinkle_info.wrinkle_area_ratio,
|
|
wrinkle_deep_ratio: result.forehead_wrinkle_info.wrinkle_deep_ratio
|
|
});
|
|
assert.equal(details.find(row => row.key === 'left_eye').metrics.wrinkle_deep_num, 58);
|
|
assert.equal(details.find(row => row.key === 'right_eye').metrics.wrinkle_shallow_num, 46);
|
|
assert.equal(details.find(row => row.key === 'left_cheek').metrics.wrinkle_score, 0);
|
|
const alternate = ReportUI.wrinkleDetails({ right_nasolabial_fold_info: { wrinkle_score: { value: 31 }, wrinkle_severity_level: { value: 2 } },
|
|
wrinkle_count: { right_nasolabial_count: 5 }, fine_line: { right_nasolabial_count: 0 } });
|
|
assert.equal(alternate.find(row => row.key === 'right_nasolabial').metrics.wrinkle_score, 31);
|
|
assert.equal(alternate.find(row => row.key === 'right_nasolabial').metrics.wrinkle_deep_num, 5);
|
|
assert.equal(alternate.find(row => row.key === 'right_nasolabial').metrics.wrinkle_shallow_num, 0);
|
|
assert(Object.values(alternate[0].metrics).every(value => value === null));
|
|
const model = SkinScore.buildViewModel(result, SkinScore.MOCK_SIDE, { realAge: 30 });
|
|
const modelBefore = JSON.stringify(model), rawBefore = JSON.stringify(result);
|
|
const presentation = ReportUI.build(model, result);
|
|
const text = presentation.views.find(view => view.key === 'wrinkles').text;
|
|
assert.deepEqual(presentation.views.find(view => view.key === 'wrinkles').details, details);
|
|
assert(!text.includes('分区明细') && !text.includes('标准化长度'));
|
|
const approved = {
|
|
'预警': '全脸共检测到皱纹 12 条、细纹 34 条,面中、口周、眼周等区域已出现静态纹倾向,纹路已呈现固化趋势,并非临时性干纹。',
|
|
'改善': '全脸共检测到皱纹 12 条、细纹 34 条,面部整体平整,仅眼周或口周有细微的干纹,无明显静态深纹,纹路面积占比相对较低。',
|
|
'良好': '面中、口周、眼周等各区域均无明显皱纹沟壑,无静态深纹与粗纹,各类纹路面积均处于极低水平,面部整体平整细腻。'
|
|
};
|
|
for (const level of Object.keys(approved)) {
|
|
const fixture = JSON.parse(modelBefore);
|
|
fixture.cats.wrinkles.level = level;
|
|
fixture.cats.wrinkles.vars.wr_cnt = 12;
|
|
fixture.cats.wrinkles.vars.fl_cnt = 34;
|
|
assert.equal(ReportUI.build(fixture, result).views.find(view => view.key === 'wrinkles').text, approved[level]);
|
|
}
|
|
assert.equal(JSON.stringify(model), modelBefore);
|
|
assert.equal(JSON.stringify(result), rawBefore);
|
|
const excellent = JSON.parse(JSON.stringify(model));
|
|
excellent.cats.smooth.level = '良好'; // Legacy level name maps to new "优秀".
|
|
excellent.cats.smooth.vars.pore_cnt = 7;
|
|
excellent.cats.smooth.vars.blackhead_cnt = 2;
|
|
let smooth = ReportUI.build(excellent, result).views.find(view => view.key === 'smooth');
|
|
assert(smooth.text.includes('粗大毛孔 7 颗、黑头 2 颗'));
|
|
assert(!smooth.text.includes('无明显粗大毛孔'));
|
|
assert.equal(smooth.level, '优秀');
|
|
excellent.cats.smooth.vars.pore_cnt = null;
|
|
smooth = ReportUI.build(excellent, result).views.find(view => view.key === 'smooth');
|
|
assert(smooth.text.includes('未完整获取'));
|
|
const source = fs.readFileSync(path.join(__dirname, '../js/app.js'), 'utf8');
|
|
const pure = source.match(/\/\* viz-pure-begin[\s\S]*?\*\/([\s\S]*?)\/\* viz-pure-end \*\//)[1];
|
|
const sandbox = {}; vm.runInNewContext(pure, sandbox);
|
|
const crop = sandbox.vizFaceCrop(4000, 3000, { left: 1479, top: 1133, width: 1116, height: 1116 });
|
|
assert(crop.focused);
|
|
assert(crop.width < 1600 && crop.height < 1800);
|
|
assert(crop.left <= 1479 && crop.top <= 1133);
|
|
assert(crop.left + crop.width >= 2595 && crop.top + crop.height >= 2249);
|
|
assert(Math.abs(crop.width / crop.height - 215 / 278) < 1e-8);
|
|
for (const rect of [null, { left: NaN }, { left: 0, top: 0, width: -1, height: 20 },
|
|
{ left: 3900, top: 0, width: 1000, height: 1000 }, { left: 0, top: 0, width: '100', height: 100 }]) {
|
|
const full = sandbox.vizFaceCrop(4000, 3000, rect);
|
|
assert.equal(full.focused, false); assert.equal(full.width, 4000);
|
|
}
|
|
for (const rect of [{ left: 0, top: 0, width: 300, height: 300 }, { left: 700, top: 700, width: 300, height: 300 }]) {
|
|
const edge = sandbox.vizFaceCrop(1000, 1000, rect);
|
|
assert(edge.focused); assert(edge.left >= 0 && edge.top >= 0);
|
|
assert(edge.left + edge.width <= 1000 && edge.top + edge.height <= 1000);
|
|
assert(edge.left <= rect.left && edge.top <= rect.top);
|
|
assert(edge.left + edge.width >= rect.left + rect.width && edge.top + edge.height >= rect.top + rect.height);
|
|
}
|
|
console.log('PASS: 12 unique wrinkle regions, all nine real metrics, aliases/count fallbacks, missing≠zero; positive pore counts vs excellent score; no raw/model/algorithm mutations; face crop/aspect/edge containment/invalid-box fallback');
|