// count.h - 计数模式(count)核心算法与文件保存 #ifndef COUNT_H #define COUNT_H #include #include #include #include "common.h" // 点云级稀疏拖影过滤:删除每圈边缘外脱离主体的稀疏外伸点(胡须状拖影), // 使 pcd/图片/面积统计都基于干净点云。判据见 cfg.filter.sparse_cut。 // 原地修改 points;返回删除点数。应在 z_gap_interpolate 之前调用。 int sparse_density_filter(std::vector& points); // 点集 → X-Z平面白底图像(0=白,255=黑点) + 换算面积。 // 宽: cfg.filter.polygon 多边形X跨度(1mm=1px); 高: z最大值(1单位=1px); // 点先按1x1网格标记再膨胀 cfg.count.point_dilate×cfg.count.point_dilate。 // area_out 返回换算实际面积(mm^2); out_w/out_h 返回实际图像尺寸。 std::vector points_to_image(const std::vector& points, double* area_out = nullptr, int* out_w = nullptr, int* out_h = nullptr); // z轴空隙插值:雷达断流/瞬间丢包导致的 z 空白带,仅在停止采集后调用一次。 // 原理:同一圈(scan包)点 z 相同,正常圈间隔≈normal_gap; // gap>2×normal_gap 且相邻两圈 Y均值差≤30mm 且 X 在相邻圈范围内时,空隙内补行。 // cfg.count.z_interpolate_mode: none/CopyTranslation/AngleBucketInterpolation(最多补10行)。 // 会原地修改 points(新增点追加到末尾);返回新增点数。 int z_gap_interpolate(std::vector& points); // KDE 密度峰值:对一组高度值做高斯核密度估计,返回密度最大处(最密)的高度。 // bandwidth<=0 时按 Silverman 经验法则自动定带宽;step 为密度曲线扫描步长(mm)。 double kde_peak_height(const std::vector& vals, double bandwidth, double step); // 按层统计物品总数(参照Java):高度=cfg.count.floor_height-Y;层数算法由 cfg.count.layer_algorithm 决定: // LevelTolerance(默认): level=round(高度/层高); 判定 |高度-level×层高| <= 容差 // HalfMax: 两步判定 ①粗筛[(level-0.5)层高,(level+0.5)层高] ②取①内最高点top, 有效区间=[top-容差, top] // KdePeak: 两步判定 ①同HalfMax粗筛 ②①内高度做KDE取峰值peak, 有效区间=[peak-容差, peak+容差] // 容差 = cfg.count.base_tolerance + layer号×cfg.count.per_level_tolerance // 从最高层(5)往下找有效层,个数=min(round(面积/(行*宽)), maxPerLayer), // 结果 = maxPerLayer*(层号-1)+该层个数。 // 返回总个数;不足一个完整箱时返回0。 int calc_item_count(const std::vector& points, const CountParams& box, std::string* detail = nullptr, // 每层点数/高度范围/面积详情 std::vector* top_layer_img = nullptr, // 被计数层(最高有效层)图像 int* top_layer_img_w = nullptr, int* top_layer_img_h = nullptr, int* top_layer_level = nullptr, double* top_layer_area = nullptr); // 将一次 count 结果保存到任务目录 make_task_dir(task_id)(后台线程异步执行,不阻塞响应): // count_data.pcd (Y已换成高度 = cfg.count.floor_height - y_mm) // count_points.jpg (全部点 X-Z 平面图) // count_layer.jpg (被计数层图像, 有有效层时) // log.txt (cfg.log.enable 开启时) void save_count_files_async(const std::vector& points, const std::vector& top_layer_img, int top_img_w, int top_img_h, const CountParams& params, const std::string& layer_detail, int total, int top_lv, double top_area); #endif // COUNT_H