You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
3.9 KiB
C

2 months ago
// count.h - 计数模式(count)核心算法与文件保存
#ifndef COUNT_H
#define COUNT_H
#include <string>
#include <vector>
#include <cstdint>
#include "common.h"
// 点云级稀疏拖影过滤:删除每圈边缘外脱离主体的稀疏外伸点(胡须状拖影),
// 使 pcd/图片/面积统计都基于干净点云。判据见 cfg.filter.sparse_cut。
// 原地修改 points;返回删除点数。应在 z_gap_interpolate 之前调用。
int sparse_density_filter(std::vector<CountPoint>& points);
2 months ago
// 点集 → X-Z平面白底图像(0=白,255=黑点) + 换算面积。
// 宽: cfg.filter.polygon 多边形X跨度(1mm=1px); 高: z最大值(1单位=1px);
// 点先按1x1网格标记再膨胀 cfg.count.point_dilate×cfg.count.point_dilate。
2 months ago
// area_out 返回换算实际面积(mm^2); out_w/out_h 返回实际图像尺寸。
std::vector<uint8_t> points_to_image(const std::vector<CountPoint>& 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行)。
2 months ago
// 会原地修改 points(新增点追加到末尾);返回新增点数。
int z_gap_interpolate(std::vector<CountPoint>& points);
// KDE 密度峰值:对一组高度值做高斯核密度估计,返回密度最大处(最密)的高度。
// bandwidth<=0 时按 Silverman 经验法则自动定带宽;step 为密度曲线扫描步长(mm)。
double kde_peak_height(const std::vector<double>& 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
2 months ago
// 从最高层(5)往下找有效层,个数=min(round(面积/(行*宽)), maxPerLayer),
// 结果 = maxPerLayer*(层号-1)+该层个数。
// 返回总个数;不足一个完整箱时返回0。
int calc_item_count(const std::vector<CountPoint>& points, const CountParams& box,
std::string* detail = nullptr, // 每层点数/高度范围/面积详情
std::vector<uint8_t>* 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)
2 months ago
// count_points.jpg (全部点 X-Z 平面图)
// count_layer.jpg (被计数层图像, 有有效层时)
// log.txt (cfg.log.enable 开启时)
2 months ago
void save_count_files_async(const std::vector<CountPoint>& points,
const std::vector<uint8_t>& 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