提交修改
This commit is contained in:
parent
252a5232da
commit
26f8780eff
@ -142,7 +142,15 @@ void EvaluateLine(
|
||||
}
|
||||
|
||||
// 角度平滑:滑动窗口均值,抑制点级噪声
|
||||
// Fix3: 先保存原始角度,平滑后对所有"原始角度已超阈"的点强制恢复特征分类,
|
||||
// 防止平滑窗口把窄孔洞两侧的异号角度互相抵消,导致真实边缘被压回 Flat。
|
||||
{
|
||||
// 保存平滑前的原始角度
|
||||
std::vector<float> rawAngles(count, 0.0f);
|
||||
for (int i = 0; i < count; i++) {
|
||||
rawAngles[i] = pts[i].signedAngleDeg;
|
||||
}
|
||||
|
||||
int smoothW = params.residualSmoothWindow;
|
||||
if (smoothW > 1) {
|
||||
int halfW = smoothW / 2;
|
||||
@ -170,6 +178,24 @@ void EvaluateLine(
|
||||
pts[i].trend = keLineAngleTrend_Flat;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix3: 若原始角度已超过检测阈值,平滑窗口不应将其压回 Flat。
|
||||
// 原始角度由 searchDist 参考点计算,本身已具备一定的抗噪能力。
|
||||
// 平滑窗口在孔洞两侧引入异号角度交叉干扰,会把窄孔洞的边缘信号抹平:
|
||||
// - 孔洞入射侧的 Desc 角被出射侧的正角平均拉升,可能越过 negThresh;
|
||||
// - 孔洞出射侧的 Asc 角被入射侧的负角平均拉低,可能跌破 posThresh。
|
||||
// 保护原则:raw 超阈 → 强制保留为特征点;raw 未超阈 → 允许平滑结果覆盖。
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!pts[i].hasAngle) continue;
|
||||
float raw = rawAngles[i];
|
||||
if (raw > posThresh && pts[i].trend != keLineAngleTrend_PositiveJump) {
|
||||
pts[i].signedAngleDeg = raw;
|
||||
pts[i].trend = keLineAngleTrend_PositiveJump;
|
||||
} else if (raw < negThresh && pts[i].trend != keLineAngleTrend_NegativeJump) {
|
||||
pts[i].signedAngleDeg = raw;
|
||||
pts[i].trend = keLineAngleTrend_NegativeJump;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
@ -248,12 +274,18 @@ void EvaluateLine(
|
||||
}
|
||||
|
||||
// 短段合并:单点的 Ascending/Descending 段视为噪声,合并回 Flat
|
||||
// 例外:紧邻 Gap 段的单点 Asc/Desc 是孔洞边缘的真实信号,不应消除
|
||||
{
|
||||
for (auto& seg : segs) {
|
||||
for (size_t k = 0; k < segs.size(); k++) {
|
||||
auto& seg = segs[k];
|
||||
if (seg.type != ESegType::Flat && seg.type != ESegType::Gap) {
|
||||
int segLen = seg.endPos - seg.startPos + 1;
|
||||
if (segLen < 2) {
|
||||
seg.type = ESegType::Flat;
|
||||
bool adjToGap = (k > 0 && segs[k - 1].type == ESegType::Gap)
|
||||
|| (k + 1 < segs.size() && segs[k + 1].type == ESegType::Gap);
|
||||
if (!adjToGap) {
|
||||
seg.type = ESegType::Flat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,10 +320,13 @@ void EvaluateLine(
|
||||
|
||||
bool seenDesc = false, seenAsc = false, seenGap = false;
|
||||
bool descFirst = false;
|
||||
bool seenInnerFlat = false; // 已在"坑底"模式下见过内部 Flat
|
||||
size_t bestExit = si;
|
||||
|
||||
for (size_t ei = si + 1; ei < segs.size(); ei++) {
|
||||
if (segs[ei].type == ESegType::Descending) {
|
||||
// 若已见过内部 Flat 且尚未找到上升沿,说明这是第二个独立特征的下降,不应桥接
|
||||
if (seenInnerFlat && !seenAsc) break;
|
||||
if (!seenAsc) descFirst = true;
|
||||
seenDesc = true;
|
||||
continue;
|
||||
@ -313,8 +348,10 @@ void EvaluateLine(
|
||||
if (seenDesc && seenAsc && descFirst) break; // 完整凹坑
|
||||
if (!seenDesc && !seenAsc && seenGap) break; // 纯空洞
|
||||
if (!seenDesc && seenAsc) break; // 仅上升(凸起),不继续
|
||||
if (seenDesc && seenAsc && !descFirst) break; // 上升-下降型边缘/凸起,完成配对
|
||||
|
||||
// seenDesc && !seenAsc: 可能是内部 Flat(坑底),继续向前找上升
|
||||
seenInnerFlat = true;
|
||||
}
|
||||
|
||||
if (bestExit <= si) continue;
|
||||
@ -327,6 +364,18 @@ void EvaluateLine(
|
||||
int startPos = segs[si].endPos;
|
||||
int endPos = segs[bestExit].startPos;
|
||||
|
||||
// 对凹坑特征,右边界应落在最后一个上升段的末端,而不是后继 Flat 的起点。
|
||||
// 否则会把边界推出到已经回到平台面的点上,导致 pair 比真实坑口更宽。
|
||||
if (isPit) {
|
||||
for (size_t back = bestExit; back > si; --back) {
|
||||
const Segment& seg = segs[back - 1];
|
||||
if (seg.type == ESegType::Ascending) {
|
||||
endPos = seg.endPos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// depth: 表面与坑底的 z 极差
|
||||
float refZ = std::min(pts[startPos].point.z, pts[endPos].point.z);
|
||||
float minZ = refZ, maxZ = refZ;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user