2026-03-24 21:27:48 +08:00
|
|
|
|
#ifndef HOLE_DETECTION_PARAMS_H
|
|
|
|
|
|
#define HOLE_DETECTION_PARAMS_H
|
|
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
2026-04-02 10:14:20 +08:00
|
|
|
|
#include "VZNL_Types.h" // 使用 VZNL_Types.h 中定义的类型
|
2026-03-24 21:27:48 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 孔洞检测算法的检测参数
|
|
|
|
|
|
*/
|
2026-03-20 20:28:41 +08:00
|
|
|
|
struct SHoleDetectionParams {
|
2026-03-24 21:27:48 +08:00
|
|
|
|
// 凹坑检测参数
|
2026-04-02 10:14:20 +08:00
|
|
|
|
float angleThresholdPos; // 正角度阈值,单位:度(默认值:50.0)
|
|
|
|
|
|
float angleThresholdNeg; // 负角度阈值,单位:度(默认值:-50.0)
|
2026-03-24 21:27:48 +08:00
|
|
|
|
float angleSearchDistance; // Method1 前后搜索距离 A,单位:mm
|
|
|
|
|
|
float minPitDepth; // 最小凹坑深度,单位:mm(默认值:1.0)
|
|
|
|
|
|
|
|
|
|
|
|
// 椭圆拟合参数
|
|
|
|
|
|
float minRadius; // 最小孔洞半径,单位:mm(默认值:2.0)
|
|
|
|
|
|
float maxRadius; // 最大孔洞半径,单位:mm(默认值:50.0)
|
|
|
|
|
|
|
|
|
|
|
|
// 平面拟合参数
|
|
|
|
|
|
int expansionSize1; // 第一圈扩展大小(默认值:5)
|
|
|
|
|
|
int expansionSize2; // 第二圈扩展大小(默认值:10)
|
|
|
|
|
|
|
|
|
|
|
|
// V 型检测参数
|
|
|
|
|
|
int minVTransitionPoints; // V 型端点之间的最小有效过渡点数(默认值:1)
|
2026-03-19 20:23:49 +08:00
|
|
|
|
float jumpThresholdResidual; // 相邻有效点的残差跳变阈值,<=0 表示自适应
|
|
|
|
|
|
float gapJumpThresholdResidual; // 跨无效点间隙的残差跳变阈值,<=0 表示自适应
|
|
|
|
|
|
int maxGapPointsInLine; // 允许跨越的最大无效点数
|
|
|
|
|
|
float minFeatureSpan; // 特征点对最小弧长跨度(mm)
|
2026-03-24 21:27:48 +08:00
|
|
|
|
int residualSmoothWindow; // 残差平滑窗口(奇数,建议 3~7)
|
|
|
|
|
|
float slopeAngleThreshold; // 坡度补充判断阈值,单位:度(默认值:3.0)
|
|
|
|
|
|
// 当曲率角未超过 angleThreshold 时,若前后参考点间的
|
|
|
|
|
|
// 净 Z 坡度角超过此阈值,则将该点判定为下降或上升趋势。
|
|
|
|
|
|
// 设置为 0 可禁用坡度补充判断。
|
2026-04-01 01:05:40 +08:00
|
|
|
|
float edgeBoundaryFilterDist; // 边缘过滤距离,单位:mm(默认值:0.0,即不过滤)
|
|
|
|
|
|
// pair 中任意端点到首/尾有效线(行扫描取 y,列扫描取 x)
|
|
|
|
|
|
// 的距离小于此值时,该 pair 将被剔除。
|
2026-03-24 21:27:48 +08:00
|
|
|
|
|
|
|
|
|
|
// 构造函数,设置默认值
|
2026-03-20 20:28:41 +08:00
|
|
|
|
SHoleDetectionParams()
|
2026-04-02 10:14:20 +08:00
|
|
|
|
: angleThresholdPos(50.0f)
|
|
|
|
|
|
, angleThresholdNeg(-50.0f)
|
2026-03-20 20:28:41 +08:00
|
|
|
|
, angleSearchDistance(2.0f)
|
|
|
|
|
|
, minPitDepth(1.0f)
|
|
|
|
|
|
, minRadius(2.0f)
|
2026-03-24 21:27:48 +08:00
|
|
|
|
, maxRadius(50.0f)
|
|
|
|
|
|
, expansionSize1(5)
|
2026-03-19 20:23:49 +08:00
|
|
|
|
, expansionSize2(10)
|
|
|
|
|
|
, minVTransitionPoints(1)
|
|
|
|
|
|
, jumpThresholdResidual(0.0f)
|
|
|
|
|
|
, gapJumpThresholdResidual(0.0f)
|
|
|
|
|
|
, maxGapPointsInLine(12)
|
|
|
|
|
|
, minFeatureSpan(2.0f)
|
|
|
|
|
|
, residualSmoothWindow(5)
|
2026-03-24 00:55:26 +08:00
|
|
|
|
, slopeAngleThreshold(3.0f)
|
2026-04-01 01:05:40 +08:00
|
|
|
|
, edgeBoundaryFilterDist(0.0f)
|
2026-03-19 20:23:49 +08:00
|
|
|
|
{}
|
|
|
|
|
|
};
|
2026-03-24 21:27:48 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 孔洞过滤参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
struct SHoleFilterParams {
|
|
|
|
|
|
|
|
|
|
|
|
// 质量阈值过滤
|
|
|
|
|
|
float maxEccentricity; // 最大离心率(默认值:0.99995,标准公式 e=sqrt(1-(b/a)^2))
|
|
|
|
|
|
|
|
|
|
|
|
// 形状过滤(拟合前)
|
|
|
|
|
|
float minAngularCoverage; // 最小角度覆盖范围,单位:度(默认值:10.0)
|
|
|
|
|
|
// 用于过滤非闭合边界。设置为 0 可禁用。
|
|
|
|
|
|
float maxRadiusFitRatio; // 最大半径拟合比率 radiusVariance / radius(默认值:1.0)
|
|
|
|
|
|
// 衡量边界点与圆的拟合程度。设置为 1.0 可禁用。
|
|
|
|
|
|
float minQualityScore; // 最小整体质量分数(默认值:0.0)
|
|
|
|
|
|
// 形状指标的加权组合。设置为 0 可禁用。
|
|
|
|
|
|
|
|
|
|
|
|
// 平面一致性过滤(投影前)
|
|
|
|
|
|
float maxPlaneResidual; // 最大点到平面残差,单位:mm(默认值:10.0)
|
|
|
|
|
|
// 用于拒绝非平面簇,例如悬崖、台阶边缘。
|
|
|
|
|
|
float maxAngularGap; // 最大角度间隙,单位:度(默认值:90.0)
|
|
|
|
|
|
// 用于拒绝 L 型或非闭合边界。
|
|
|
|
|
|
float minInlierRatio; // 圆拟合的最小内点比率(默认值:0.0)
|
|
|
|
|
|
// 表示落在拟合圆容差范围内的点所占比例。
|
|
|
|
|
|
|
2026-04-01 01:05:40 +08:00
|
|
|
|
// 深度验证
|
|
|
|
|
|
float minHoleDepth; // 圆孔内部最大 Z 与参考平面 Z 的最小差值,单位:mm(默认值:2.5)
|
|
|
|
|
|
// 若差值小于此阈值则认为是假孔,返回失败。<=0 表示不过滤。
|
|
|
|
|
|
|
2026-03-24 21:27:48 +08:00
|
|
|
|
// 构造函数,设置默认值
|
|
|
|
|
|
SHoleFilterParams()
|
|
|
|
|
|
: maxEccentricity(0.99995f)
|
|
|
|
|
|
, minAngularCoverage(10.f)
|
|
|
|
|
|
, maxRadiusFitRatio(1.f)
|
|
|
|
|
|
, minQualityScore(0.f)
|
|
|
|
|
|
, maxPlaneResidual(10.0f)
|
|
|
|
|
|
, maxAngularGap(90.0f)
|
|
|
|
|
|
, minInlierRatio(0.f)
|
2026-04-01 01:05:40 +08:00
|
|
|
|
, minHoleDepth(2.5f)
|
2026-03-24 21:27:48 +08:00
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 单个孔洞检测结果
|
|
|
|
|
|
*
|
|
|
|
|
|
* 注意:SVzNL3DPointF 和 SVzNL2DPointF 在 VZNL_Types.h 中定义。
|
|
|
|
|
|
*/
|
|
|
|
|
|
struct SHoleResult {
|
|
|
|
|
|
SVzNL3DPointF center; // 孔洞中心点 (x, y, z)
|
|
|
|
|
|
SVzNL3DPointF normal; // 拟合平面法向量(单位长度)
|
|
|
|
|
|
float radius; // 孔洞半径,单位:mm
|
|
|
|
|
|
float depth; // 凹坑深度,单位:mm
|
|
|
|
|
|
float eccentricity; // 离心率(0 表示完美圆形)
|
|
|
|
|
|
float radiusVariance; // 半径离散度,单位:mm
|
|
|
|
|
|
float angularSpan; // 角度覆盖范围,单位:度
|
|
|
|
|
|
float qualityScore; // 质量分数(0~1,越高越好)
|
|
|
|
|
|
|
|
|
|
|
|
SHoleResult()
|
|
|
|
|
|
: center()
|
|
|
|
|
|
, normal()
|
|
|
|
|
|
, radius(0.0f)
|
|
|
|
|
|
, depth(0.0f)
|
|
|
|
|
|
, eccentricity(0.0f)
|
|
|
|
|
|
, radiusVariance(0.0f)
|
|
|
|
|
|
, angularSpan(0.0f)
|
|
|
|
|
|
, qualityScore(0.0f)
|
|
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 多孔洞检测结果
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note 内存管理:holes 数组不会自动释放。
|
|
|
|
|
|
* 调用者必须调用 FreeMultiHoleResult() 或手动 delete[] holes。
|
|
|
|
|
|
*/
|
|
|
|
|
|
struct SMultiHoleResult {
|
|
|
|
|
|
int holeCount; // 检测到的孔洞数量
|
|
|
|
|
|
SHoleResult* holes; // 孔洞结果数组(调用者必须释放)
|
|
|
|
|
|
int totalCandidates; // 过滤前的候选孔洞总数
|
|
|
|
|
|
int filteredCount; // 被过滤掉的孔洞数量
|
|
|
|
|
|
|
|
|
|
|
|
SMultiHoleResult()
|
|
|
|
|
|
: holeCount(0)
|
|
|
|
|
|
, holes(nullptr)
|
|
|
|
|
|
, totalCandidates(0)
|
|
|
|
|
|
, filteredCount(0)
|
|
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 释放 DetectMultipleHoles 分配的内存
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param [in,out] result 要释放的结果结构
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline void FreeMultiHoleResult(SMultiHoleResult* result) {
|
|
|
|
|
|
if (result != nullptr && result->holes != nullptr) {
|
|
|
|
|
|
delete[] result->holes;
|
|
|
|
|
|
result->holes = nullptr;
|
|
|
|
|
|
result->holeCount = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 线段端点对结果
|
|
|
|
|
|
*
|
|
|
|
|
|
* 表示在线扫描中检测到的一段特征,包含起点和终点。
|
|
|
|
|
|
* 可用于描述凹坑边界、空洞间隙等一维特征。
|
|
|
|
|
|
*/
|
|
|
|
|
|
struct SSegmentPair {
|
|
|
|
|
|
SVzNLPointXYZ startPoint; // 线段起点
|
|
|
|
|
|
SVzNLPointXYZ endPoint; // 线段终点
|
|
|
|
|
|
int startRow; // 起点行索引
|
|
|
|
|
|
int startCol; // 起点列索引
|
|
|
|
|
|
int endRow; // 终点行索引
|
|
|
|
|
|
int endCol; // 终点列索引
|
|
|
|
|
|
float depth; // 起点和终点之间的深度差
|
|
|
|
|
|
|
|
|
|
|
|
SSegmentPair()
|
|
|
|
|
|
: startPoint()
|
|
|
|
|
|
, endPoint()
|
|
|
|
|
|
, startRow(0)
|
|
|
|
|
|
, startCol(0)
|
|
|
|
|
|
, endRow(0)
|
|
|
|
|
|
, endCol(0)
|
|
|
|
|
|
, depth(0.0f)
|
|
|
|
|
|
{}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // HOLE_DETECTION_PARAMS_H
|