rodAndBarDetection version 1.3.6 :

新的定位盘中心测量功能:优化聚类前的垂直点去除算法,保证聚类结果正确
This commit is contained in:
jerryzeng 2026-06-06 23:02:06 +08:00
parent 5d95855e2a
commit a442445560
3 changed files with 88 additions and 113 deletions

View File

@ -302,12 +302,12 @@ SG_APISHARED_EXPORT void wd_getLineCorerFeature(
/// <summary>
/// 提取激光线上的与XY平面垂直的特征垂直段
/// </summary>
SG_APISHARED_EXPORT void wd_getXYVertialFeature_peakCornerMethod(
SG_APISHARED_EXPORT void wd_getXYVertialFeature_dirAngleMethod(
std::vector< SVzNL3DPosition>& lineData,
int lineIdx,
const double peakChkWin,
const SSG_cornerParam cornerPara,
std::vector<SSG_RUN>& xyVerticalSegs //环
std::vector<int>& xyVerticalFlags //环
);
/// 提取激光线上的拐点特征。是在PSM LVTypeFeature, BQ等拐点算法的基础上的版本。
@ -795,9 +795,9 @@ SG_APISHARED_EXPORT Plane robustFitPlane(
SG_APISHARED_EXPORT Plane ransacFitPlane(
const std::vector<cv::Point3d>& points,
std::vector<cv::Point3d>& out_inliers,
float dist_thresh = 0.5f, // 内点距离阈值
float dist_thresh = 0.3f, // 内点距离阈值
int max_iter = 1000, // 最大迭代
int stop_no_improve = 150 // 连续多少次无提升就提前退出
int stop_no_improve = 250 // 连续多少次无提升就提前退出
);
//计算一个平面调平参数。

View File

@ -5713,109 +5713,33 @@ void wd_getLineCorerFeature(
/// 4判断拐角是否为跳变
///
/// </summary>
void wd_getXYVertialFeature_peakCornerMethod(
void wd_getXYVertialFeature_dirAngleMethod(
std::vector< SVzNL3DPosition>& lineData,
int lineIdx,
const double peakChkWin,
const SSG_cornerParam cornerPara,
std::vector<SSG_RUN>& xyVerticalSegs
std::vector<int>& xyVerticalFlags
)
{
double arcPerPointCornerMinValue = 5; //arc上每个点的转角最小值
double arcTotalCornerMinValue = 30; //整个Arc的转角最小值
if (lineIdx == 1062)
int kkk = 1;
double minVerticalAngle = 75.0; //arcÉÏÿ¸öµãµÄת½Ç×îСֵ
xyVerticalFlags.resize(lineData.size());
//计算前向角和后向角
std::vector< SSG_pntDirAngle> ptDirAngles;
wd_computeDirAngle_wholeLine(lineData, cornerPara, ptDirAngles);
double cornerMergeScale = cornerPara.scale;
//提取backwardAngle极值较早实现函数可以使用此函数进行代码优化
std::vector< SSG_pntDirAngle> backwardAnglePeakP;
std::vector< SSG_pntDirAngle> backwardAnglePeakM;
wd_searchBackwardAnglePeaks(
ptDirAngles,
lineData,
cornerPara.cornerTh,
cornerMergeScale,
backwardAnglePeakP,
backwardAnglePeakM
);
//提取forwardAngle极值较早实现函数可以使用此函数进行代码优化
std::vector< SSG_pntDirAngle> forwardAnglePeakP;
std::vector< SSG_pntDirAngle> forwardAnglePeakM;
wd_searchForwardAnglePeaks(
ptDirAngles,
lineData,
cornerPara.cornerTh,
cornerMergeScale,
forwardAnglePeakP,
forwardAnglePeakM
);
//匹配forwardAnglePeakM和backwardAnglePeakM, forwardAnglePeakM在前backwardAnglePeakM在后
for (int i = 0; i < (int)forwardAnglePeakM.size(); i++)
for (int i = 0; i < (int)ptDirAngles.size(); i++)
{
for (int j = 0; j < (int)backwardAnglePeakM.size(); j++)
{
if (backwardAnglePeakM[j].pntIdx > forwardAnglePeakM[i].pntIdx)
{
int pntIdx_1 = forwardAnglePeakM[i].pntIdx;
int pntIdx_2 = backwardAnglePeakM[j].pntIdx;
//计算两者的角度
double diffY = abs(lineData[pntIdx_2].pt3D.y - lineData[pntIdx_1].pt3D.y);
if (diffY < cornerMergeScale)
{
double tanValue = (lineData[pntIdx_2].pt3D.z - lineData[pntIdx_1].pt3D.z) / diffY;
double angle = atan(tanValue) * 180.0 / PI;
if (abs(angle) > cornerPara.cornerTh)
{
SSG_RUN a_seg;
if(lineData[pntIdx_1].pt3D.z < lineData[pntIdx_2].pt3D.z)
a_seg.value = 1;
else
a_seg.value = -1;
a_seg.start = pntIdx_1;
a_seg.len = pntIdx_2 - pntIdx_1 +1;
xyVerticalSegs.push_back(a_seg);
}
}
break;
}
}
}
if (ptDirAngles[i].type < 0)
continue;
//匹配forwardAnglePeakP和backwardAnglePeakP, forwardAnglePeakP在前backwardAnglePeakP在后
for (int i = 0; i < (int)forwardAnglePeakP.size(); i++)
{
for (int j = 0; j < (int)backwardAnglePeakP.size(); j++)
{
if (backwardAnglePeakP[j].pntIdx > forwardAnglePeakP[i].pntIdx)
{
int pntIdx_1 = forwardAnglePeakP[i].pntIdx;
int pntIdx_2 = backwardAnglePeakP[j].pntIdx;
//计算两者的角度
double diffY = abs(lineData[pntIdx_2].pt3D.y - lineData[pntIdx_1].pt3D.y);
if (diffY < cornerMergeScale)
{
double tanValue = (lineData[pntIdx_2].pt3D.z - lineData[pntIdx_1].pt3D.z) / diffY;
double angle = atan(tanValue) * 180.0 / PI;
if (abs(angle) > cornerPara.cornerTh)
{
SSG_RUN a_seg;
if (lineData[pntIdx_1].pt3D.z < lineData[pntIdx_2].pt3D.z)
a_seg.value = 1;
else
a_seg.value = -1;
a_seg.start = pntIdx_1;
a_seg.len = pntIdx_2 - pntIdx_1 + 1;
xyVerticalSegs.push_back(a_seg);
}
}
break;
}
}
if (((ptDirAngles[i].backwardAngle < -minVerticalAngle) && (ptDirAngles[i].forwardAngle < -minVerticalAngle)) ||
((ptDirAngles[i].backwardAngle > minVerticalAngle) && (ptDirAngles[i].forwardAngle > minVerticalAngle)))
xyVerticalFlags[i] = 1;
}
return;
}
/// 提取激光线上的拐点特征。是在PSM LVTypeFeature, BQ等拐点算法的基础上的版本。

View File

@ -26,7 +26,8 @@
//version 1.3.3 : 筑裕钢筋焊缝提取算法改进中间版本
//version 1.3.4 : 新的定位盘中心测量功能算法优化
//version 1.3.5 : 新的定位盘中心测量功能占将float运算改成double ,测试PC和3588差异
std::string m_strVersion = "1.3.5";
//version 1.3.6 : 新的定位盘中心测量功能:优化聚类前的垂直点去除算法,保证聚类结果正确
std::string m_strVersion = "1.3.6";
const char* wd_rodAndBarDetectionVersion(void)
{
return m_strVersion.c_str();
@ -2031,51 +2032,101 @@ SSX_platePoseInfo sx_getLocationPlatePose_new(
flags[i].resize(linePtNum);
std::fill(flags[i].begin(), flags[i].end(), 0);
}
std::vector<std::vector<SSG_RUN>> zVertivalSegs;
std::vector<std::vector<int>> zVertivalFlags;
for (int line = 0; line < lineNum; line++)
{
if (line == 700)
int kkk = 1;
std::vector<SSG_RUN> line_verticalSegs;
wd_getXYVertialFeature_peakCornerMethod(
std::vector<int> line_verticalFlags;
wd_getXYVertialFeature_dirAngleMethod(
scanLines[line],
line,
cornerPara.scale,
cornerPara,
line_verticalSegs
line_verticalFlags
);
zVertivalSegs.push_back(line_verticalSegs);
zVertivalFlags.push_back(line_verticalFlags);
for (int i = 0; i < (int)line_verticalSegs.size(); i++)
for (int i = 0; i < (int)line_verticalFlags.size(); i++)
{
int idx_0 = line_verticalSegs[i].start;
for (int j = 0; j < line_verticalSegs[i].len; j++)
flags[line][idx_0 + j] = 1;
if(line_verticalFlags[i] > 0)
flags[line][i] = 1;
}
}
std::vector<std::vector<SSG_RUN>> zVertivalSegs_h;
std::vector<std::vector<int>> zVertivalFlags_h;
for (int line = 0; line < linePtNum; line++)
{
if (line == 1177)
int kkk = 1;
std::vector<SSG_RUN> line_verticalSegs;
wd_getXYVertialFeature_peakCornerMethod(
std::vector<int> line_verticalFlags;
wd_getXYVertialFeature_dirAngleMethod(
scanLines_h[line],
line,
cornerPara.scale,
cornerPara,
line_verticalSegs
line_verticalFlags
);
zVertivalSegs_h.push_back(line_verticalSegs);
zVertivalFlags_h.push_back(line_verticalFlags);
for (int i = 0; i < (int)line_verticalSegs.size(); i++)
for (int i = 0; i < (int)line_verticalFlags.size(); i++)
{
int idx_0 = line_verticalSegs[i].start;
for (int j = 0; j < line_verticalSegs[i].len; j++)
flags[idx_0 + j][line] = 1;
if(line_verticalFlags[i] > 0)
flags[i][line] = 1;
}
}
for (int line = 0; line < lineNum; line++)
{
for (int j = 0; j < linePtNum; j++)
{
if (flags[line][j] > 0)
{
scanLines[line][j].pt3D.z = 0;
scanLines_h[j][line].pt3D.z = 0;
}
}
}
//迭代一次
SSG_lineSegParam lineSegPara;
lineSegPara.distScale = 5.0;
lineSegPara.segGapTh_y = 5.0;
lineSegPara.segGapTh_z = 5.0;
const int minSegLen = 5;
for (int line = 0; line < lineNum; line++)
{
std::vector<SSG_RUN> segs;
wd_getLineDataIntervals(
scanLines[line],
lineSegPara,
segs);
for (int i = 0; i < (int)segs.size(); i++)
{
if (segs[i].len <= minSegLen)
{
int idx0 = segs[i].start;
for (int j = 0; j < segs[i].len; j++)
flags[line][idx0 + j] = 1;
}
}
}
for (int line = 0; line < linePtNum; line++)
{
std::vector<SSG_RUN> segs;
wd_getLineDataIntervals(
scanLines_h[line],
lineSegPara,
segs);
for (int i = 0; i < (int)segs.size(); i++)
{
if (segs[i].len <= minSegLen)
{
int idx0 = segs[i].start;
for (int j = 0; j < segs[i].len; j++)
flags[idx0 + j][line] = 1;
}
}
}
//标注
for (int line = 0; line < lineNum; line++)
{