修复完美像素无法识别自身产物的网格
Project CI / Repository checks (pull_request) Successful in 1m19s
Project CI / Frontend tests (pull_request) Failing after 2m6s
Project CI / Backend tests (pull_request) Successful in 3m44s
Project CI / Native shell tests (pull_request) Successful in 14m29s

边缘 profile 用的是跨度 2 的中心差分,硬块边界落在列 b-1|b 之间时
profile[b-1] 与 profile[b] 逐位相等:两者跨的是同一条边,逐行被加数
相同、求和顺序相同。峰值判定两侧都用严格大于,会把这个 2 宽平台的
两端一起丢掉,于是最干净的输入反而 0 个峰、被判为未识别到网格——
完美像素处理不了自己的输出。

estimate_step_size 左邻比较放宽为 >=,右邻保持严格 >:平台只保留
一个索引,且是右端,正好是左闭右开语义下的真实块边。两侧都放宽则
会把长度 K 的常数段整段判为峰。

walk 与 snap_uniform_cuts 的 argmax 同样改为 >=,取等值段的最后一
个索引。取第一个会让每条切线落在真实边界左边 1px,每个 cell 因此
混进 1/4 的邻块。实测在 266x253 的最近邻放大像素画上,切线命中真实
块边从 2.6% 升到 98.5%,左右镜像、上下翻转、180° 旋转下一致;龙图
内容区内 134/134 全中。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-14 12:01:59 +00:00
parent d901945c77
commit 5f82cc8b72
@@ -588,10 +588,18 @@ fn estimate_step_size(profile: &[f64], config: SnapConfig) -> Option<f64> {
return None;
}
let threshold = maximum * config.peak_threshold_multiplier;
// The profile is a two-span central difference, so a hard block edge between
// columns `b - 1` and `b` makes `profile[b - 1]` and `profile[b]` bitwise equal:
// both straddle the same edge and sum the same per-row terms in the same order.
// A strict comparison on both sides rejects both ends of that plateau, which is
// why perfectly snapped pixel art used to yield zero peaks. Accepting equality on
// the left keeps exactly one index per plateau — the right end, which is the real
// boundary — while a strict comparison on the right still rejects the interior of
// wider constant runs.
let peaks = (1..profile.len().saturating_sub(1))
.filter(|&index| {
profile[index] > threshold
&& profile[index] > profile[index - 1]
&& profile[index] >= profile[index - 1]
&& profile[index] > profile[index + 1]
})
.collect::<Vec<_>>();
@@ -694,7 +702,10 @@ fn walk(
let mut best_index = start;
let mut best_value = -1.0f64;
for (index, value) in profile.iter().enumerate().take(end).skip(start) {
if *value > best_value {
// `>=` keeps the last index of an equal run, matching the plateau end that
// `estimate_step_size` selects. Picking the first index instead would place
// every cut one pixel left of the real block boundary.
if *value >= best_value {
best_value = *value;
best_index = index;
}
@@ -878,7 +889,8 @@ fn snap_uniform_cuts(
.take(end.min(profile.len().saturating_sub(1)) + 1)
.skip(start)
{
if *value > best_value {
// Same plateau-end convention as `walk`.
if *value >= best_value {
best_value = *value;
best_index = index;
}