Add activated bone brightness scoring
This commit is contained in:
@@ -67,6 +67,8 @@ const AUTO_PROGRESS_STEPS = [
|
|||||||
];
|
];
|
||||||
const BONE_BRIGHT_THRESHOLD = 185;
|
const BONE_BRIGHT_THRESHOLD = 185;
|
||||||
const BONE_EDGE_THRESHOLD = 165;
|
const BONE_EDGE_THRESHOLD = 165;
|
||||||
|
const BONE_ACTIVATION_GAMMA = 1.65;
|
||||||
|
const BONE_MAX_REWARD = 1.45;
|
||||||
const STL_DISPLAY_MODES = ["hidden", "solid", "translucent"];
|
const STL_DISPLAY_MODES = ["hidden", "solid", "translucent"];
|
||||||
const STL_DISPLAY_LABELS = {
|
const STL_DISPLAY_LABELS = {
|
||||||
hidden: "取消显示",
|
hidden: "取消显示",
|
||||||
@@ -3043,6 +3045,18 @@ async function prepareAutoFineImageContext(settings) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function smoothStep(edge0, edge1, value) {
|
||||||
|
const t = clamp((value - edge0) / Math.max(edge1 - edge0, 0.001), 0, 1);
|
||||||
|
return t * t * (3 - 2 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
function boneBrightnessReward(lum) {
|
||||||
|
if (lum < BONE_EDGE_THRESHOLD) return 0;
|
||||||
|
const activation = Math.pow(smoothStep(BONE_EDGE_THRESHOLD, 255, lum), BONE_ACTIVATION_GAMMA);
|
||||||
|
const brightBoost = smoothStep(BONE_BRIGHT_THRESHOLD, 255, lum);
|
||||||
|
return activation * (0.35 + BONE_MAX_REWARD * brightBoost);
|
||||||
|
}
|
||||||
|
|
||||||
function scorePoseAgainstBoneImages(pose, context, settings) {
|
function scorePoseAgainstBoneImages(pose, context, settings) {
|
||||||
if (!context?.frames?.length || !context.samples?.length || !context.volumeScene) return NaN;
|
if (!context?.frames?.length || !context.samples?.length || !context.volumeScene) return NaN;
|
||||||
const current = { ...state.pose };
|
const current = { ...state.pose };
|
||||||
@@ -3089,8 +3103,8 @@ function scorePoseAgainstBoneImages(pose, context, settings) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const lum = image.data[(y * image.width + x) * 4] || 0;
|
const lum = image.data[(y * image.width + x) * 4] || 0;
|
||||||
if (lum >= BONE_BRIGHT_THRESHOLD) hitReward += lum >= 215 ? 1.18 : 1;
|
const reward = boneBrightnessReward(lum);
|
||||||
else if (lum >= BONE_EDGE_THRESHOLD) hitReward += 0.22;
|
if (reward > 0) hitReward += reward;
|
||||||
else missPenalty += 1.05 - (lum / Math.max(BONE_EDGE_THRESHOLD, 1)) * 0.28;
|
else missPenalty += 1.05 - (lum / Math.max(BONE_EDGE_THRESHOLD, 1)) * 0.28;
|
||||||
contributors += 1;
|
contributors += 1;
|
||||||
}
|
}
|
||||||
@@ -3332,7 +3346,7 @@ async function runAutoFine(options = {}) {
|
|||||||
}
|
}
|
||||||
setAutoProgress(true, 94, "应用最佳位姿", "正在把本轮最高分候选写回位姿控件和融合视图。", "apply");
|
setAutoProgress(true, 94, "应用最佳位姿", "正在把本轮最高分候选写回位姿控件和融合视图。", "apply");
|
||||||
state.pose = { ...best.pose };
|
state.pose = { ...best.pose };
|
||||||
state.autoResult = { ...best, evaluated, settings: { ...autoSettingsForStorage(settings), scoring: settings.imageContext ? "strict-bright-bone-window-stl-samples" : "reference-stl-box-overlap", window: "bone", boneThreshold: BONE_BRIGHT_THRESHOLD } };
|
state.autoResult = { ...best, evaluated, settings: { ...autoSettingsForStorage(settings), scoring: settings.imageContext ? "activated-bright-bone-window-stl-samples" : "reference-stl-box-overlap", window: "bone", boneThreshold: BONE_BRIGHT_THRESHOLD, boneActivationGamma: BONE_ACTIVATION_GAMMA } };
|
||||||
state.lastAutoPose = { before, after: { ...state.pose } };
|
state.lastAutoPose = { before, after: { ...state.pose } };
|
||||||
state.autoDeltaBaseline = { ...before };
|
state.autoDeltaBaseline = { ...before };
|
||||||
renderPoseControls();
|
renderPoseControls();
|
||||||
@@ -3343,7 +3357,7 @@ async function runAutoFine(options = {}) {
|
|||||||
const scoreText = Number.isFinite(best.score) ? best.score.toFixed(4) : "不可用";
|
const scoreText = Number.isFinite(best.score) ? best.score.toFixed(4) : "不可用";
|
||||||
const referenceText = describeAutoReference(settings);
|
const referenceText = describeAutoReference(settings);
|
||||||
$("autoResult").textContent = changed
|
$("autoResult").textContent = changed
|
||||||
? `本轮最高分候选:${best.mode};score ${scoreText};评估 ${evaluated} 个候选;${settings.imageContext ? `严格骨窗高亮评分,亮度 ≥ ${BONE_BRIGHT_THRESHOLD} 才作为骨骼命中` : "参考 STL 盒体评分"};${referenceText}。`
|
? `本轮最高分候选:${best.mode};score ${scoreText};评估 ${evaluated} 个候选;${settings.imageContext ? `骨窗高亮激活评分,亮度越高骨骼奖励越大,${BONE_EDGE_THRESHOLD} 以下扣分` : "参考 STL 盒体评分"};${referenceText}。`
|
||||||
: `本轮未找到比当前位姿更高分的候选;score ${scoreText};评估 ${evaluated} 个候选。这不代表已配准正确,只说明当前搜索范围和参考 STL 下没有更高分;${referenceText};自动微调目前只调整平移/缩放,明显旋转错位需要先手动校正。`;
|
: `本轮未找到比当前位姿更高分的候选;score ${scoreText};评估 ${evaluated} 个候选。这不代表已配准正确,只说明当前搜索范围和参考 STL 下没有更高分;${referenceText};自动微调目前只调整平移/缩放,明显旋转错位需要先手动校正。`;
|
||||||
updateAutoPoseResult(before, state.pose);
|
updateAutoPoseResult(before, state.pose);
|
||||||
setAutoProgress(true, 100, changed ? "微调完成" : "本轮未改动", changed ? `已应用 ${best.mode}。` : "没有强行移动模型;请检查参考 STL 和大角度旋转。", "apply");
|
setAutoProgress(true, 100, changed ? "微调完成" : "本轮未改动", changed ? `已应用 ${best.mode}。` : "没有强行移动模型;请检查参考 STL 和大角度旋转。", "apply");
|
||||||
|
|||||||
Reference in New Issue
Block a user