algoLib/sourceCode/sieveNodeDetection.cpp
2025-06-08 10:46:41 +08:00

165 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <vector>
#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
#include "SG_sieveNodeDetection_Export.h"
#include <opencv2/opencv.hpp>
#include <limits>
void sg_lineDataR(SVzNL3DLaserLine* a_line,
const double* camPoseR,
double groundH)
{
lineDataRT(a_line, camPoseR, groundH);
}
//扫描线处理,进行垂直方向的特征提取和生长
void sg_sieveNodeDetection_lineProc(
SVzNL3DLaserLine* a_line,
int lineIdx,
int* errCode,
std::vector<std::vector< SSG_featureSemiCircle>>& all_vLineFeatures,
std::vector<std::vector<int>>& noisePts,
const SSG_sieveNodeDetectionParam sieveDetectParam)
{
std::vector< SSG_featureSemiCircle> a_line_features;
//滤波,滤除异常点
std::vector<SVzNL3DPosition> filterData;
std::vector<int> lineNoisePts;
sg_lineDataRemoveOutlier(a_line->p3DPosition, a_line->nPositionCnt, sieveDetectParam.filterParam, filterData, lineNoisePts);
noisePts.push_back(lineNoisePts);
sg_getLineUpperSemiCircleFeature(
filterData.data(),
filterData.size(),
lineIdx,
sieveDetectParam.sieveDiameter,
sieveDetectParam.slopeParam,
a_line_features);
all_vLineFeatures.push_back(a_line_features); //空行也加入,保证能按行号索引
return;
}
int _checkFeatureSplit(
SSG_featureSemiCircle& a_feaurue,
std::vector< SSG_featureSemiCircle>& chk_line_feature,
double splitMaxDist) //在此距离内为有效分叉
{
int split = -1;
for (int i = 0, i_max = chk_line_feature.size(); i < i_max; i++)
{
if (i < i_max - 1)
{
if ((chk_line_feature[i].midY < a_feaurue.midY) && (chk_line_feature[i + 1].midY > a_feaurue.midY))
{
double dist_1 = abs(chk_line_feature[i].midY - a_feaurue.midY);
double dist_2 = abs(chk_line_feature[i+1].midY - a_feaurue.midY);
if ((dist_1 < splitMaxDist) && (dist_2 < splitMaxDist))
{
split = i;
break;
}
}
}
}
return split;
}
void sg_getSieveNodes(
SVzNL3DLaserLine* laser3DPoints,
int lineNum,
const SSG_sieveNodeDetectionParam sieveDetectParam,
std::vector<SVzNL3DPoint>& nodePos)
{
int errCode = 0;
std::vector<std::vector<int>> noisePts;
std::vector<std::vector< SSG_featureSemiCircle>> all_vLineFeatures;
for (int i = 0; i < lineNum; i++)
{
if (i == 19)
int kkk = 1;
//将nPointIdx转义使用前清零
for (int j = 0; j < laser3DPoints[i].nPositionCnt; j++)
laser3DPoints[i].p3DPosition[j].nPointIdx = 0;
//行处理
sg_sieveNodeDetection_lineProc(
&laser3DPoints[i],
i,
&errCode,
all_vLineFeatures,
noisePts,
sieveDetectParam);
}
//根据筛网的特点去除无效的feature。当上下两个feature在下一条扫描线被合并成一个feature时说明上一条扫描线的两个feature是无效feature。其相邻的feature均为无效feature
for (int i = 0; i < lineNum; i++)
{
//与前一条扫描线比较,寻找开始
std::vector< SSG_featureSemiCircle>& line_features = all_vLineFeatures[i];
if (i > 0)
{
std::vector< SSG_featureSemiCircle>& pre_line_features = all_vLineFeatures[i-1];
for (int j = 0, j_max = line_features.size(); j < j_max; j++)
{
int split = _checkFeatureSplit(line_features[j], pre_line_features, sieveDetectParam.sieveHoleSize);
if (split >= 0)
{
pre_line_features[split].flag = FEATURE_FLAG_INVLD_END;
pre_line_features[split + 1].flag = FEATURE_FLAG_INVLD_END;
line_features[j].flag = FEATURE_FLAG_VALID_START;
}
}
}
//与后一条扫描线比较,寻找结束
if (i < lineNum - 1)
{
std::vector< SSG_featureSemiCircle>& post_line_features = all_vLineFeatures[i + 1];
for (int j = 0, j_max = line_features.size(); j < j_max; j++)
{
int split = _checkFeatureSplit(line_features[j], post_line_features, sieveDetectParam.sieveHoleSize);
if (split >= 0)
{
post_line_features[split].flag = FEATURE_FLAG_INVLD_START;
post_line_features[split + 1].flag = FEATURE_FLAG_INVLD_START;
line_features[j].flag = FEATURE_FLAG_VALID_END;
}
}
}
}
//feature生长。碰到无效feature生长停止。无效生长可以作为生长起点。其生长树上的所有feature均为无效feature
sg_getFeatureGrowingTrees_semiCircle(
lineFeatures,
trees,
growParam);
#if _OUTPUT_LINE_PROC_RESULT
//输出扫描线处理结果
for (int i = 0, i_max = all_vLineFeatures.size(); i < i_max; i++)
{
std::vector< SSG_featureSemiCircle>& a_line_features = all_vLineFeatures[i];
for (int j = 0, j_max = a_line_features.size(); j < j_max; j++)
{
SSG_featureSemiCircle& a_feature = a_line_features[j];
for (int m = a_feature.startPtIdx; m <= a_feature.endPtIdx; m++)
laser3DPoints[i].p3DPosition[m].nPointIdx = 1; //此处nPointIdx转义
laser3DPoints[i].p3DPosition[a_feature.midPtIdx].nPointIdx = 2;
}
}
#endif
}
//计算一个平面调平参数。
//以数据输入中ROI以内的点进行平面拟合计算调平参数
//旋转矩阵为调平参数,即将平面法向调整为垂直向量的参数
SSG_planeCalibPara sg_getSieveBaseCalibPara(
SVzNL3DLaserLine* laser3DPoints,
int lineNum,
std::vector<SVzNL3DRangeD>& ROIs)
{
return sg_getPlaneCalibPara_ROIs(laser3DPoints, lineNum, ROIs);
}