GrabBag/App/BeltTearing/BeltTearingServer/beltTearingDetection.cpp

1284 lines
42 KiB
C++
Raw Normal View History

#include <vector>
#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
#include "beltTearingDetection_Export.h"
#include <opencv2/opencv.hpp>
#include "SG_errCode.h"
typedef struct
{
int tearID;
int vGap_num;
double vGap_depth_max;
double vGap_width_max;
double vGap_width_sum; //用于计算均值
int hGap_num;
double hGap_depth_max;
double hGap_width_max; //最大值为撕裂最宽处
double hGap_width_sum; //用于计算均值
}SSG_tearProcessInfo; //撕裂处理过程数据
double _getGapDepth(std::vector<SVzNL3DPosition>& vldPts, int start, int end)
{
double start_z = vldPts[start].pt3D.z;
double end_z = vldPts[end].pt3D.z;
double max_z = start_z;
for (int i = start+1; i <= end; i++)
{
if (max_z < vldPts[i].pt3D.z)
max_z = vldPts[i].pt3D.z;
}
double depth = max_z - (start_z + end_z) / 2;
return depth;
}
void _combineROI(SSG_ROIRectD* roi, SSG_ROIRectD* sub_roi)
{
if (roi->left > sub_roi->left)
roi->left = sub_roi->left;
if (roi->right < sub_roi->right)
roi->right = sub_roi->right;
if (roi->top > sub_roi->top)
roi->top = sub_roi->top;
if (roi->bottom < sub_roi->bottom)
roi->bottom = sub_roi->bottom;
return;
}
bool compareByStartY(const SSG_basicFeatureGap& a, const SSG_basicFeatureGap& b) {
return a.gap_start < b.gap_start;
}
//垂直扫描线处理,进行垂直方向的特征提取
//垂直扫描线点间距小于1mm使用差分公式。
void sg_bearTearing_vLineProc(
SVzNL3DLaserLine* a_line, //当前扫描线
int lineIdx, //当前扫描线序号
const SSG_beltTearingParam measureParam,
std::vector<SSG_basicFeatureGap>& vLineFeatures)
{
//double minGapW = 1.0;
//从栅格数据生成非零序列
//统计Gap
std::vector<SVzNL3DPosition> vldPts;
std::vector<SSG_RUN> gaps;
int preIdx = -1;
int vldPtSize = 0;
int gapSize = 0;
for (int i = 0; i < a_line->nPositionCnt; i++)
{
SVzNL3DPosition a_pt = a_line->p3DPosition[i];
if (a_pt.pt3D.z > 1e-4)
{
a_pt.nPointIdx = -1;
if (preIdx >= 0)
{
int gapPtNum = i - preIdx - 1;
double gapW = abs(a_pt.pt3D.y - vldPts[vldPtSize - 1].pt3D.y);
if ((gapPtNum >= 2) && (gapW > 1.0))
{
SSG_RUN a_gap = { vldPtSize-1, 2, 0};//vldGap
gaps.push_back(a_gap);
vldPts[vldPtSize - 1].nPointIdx = gapSize;
a_pt.nPointIdx = gapSize;
gapSize++;
}
}
vldPts.push_back(a_pt);
vldPtSize++;
preIdx = i;
}
}
//计算一阶差分值
std::vector<double> difference;
std::vector<int> diffBinValue;
difference.resize(vldPts.size());
diffBinValue.resize(vldPts.size());
for (int i = 1, i_max = vldPts.size(); i < i_max; i++)
{
double a_difference = (vldPts[i].pt3D.z - vldPts[i-1].pt3D.z) / (vldPts[i].pt3D.y - vldPts[i - 1].pt3D.y);
difference[i] = a_difference;
int a_binValue;
a_binValue = a_difference > measureParam.differnceBinTh ? 1 : (a_difference < -measureParam.differnceBinTh ? -1 : 0);
diffBinValue[i] = a_binValue;
if (1 == i) //第一个
{
difference[0] = a_difference;
diffBinValue[0] = a_binValue;
}
}
//检测+1序列和-1序列
std::vector< SSG_RUN> runs;
SSG_RUN a_run;
memset(&a_run, 0, sizeof(SSG_RUN));
for (int i = 1, i_max = vldPts.size(); i < i_max; i++)
{
if (0 != diffBinValue[i])
{
if (0 == a_run.value)
{
a_run.start = i;
a_run.len = 1;
a_run.value = diffBinValue[i];
}
else
{
if (a_run.value != diffBinValue[i])
{
runs.push_back(a_run);
a_run.start = i;
a_run.len = 1;
a_run.value = diffBinValue[i];
}
else
{
a_run.len++;
}
}
}
else
{
if (0 != a_run.value)
{
runs.push_back(a_run);
memset(&a_run, 0, sizeof(SSG_RUN));
}
}
}
if (0 != a_run.value) //最后一个
{
runs.push_back(a_run);
}
//配对生成特征
for (int i = 0, i_max = runs.size(); i < i_max; i++)
{
SSG_RUN a_run = runs[i];
if (0 == a_run.value)
continue;
if (i < i_max-1)
{
SSG_RUN* nxt_run = &runs[i + 1];
//检查是否可以配对
if (a_run.value != nxt_run->value)
{
//检查距离
double pos_end = vldPts[a_run.start + a_run.len - 1].pt3D.y;
double nxt_pos_start = vldPts[nxt_run->start].pt3D.y;
double dist = nxt_pos_start - pos_end;
if (dist < measureParam.extractPara.sameGapTh)
{
a_run.len = nxt_run->start + nxt_run->len - a_run.start;
nxt_run->value = 0; //invalid
}
}
}
//检查前后是否有Gap精确确定起始点
//在前后检查10个点看是否有Gap
int start = a_run.start;
int end = a_run.start + a_run.len - 1;
bool hasGap = false;
for (int m = 0; m < measureParam.extractPara.gapChkWin; m++)
{
int ptIdx = a_run.start - m;
if (ptIdx > 0)
{
double gapLen = vldPts[ptIdx].pt3D.y - vldPts[ptIdx-1].pt3D.y;
if (gapLen > measureParam.scanYScale * 2) //找到Gap
{
start = ptIdx - 1;
hasGap = true;
if (vldPts[ptIdx].nPointIdx >= 0)
gaps[vldPts[ptIdx].nPointIdx].value = 1; //invalid
if(vldPts[ptIdx - 1].nPointIdx >= 0)
gaps[vldPts[ptIdx - 1].nPointIdx].value = 1; //invalid
break;
}
}
}
int vldPtSize = vldPts.size();
for (int m = 0; m < measureParam.extractPara.gapChkWin; m++)
{
int ptIdx = a_run.start + a_run.len - 1 + m;
if (ptIdx < vldPtSize-1)
{
double gapLen = vldPts[ptIdx+1].pt3D.y - vldPts[ptIdx ].pt3D.y;
if (gapLen > measureParam.scanYScale * 2) //找到Gap
{
end = ptIdx + 1;
hasGap = true;
if (vldPts[ptIdx].nPointIdx >= 0)
gaps[vldPts[ptIdx].nPointIdx].value = 1; //invalid
if (vldPts[ptIdx + 1].nPointIdx >= 0)
gaps[vldPts[ptIdx + 1].nPointIdx].value = 1; //invalid
break;
}
}
}
if (end > start) //gap必须大于0
{
//生成特征
SSG_basicFeatureGap a_feature;
memset(&a_feature, 0, sizeof(SSG_basicFeatureGap));
a_feature.lineIdx = lineIdx;
a_feature.gap_start = vldPts[start].pt3D.y;
a_feature.gap_width = vldPts[end].pt3D.y - vldPts[start].pt3D.y;
a_feature.gapPt_0 = vldPts[start];
a_feature.gapPt_1 = vldPts[end];
double x1, x2;
if (vldPts[end].pt3D.x > vldPts[start].pt3D.x)
{
x1 = vldPts[start].pt3D.x;
x2 = vldPts[end].pt3D.x;
}
else
{
x1 = vldPts[end].pt3D.x;
x2 = vldPts[start].pt3D.x;
}
a_feature.roi = { x1, x2, vldPts[start].pt3D.y, vldPts[end].pt3D.y };
if (true == hasGap)
a_feature.gap_depth = -1; //穿透型撕裂
else
a_feature.gap_depth = _getGapDepth(vldPts, start, end);
//检查与前一个feature是否交叉或相连
if (vLineFeatures.size() > 0)
{
SSG_basicFeatureGap* pre_feature = &vLineFeatures[vLineFeatures.size() - 1];
if ((a_feature.roi.bottom > pre_feature->roi.top) && (pre_feature->roi.bottom > a_feature.roi.top)) //合并
{
//合并
pre_feature->gapPt_1 = a_feature.gapPt_1;
_combineROI(&pre_feature->roi, &a_feature.roi);
if ((a_feature.gap_depth < 0) || (pre_feature->gap_depth < 0))
pre_feature->gap_depth = -1;
else
pre_feature->gap_depth = pre_feature->gap_depth < a_feature.gap_depth ? a_feature.gap_depth : pre_feature->gap_depth;
pre_feature->gap_width = pre_feature->roi.bottom - pre_feature->roi.top;
}
else
{
double dist_y = a_feature.roi.top - pre_feature->roi.bottom;
if (dist_y < measureParam.scanYScale * 3)
{
//合并
pre_feature->gapPt_1 = a_feature.gapPt_1;
_combineROI(&pre_feature->roi, &a_feature.roi);
if ((a_feature.gap_depth < 0) || (pre_feature->gap_depth < 0))
pre_feature->gap_depth = -1;
else
pre_feature->gap_depth = pre_feature->gap_depth < a_feature.gap_depth ? a_feature.gap_depth : pre_feature->gap_depth;
pre_feature->gap_width = pre_feature->roi.bottom - pre_feature->roi.top;
}
else
vLineFeatures.push_back(a_feature);
}
}
else //if(a_gap.gap_width > minGapW) //小于minGapW的视为噪声
vLineFeatures.push_back(a_feature);
}
}
#if KEEP_GAP_AS_FEATURE
//将Gap生成feature
int gapFeatureNum = 0;
for (int i = 0, i_max = gaps.size(); i < i_max; i++)
{
SSG_RUN* a_run = &gaps[i];
if (0 == a_run->value) //valid
{
int start = a_run->start;
int end = a_run->start + a_run->len - 1;
SSG_basicFeatureGap a_gap;
memset(&a_gap, 0, sizeof(SSG_basicFeatureGap));
a_gap.lineIdx = lineIdx;
a_gap.gap_start = vldPts[start].pt3D.y;
a_gap.gap_width = vldPts[end].pt3D.y - vldPts[start].pt3D.y;
a_gap.gapPt_0 = vldPts[start];
a_gap.gapPt_1 = vldPts[end];
double x1, x2;
if (vldPts[end].pt3D.x > vldPts[start].pt3D.x)
{
x1 = vldPts[start].pt3D.x;
x2 = vldPts[end].pt3D.x;
}
else
{
x1 = vldPts[end].pt3D.x;
x2 = vldPts[start].pt3D.x;
}
a_gap.roi = { x1, x2, vldPts[start].pt3D.y, vldPts[end].pt3D.y };
a_gap.gap_depth = -1; //穿透型撕裂
vLineFeatures.push_back(a_gap);
gapFeatureNum++;
}
}
//排序
if (gapFeatureNum > 0)
{
std::sort(vLineFeatures.begin(), vLineFeatures.end(), compareByStartY);
}
#endif
return;
}
//水平扫描线处理,进行垂直方向的特征提取和生长
//水平扫描线若点间距小于1mm使用差分公式反之直接使用前后点差值计算。
void sg_bearTearing_hLineProc(
SSG_hLineProInfo* hLineProc,
int workerIdx,
int hLineIdx, //水平扫描点序号,对应垂直扫描线的线序号
SVzNL3DLaserLine** buffLines,
const SSG_beltTearingParam measureParam,
std::vector<SSG_basicFeatureGap>& hLineFeatures )
{
//注意进行处理时buffer已经满不需要考虑buffer不满的情况
//处理中间扫描线数据这样能够检测后面的跳变。整体处理延后SCAN_BUFF_SIZE / 2条扫描线
int midPos = SCAN_BUFF_SIZE / 2;
SVzNL3DPosition* procData = &(buffLines[midPos]->p3DPosition[workerIdx]);
if (procData->pt3D.z < 1e-4)
return;
if (hLineProc->preVldData.pt3D.z < 1e-4)
{
hLineProc->preVldData = *procData;
return;
}
//计算差值
double x_diff = procData->pt3D.x - hLineProc->preVldData.pt3D.x;
double a_difference;
int a_binValue;
if (x_diff > measureParam.tearingMinGap)
{
hLineProc->gapPos.nPointIdx = -1;
hLineProc->hLineSM = keSG_HLineProc_Init;
memset(&hLineProc->firstHalf, 0, sizeof(SSG_RUN));
memset(&hLineProc->firstHalf_startPt, 0, sizeof(SVzNL3DPosition));
memset(&hLineProc->firstHalf_endPt, 0, sizeof(SVzNL3DPosition));
a_difference = 0.0;
a_binValue = 0;
}
else
{
//检查Gap
if (x_diff > measureParam.scanXScale * 2) //找到Gap
{
hLineProc->gapPos = hLineProc->preVldData;
}
a_difference = procData->pt3D.z - hLineProc->preVldData.pt3D.z;
if (measureParam.scanXScale < 1.0)
a_difference = a_difference / x_diff;
a_binValue = a_difference > measureParam.differnceBinTh ? 1 : (a_difference < -measureParam.differnceBinTh ? -1 : 0);
}
switch (hLineProc->hLineSM)
{
case keSG_HLineProc_Init:
if (a_binValue != 0)
{
hLineProc->gapMaxZ = procData->pt3D.z;
hLineProc->firstHalf.start = procData->nPointIdx;
hLineProc->firstHalf.len = 1;
hLineProc->firstHalf.value = a_binValue;
hLineProc->firstHalf_startPt = *procData;
hLineProc->firstHalf_endPt = *procData;
hLineProc->hLineSM = keSG_HLineProc_First_Half;
}
break;
case keSG_HLineProc_First_Half:
if(hLineProc->gapMaxZ < procData->pt3D.z)
hLineProc->gapMaxZ = procData->pt3D.z;
if (0 == a_binValue)
{
//进行wait状态
hLineProc->hLineSM = keSG_HLineProc_Wait_Second;
}
else if (hLineProc->firstHalf.value != a_binValue)
{
hLineProc->secondHalf.start = procData->nPointIdx;
hLineProc->secondHalf.len = 1;
hLineProc->secondHalf.value = a_binValue;
hLineProc->secondHalf_startPt = *procData;
hLineProc->secondHalf_endPt = *procData;
hLineProc->hLineSM = keSG_HLineProc_Second_Half;
}
else
{
hLineProc->firstHalf.len++;
hLineProc->firstHalf_endPt = *procData;
}
break;
case keSG_HLineProc_Wait_Second:
if (hLineProc->gapMaxZ < procData->pt3D.z)
hLineProc->gapMaxZ = procData->pt3D.z;
if (0 == a_binValue)
{
double x_diff = abs(procData->pt3D.x - hLineProc->firstHalf_endPt.pt3D.x);
if (x_diff > measureParam.extractPara.sameGapTh)
{
memset(&hLineProc->firstHalf, 0, sizeof(SSG_RUN));
memset(&hLineProc->firstHalf_startPt, 0, sizeof(SVzNL3DPosition));
memset(&hLineProc->firstHalf_endPt, 0, sizeof(SVzNL3DPosition));
hLineProc->hLineSM = keSG_HLineProc_Init;
}
}
else if (hLineProc->firstHalf.value != a_binValue)
{
hLineProc->secondHalf.start = procData->nPointIdx;
hLineProc->secondHalf.len = 1;
hLineProc->secondHalf.value = a_binValue;
hLineProc->secondHalf_startPt = *procData;
hLineProc->secondHalf_endPt = *procData;
hLineProc->hLineSM = keSG_HLineProc_Second_Half;
}
else
{
if (x_diff > measureParam.extractPara.sameGapTh)
{
//firstHalf重新开始
hLineProc->firstHalf.start = procData->nPointIdx;
hLineProc->firstHalf.len = 1;
hLineProc->firstHalf.value = a_binValue;
hLineProc->firstHalf_startPt = *procData;
hLineProc->firstHalf_endPt = *procData;
}
else
{
//firstHalf的延续
hLineProc->firstHalf.len = procData->nPointIdx - hLineProc->firstHalf_startPt.nPointIdx + 1;
hLineProc->firstHalf_endPt = *procData;
}
hLineProc->hLineSM = keSG_HLineProc_First_Half;
}
break;
case keSG_HLineProc_Second_Half:
if (0 == a_binValue)
{
//匹配
//生成特征
SSG_basicFeatureGap a_gap;
memset(&a_gap, 0, sizeof(SSG_basicFeatureGap));
a_gap.lineIdx = hLineIdx;
//向前检查Gap
SVzNL3DPosition start;
int x_lineDiff = hLineProc->firstHalf_startPt.nPointIdx - hLineProc->gapPos.nPointIdx;
if ((x_lineDiff > 0) && (x_lineDiff < measureParam.extractPara.gapChkWin))
{
a_gap.gap_start = hLineProc->gapPos.pt3D.x;
start = hLineProc->gapPos;
}
else
{
a_gap.gap_start = hLineProc->firstHalf_startPt.pt3D.x;
start = hLineProc->firstHalf_startPt;
}
//向后检查Gap
bool hasPostGap = false;
SVzNL3DPosition postGap;
memset(&postGap, 0, sizeof(SVzNL3DPosition));
int chkLen = measureParam.extractPara.gapChkWin;
if (chkLen > SCAN_BUFF_SIZE / 2)
chkLen = SCAN_BUFF_SIZE / 2;
SVzNL3DPosition preData = *procData;
for (int m = 1; m <= chkLen; m++)
{
int lineIdx = midPos + m;
if (buffLines[lineIdx]->p3DPosition[workerIdx].pt3D.z < 1e-4)
continue;
double x_dff_2 = buffLines[lineIdx]->p3DPosition[workerIdx].pt3D.x - preData.pt3D.x;
if (x_dff_2 > measureParam.scanXScale * 2) //找到Gap
{
hasPostGap = true;
postGap = buffLines[lineIdx]->p3DPosition[workerIdx];
break;
}
preData = buffLines[lineIdx]->p3DPosition[workerIdx];
}
SVzNL3DPosition end;
if (true == hasPostGap)
{
end = postGap;
a_gap.gap_width = postGap.pt3D.x - a_gap.gap_start;
a_gap.gap_depth = -1;//穿透型撕裂
double y1, y2;
if (start.pt3D.y < end.pt3D.y)
{
y1 = start.pt3D.y;
y2 = end.pt3D.y;
}
else
{
y1 = end.pt3D.y;
y2 = start.pt3D.y;
}
a_gap.roi = { a_gap.gap_start, postGap.pt3D.x, y1, y2};
a_gap.gapPt_0 = start;
a_gap.gapPt_1 = end;
}
else
{
end = hLineProc->secondHalf_endPt;
a_gap.gap_width = hLineProc->secondHalf_endPt.pt3D.x - a_gap.gap_start;
a_gap.gap_depth = hLineProc->gapMaxZ - (start.pt3D.z + end.pt3D.z) / 2;
double y1, y2;
if (start.pt3D.y < end.pt3D.y)
{
y1 = start.pt3D.y;
y2 = end.pt3D.y;
}
else
{
y1 = end.pt3D.y;
y2 = start.pt3D.y;
}
a_gap.roi = { a_gap.gap_start, hLineProc->secondHalf_endPt.pt3D.x, y1, y2 };
a_gap.gapPt_0 = start;
a_gap.gapPt_1 = end;
}
hLineFeatures.push_back(a_gap);
memset(&hLineProc->firstHalf, 0, sizeof(SSG_RUN));
memset(&hLineProc->firstHalf_startPt, 0, sizeof(SVzNL3DPosition));
memset(&hLineProc->firstHalf_endPt, 0, sizeof(SVzNL3DPosition));
memset(&hLineProc->secondHalf, 0, sizeof(SSG_RUN));
memset(&hLineProc->secondHalf_startPt, 0, sizeof(SVzNL3DPosition));
memset(&hLineProc->secondHalf_endPt, 0, sizeof(SVzNL3DPosition));
hLineProc->hLineSM = keSG_HLineProc_Init;
}
else if (hLineProc->firstHalf.value != a_binValue)
{
//firstHalf延续
hLineProc->firstHalf.len = procData->nPointIdx - hLineProc->firstHalf_startPt.nPointIdx + 1;
hLineProc->firstHalf_endPt = *procData;
memset(&hLineProc->secondHalf, 0, sizeof(SSG_RUN));
memset(&hLineProc->secondHalf_startPt, 0, sizeof(SVzNL3DPosition));
memset(&hLineProc->secondHalf_endPt, 0, sizeof(SVzNL3DPosition));
hLineProc->hLineSM = keSG_HLineProc_First_Half;
}
else
{
//secondHalf继续
hLineProc->secondHalf.len++;
hLineProc->secondHalf_endPt = *procData;
}
break;
default:
break;
}
hLineProc->preVldData = *procData;
return;
}
void sg_beltTearingInit(
int linePtNum,
std::vector<SSG_hLineProInfo>& hLineWorkers )
{
hLineWorkers.resize(linePtNum);
for (int i = 0; i < linePtNum; i++)
memset(&hLineWorkers[i], 0, sizeof(SSG_hLineProInfo));
}
bool _chkTreeMatching(
SSG_basicFeatureGap* a_feature,
SSG_beltTearingInfo* a_tree,
const SSG_beltTearingParam measureParam,
double* dist_x,
double* dist_y
)
{
//此处只使用ROI来进行匹配
//计算水平方向距离
double x_dist;
if ((a_feature->roi.right >= a_tree->roi.left) && (a_tree->roi.right >= a_feature->roi.left))
x_dist = 0; //有重合区
else if (a_tree->roi.left > a_feature->roi.right)
x_dist = a_tree->roi.left - a_feature->roi.right;
else
x_dist = a_feature->roi.left - a_tree->roi.right;
//计算垂直方向距离
double y_dist;
if ((a_feature->roi.bottom >= a_tree->roi.top) && (a_tree->roi.bottom >= a_feature->roi.top))
y_dist = 0; //有重合区
else if (a_tree->roi.top > a_feature->roi.bottom)
y_dist = a_tree->roi.top - a_feature->roi.bottom;
else
y_dist = a_feature->roi.top - a_tree->roi.bottom;
*dist_x = x_dist;
*dist_y = y_dist;
if (((y_dist < measureParam.scanYScale * 3) && (x_dist < measureParam.tearingMinGap)))
//||((x_dist < measureParam.scanXScale * 3) && (y_dist < measureParam.tearingMinGap)))
return true;
return false;
}
SSG_beltTearingInfo* _findMatchTre(
SSG_basicFeatureGap* a_feature,
std::vector<SSG_beltTearingInfo>& existTrees,
const SSG_beltTearingParam measureParam)
{
for (int i = 0, i_max = existTrees.size(); i < i_max; i++)
{
SSG_beltTearingInfo* a_tree = &existTrees[i];
double x_dist, y_dist;
bool isMatching = _chkTreeMatching(
a_feature,
a_tree,
measureParam,
&x_dist,
&y_dist);
if(true == isMatching)
return a_tree;
}
return NULL;
}
void _mergeTwoTree(
SSG_beltTearingInfo* mergeTree,
SSG_beltTearingInfo* subTree
)
{
mergeTree->endLineIdx = mergeTree->endLineIdx < subTree->endLineIdx ? subTree->endLineIdx : mergeTree->endLineIdx;
#if OUTPUT_TEARING_POINTS
mergeTree->pts.insert(mergeTree->pts.end(), subTree->pts.begin(), subTree->pts.end());
#endif
_combineROI(&mergeTree->roi, &subTree->roi);
mergeTree->statLineIdx = mergeTree->statLineIdx > subTree->statLineIdx ? subTree->statLineIdx : mergeTree->statLineIdx;
mergeTree->tearDepth = mergeTree->tearDepth < subTree->tearDepth ? subTree->tearDepth : mergeTree->tearDepth;
subTree->tearStatus = keSG_tearStatus_Invalid;
return;
}
SSG_tearProcessInfo* _getProcInfo(
int tearProcInfo_IdOffset,
int tearID,
std::vector<SSG_tearProcessInfo>& tearProcInfo)
{
int index = tearID;
if (tearProcInfo_IdOffset > index)
index = INT_MAX - tearProcInfo_IdOffset + index;
else
index = index - tearProcInfo_IdOffset;
SSG_tearProcessInfo* a_procInfo = &tearProcInfo[index];
if (a_procInfo->tearID >= 0)
{
try {
if (a_procInfo->tearID != tearID)
throw std::runtime_error("撕裂的ID与撕裂处理数据的ID不匹配");
}
catch (const std::runtime_error& e) {
std::cerr << "Caught an exception: " << e.what() << std::endl;
}
}
return a_procInfo;
}
///数据输入必须是grid格式以进行水平方向和垂直方向的处理
//每条扫描线调用一次处理程序
//每条扫描线完成一次垂直扫描线处理同时N个水平状态机同时处理
//生长时通过ROI判断是否有匹配的生长树。水平Feature的生长不记录开始和结束扫描线号
void sg_detectBeltTearing(
SVzNL3DLaserLine* laser3DPoints, //一条扫描线
int inputLineIdx,
int nPointCount, //每条扫描线的点数量。当采用Grid数据格式时每条扫描线的点的数量是相同的。必须使用Grid格式
int* errCode,
std::vector<SSG_hLineProInfo>& hLineWorkers,
std::vector<SSG_beltTearingInfo>& beltTearings_new,
std::vector<SSG_beltTearingInfo>& beltTearings_growing,
std::vector<SSG_beltTearingInfo>& beltTearings_ended,
std::vector<SSG_beltTearingInfo>& beltTearings_unknown, //未判明,应用无需处理。
const SSG_beltTearingParam measureParam)
{
//算法需要建立Buff同时延时处理。
static SVzNL3DLaserLine** buffLines = (SVzNL3DLaserLine**)malloc(sizeof(SVzNL3DLaserLine*) * SCAN_BUFF_SIZE);
static int buffSize = 0;
static int tearID = 1; //因为皮带是循环运行,需要考虑无限增长
//撕裂处理过程数据。因为皮带是循环运行,因此容器不能无限增长,需要将结束的撕裂过程数据清除
static int tearProcInfo_IdOffset = 1; //id从1开始
static std::vector<SSG_tearProcessInfo> tearProcInfo;
if (NULL == laser3DPoints) //复位内部静态变量
{
buffSize = 0;
tearID = 1;
tearProcInfo_IdOffset = 1;
tearProcInfo.resize(0);
return;
}
*errCode = 0;
if (0 == laser3DPoints->nPositionCnt)
return;
if (hLineWorkers.size() != laser3DPoints->nPositionCnt) //空行
{
*errCode = SG_ERR_NOT_GRID_FORMAT;
return;
}
/* 数据缓冲FIFO。只有缓冲区满后才进行处理。 */
if (buffSize < SCAN_BUFF_SIZE) //需要申请buff空间
{
SVzNL3DLaserLine* a_buffLine = (SVzNL3DLaserLine*)malloc(sizeof(SVzNL3DLaserLine));
a_buffLine->nPositionCnt = laser3DPoints->nPositionCnt;
a_buffLine->nTimeStamp = inputLineIdx;
a_buffLine->p3DPosition = (SVzNL3DPosition*)malloc(sizeof(SVzNL3DPosition) * laser3DPoints->nPositionCnt);
memcpy(a_buffLine->p3DPosition, laser3DPoints->p3DPosition, sizeof(SVzNL3DPosition) * laser3DPoints->nPositionCnt);
for (int i = 0; i < laser3DPoints->nPositionCnt; i++)
a_buffLine->p3DPosition[i].nPointIdx = inputLineIdx; //用于水平处理时得到点对应的LineIdx
buffLines[buffSize] = a_buffLine;
buffSize++;
return; //buffer未满不处理
}
else //当Buffer已满申请的空间复用不需要再申请空间
{
SVzNL3DLaserLine* tmpLine = buffLines[0];
for (int i = 0; i < SCAN_BUFF_SIZE - 1; i++)
buffLines[i] = buffLines[i + 1];
tmpLine->nPositionCnt = laser3DPoints->nPositionCnt;
tmpLine->nTimeStamp = inputLineIdx;
memcpy(tmpLine->p3DPosition, laser3DPoints->p3DPosition, sizeof(SVzNL3DPosition) * laser3DPoints->nPositionCnt);
for (int i = 0; i < laser3DPoints->nPositionCnt; i++)
tmpLine->p3DPosition[i].nPointIdx = inputLineIdx; //用于水平处理时得到点对应的LineIdx
buffLines[SCAN_BUFF_SIZE - 1] = tmpLine;
}
/* 将已经生成的beltTearings_new合并到beltTearings_growing中并清空beltTearings_new */
if (beltTearings_new.size() > 0)
{
for (int i = 0; i < beltTearings_new.size(); i++)
beltTearings_new[i].tearStatus = keSG_tearStatus_Growing;
beltTearings_growing.insert(beltTearings_growing.end(), beltTearings_new.begin(), beltTearings_new.end());
beltTearings_new.clear();
}
/* 将beltTearings_ended清空 */
if (beltTearings_ended.size() > 0)
{
for (int i = 0, i_max = beltTearings_ended.size(); i < i_max; i++)
{
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
beltTearings_ended[i].tearID,
tearProcInfo);
match_procInfo->tearID = -1;
}
beltTearings_ended.clear();
//调整tearProcInfo
int vldStart = -1;
for (int i = 0, i_max = tearProcInfo.size(); i < i_max; i++)
{
if (tearProcInfo[i].tearID > 0)
{
vldStart = i;
break;
}
}
if (vldStart > 0)
{
tearProcInfo.erase(tearProcInfo.begin(), tearProcInfo.begin() + vldStart);
tearProcInfo_IdOffset = tearProcInfo[0].tearID;
}
}
/****************************************************************/
/**** 对BuffLines的中间进行处理延时了BuffLines的一半行数 ****/
/****************************************************************/
int buffMidPos = SCAN_BUFF_SIZE / 2;
if ( (buffLines[buffMidPos]->nTimeStamp == 422) ||(buffLines[buffMidPos]->nTimeStamp == 182))
int kkk = 1;
int procLineIdx = buffLines[buffMidPos]->nTimeStamp;
//对当前扫描线数据进行处理
std::vector<SSG_basicFeatureGap> vLineFeatures;
sg_bearTearing_vLineProc(
buffLines[buffMidPos], //当前扫描线
buffLines[buffMidPos]->nTimeStamp, //当前扫描线序号
measureParam,
vLineFeatures);
//缓冲,水平处理
std::vector<SSG_basicFeatureGap> hLineFeatures;
//hLineFeatures.resize(hLineWorkers.size());
for (int i = 0; i < laser3DPoints->nPositionCnt; i++)
{
//if ((buffLines[buffMidPos]->nTimeStamp == 295) && (i == 725))
// int kkk = 1;
//水平扫描线处理,进行垂直方向的特征提取和生长
std::vector<SSG_basicFeatureGap> a_hLineFeatures;
sg_bearTearing_hLineProc(
&hLineWorkers[i],
i,
buffLines[buffMidPos]->nTimeStamp, //水平扫描点序号,对应垂直扫描线的线序号
buffLines,
measureParam,
a_hLineFeatures);
//if (0 == a_hLineFeatures.size())
// hLineFeatures[i].lineIdx = -1;
//else
if(a_hLineFeatures.size() > 0)
{
hLineFeatures.push_back(a_hLineFeatures[0]);
//hLineFeatures[i] = a_hLineFeatures[0];
//if ((a_hLineFeatures[0].gapPt_0.pt3D.x < 10871) &&(a_hLineFeatures[0].gapPt_0.pt3D.x > 10870))
// int kkk = 1;
}
}
//垂直特征生长
//对于垂直特征生长,不能同一棵生长树对应多个特征,除非是包含关系
//当一个特征属于两个以上的生长树时,为了简化处理逻辑,不进行生长树的合并,选择最合适的生长树
if (vLineFeatures.size() > 0)
{
std::vector<SSG_intPair> feature_tree_id_pair; //注意vector取地址时在push_back操作后单元地址可能会变化使用序号
feature_tree_id_pair.resize(vLineFeatures.size()); //每个featurec对应一个matchTree
std::vector<SVzNL2DPointD> feature_tree_pair_dist;
feature_tree_pair_dist.resize(vLineFeatures.size());
for (int i = 0, i_max = vLineFeatures.size(); i < i_max; i++)
{
feature_tree_id_pair[i].data_0 = -1; //指示tree_id
feature_tree_id_pair[i].data_1 = -1; //指示group_id
for (int j = 0, j_max = beltTearings_growing.size(); j < j_max; j++)
{
double dist_x = -1, dist_y = -1;
bool isMatching = _chkTreeMatching(
&vLineFeatures[i],
&beltTearings_growing[j],
measureParam,
&dist_x,
&dist_y);
if (true == isMatching)
{
if (feature_tree_id_pair[i].data_0 < 0)
{
feature_tree_id_pair[i].data_0 = j;
feature_tree_id_pair[i].data_1 = 0;
feature_tree_pair_dist[i].x = dist_x;
feature_tree_pair_dist[i].y = dist_y;
}
else //取最近的tree。垂直特征生长使用dist_y来计算
{
if (dist_y < feature_tree_pair_dist[i].y)
{
feature_tree_id_pair[i].data_0 = j;
feature_tree_id_pair[i].data_1 = 0;
feature_tree_pair_dist[i].x = dist_x;
feature_tree_pair_dist[i].y = dist_y;
}
}
}
}
for (int j = 0, j_max = beltTearings_unknown.size(); j < j_max; j++)
{
if (keSG_tearStatus_Invalid == beltTearings_unknown[j].tearStatus)
continue;
double dist_x = -1, dist_y = -1;
bool isMatching = _chkTreeMatching(
&vLineFeatures[i],
&beltTearings_unknown[j],
measureParam,
&dist_x,
&dist_y);
if (true == isMatching)
{
if (feature_tree_id_pair[i].data_0 < 0)
{
feature_tree_id_pair[i].data_0 = j;
feature_tree_id_pair[i].data_1 = 1;
feature_tree_pair_dist[i].x = dist_x;
feature_tree_pair_dist[i].y = dist_y;
}
else //取最近的tree。垂直特征生长使用dist_y来计算
{
if (dist_y < feature_tree_pair_dist[i].y)
{
feature_tree_id_pair[i].data_0 = j;
feature_tree_id_pair[i].data_1 = 1;
feature_tree_pair_dist[i].x = dist_x;
feature_tree_pair_dist[i].y = dist_y;
}
}
}
}
}
//检查是否有同一个feature属于两个生长树的情况
for (int i = 0, i_max = vLineFeatures.size(); i < i_max; i++)
{
if (feature_tree_id_pair[i].data_0 < 0)
continue;
for (int j = i + 1; j < i_max; j++)
{
if ( (feature_tree_id_pair[i].data_0 == feature_tree_id_pair[j].data_0) &&
(feature_tree_id_pair[i].data_1 == feature_tree_id_pair[j].data_1))
{
//比较y距离
if ( (feature_tree_pair_dist[i].y < feature_tree_pair_dist[j].y) &&
(feature_tree_pair_dist[j].y > 1e-4)) //不为0
feature_tree_id_pair[j].data_0 = -1;
else if ((feature_tree_pair_dist[j].y < feature_tree_pair_dist[i].y) &&
(feature_tree_pair_dist[i].y > 1e-4)) //不为0
feature_tree_id_pair[i].data_0 = -1;
break;
}
}
}
for (int i = 0, i_max = vLineFeatures.size(); i < i_max; i++)
{
//对于垂直特征生长,不能同一棵生长树对应多个特征,除非是包含关系
SSG_basicFeatureGap* a_vFeature = &vLineFeatures[i];
if (feature_tree_id_pair[i].data_0 < 0)
{
SSG_beltTearingInfo a_newTree;
memset(&a_newTree, 0, sizeof(SSG_beltTearingInfo));
a_newTree.tearID = tearID; //
tearID++;
if (tearID == 0) //循环一圈
tearID = 1;
a_newTree.statLineIdx = procLineIdx;
a_newTree.endLineIdx = procLineIdx;
a_newTree.roi = a_vFeature->roi;
a_newTree.tearDepth = a_vFeature->gap_depth;
a_newTree.tearType = keSG_tearType_MachineDir; //纵撕
a_newTree.tearStatus = keSG_tearStatus_Uknown; //unknown
#if OUTPUT_TEARING_POINTS
a_vFeature->gapPt_0.nPointIdx = a_newTree.tearID;
a_vFeature->gapPt_1.nPointIdx = a_newTree.tearID;
a_newTree.pts.push_back(a_vFeature->gapPt_0);
a_newTree.pts.push_back(a_vFeature->gapPt_1);
#endif
beltTearings_unknown.push_back(a_newTree);
SSG_tearProcessInfo a_procInfo;
memset(&a_procInfo, 0, sizeof(SSG_tearProcessInfo));
a_procInfo.tearID = a_newTree.tearID;
a_procInfo.vGap_depth_max = a_vFeature->gap_depth;
a_procInfo.vGap_width_max = a_vFeature->gap_width;
a_procInfo.vGap_width_sum = a_vFeature->gap_width;
a_procInfo.vGap_num = 1;
tearProcInfo.push_back(a_procInfo);
}
else
{
SSG_beltTearingInfo* a_matchTree;
int tree_id = feature_tree_id_pair[i].data_0;
if(0 == feature_tree_id_pair[i].data_1)
a_matchTree = &beltTearings_growing[tree_id];
else
a_matchTree = &beltTearings_unknown[tree_id];
//取相应的procInfo
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
a_matchTree->tearID,
tearProcInfo);
if ((a_vFeature->gap_depth < 0) || (match_procInfo->vGap_depth_max < 0))
match_procInfo->vGap_depth_max = -1; //贯穿撕裂
else
match_procInfo->vGap_depth_max = match_procInfo->vGap_depth_max < a_vFeature->gap_depth ? a_vFeature->gap_depth : match_procInfo->vGap_depth_max;
match_procInfo->vGap_width_max = match_procInfo->vGap_width_max < a_vFeature->gap_width ? a_vFeature->gap_width : match_procInfo->vGap_width_max;
match_procInfo->vGap_width_sum += a_vFeature->gap_width;
match_procInfo->vGap_num++;
#if OUTPUT_TEARING_POINTS
a_vFeature->gapPt_0.nPointIdx = a_matchTree->tearID;
a_vFeature->gapPt_1.nPointIdx = a_matchTree->tearID;
a_matchTree->pts.push_back(a_vFeature->gapPt_0);
a_matchTree->pts.push_back(a_vFeature->gapPt_1);
#endif
//
a_matchTree->endLineIdx = procLineIdx;
_combineROI(&a_matchTree->roi, &a_vFeature->roi);
if (keSG_tearType_MachineDir == a_matchTree->tearType)
{
a_matchTree->tearWidth = match_procInfo->vGap_width_max;
a_matchTree->tearDepth = match_procInfo->vGap_depth_max;
}
}
}
}
#if ENABLE_CROSS_WISE_TEAR
//水平特征生长
if (hLineFeatures.size() > 0)
{
std::vector<SSG_intPair> hFeature_tree_id_pair; //注意vector取地址时在push_back操作后单元地址可能会变化使用序号
hFeature_tree_id_pair.resize(hLineFeatures.size()); //每个featurec对应一个matchTree
std::vector<SVzNL2DPointD> hFeature_tree_pair_dist;
hFeature_tree_pair_dist.resize(hLineFeatures.size());
for(int i = 0, i_max = hLineFeatures.size(); i < i_max; i++)
{
hFeature_tree_id_pair[i].data_0 = -1; //指示tree_id
hFeature_tree_id_pair[i].data_1 = -1; //指示group_id
//对于beltTearings_unknown当纵撕不允许 横撕允许,且合并
for (int j = 0, j_max = beltTearings_unknown.size(); j < j_max; j++)
{
if (keSG_tearStatus_Invalid == beltTearings_unknown[j].tearStatus)
continue;
double dist_x = -1, dist_y = -1;
bool isMatching = _chkTreeMatching(
&hLineFeatures[i],
&beltTearings_unknown[j],
measureParam,
&dist_x,
&dist_y);
if (true == isMatching)
{
if (hFeature_tree_id_pair[i].data_0 < 0)
{
hFeature_tree_id_pair[i].data_0 = j;
hFeature_tree_id_pair[i].data_1 = 1; //1:beltTearings_unknown
hFeature_tree_pair_dist[i].x = dist_x;
hFeature_tree_pair_dist[i].y = dist_y;
}
else //检查合并。
{
int mergeTreeIdx = hFeature_tree_id_pair[i].data_0;
_mergeTwoTree(&beltTearings_unknown[mergeTreeIdx],&beltTearings_unknown[j]);
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
beltTearings_unknown[j].tearID,
tearProcInfo);
match_procInfo->tearID = -1; //被合并的处理块置无效
}
}
}
for (int j = 0, j_max = beltTearings_growing.size(); j < j_max; j++)
{
double dist_x = -1, dist_y = -1;
bool isMatching = _chkTreeMatching(
&hLineFeatures[i],
&beltTearings_growing[j],
measureParam,
&dist_x,
&dist_y);
if (true == isMatching)
{
if (hFeature_tree_id_pair[i].data_0 < 0)
{
hFeature_tree_id_pair[i].data_0 = j;
hFeature_tree_id_pair[i].data_1 = 0; //0 : beltTearings_growing
hFeature_tree_pair_dist[i].x = dist_x;
hFeature_tree_pair_dist[i].y = dist_y;
}
else
{
#if 0
//取最近的tree。水平特征生长也使用dist_y来计算。
if (dist_y < hFeature_tree_pair_dist[i].y)
{
hFeature_tree_id_pair[i].data_0 = j;
hFeature_tree_id_pair[i].data_1 = 0;
hFeature_tree_pair_dist[i].x = dist_x;
hFeature_tree_pair_dist[i].y = dist_y;
}
#else
//beltTearings_growing为正在生长的树优先。
hFeature_tree_id_pair[i].data_0 = j;
hFeature_tree_id_pair[i].data_1 = 0;
hFeature_tree_pair_dist[i].x = dist_x;
hFeature_tree_pair_dist[i].y = dist_y;
#endif
}
}
}
}
for (int i = 0, i_max = hLineFeatures.size(); i < i_max; i++)
{
SSG_basicFeatureGap* a_hFeature = &hLineFeatures[i];
if (a_hFeature->lineIdx < 0)
continue;
if (hFeature_tree_id_pair[i].data_0 < 0)
{
SSG_beltTearingInfo a_newTree;
memset(&a_newTree, 0, sizeof(SSG_beltTearingInfo));
a_newTree.tearID = tearID; //
tearID++;
if (tearID == 0) //循环一圈
tearID = 1;
a_newTree.statLineIdx = procLineIdx;
a_newTree.endLineIdx = procLineIdx;
a_newTree.roi = a_hFeature->roi;
a_newTree.tearDepth = a_hFeature->gap_depth;
a_newTree.tearType = keSG_tearType_CrossWise; //横撕
a_newTree.tearStatus = keSG_tearStatus_Uknown; //unknown
#if OUTPUT_TEARING_POINTS
a_hFeature->gapPt_0.nPointIdx = a_newTree.tearID;
a_hFeature->gapPt_1.nPointIdx = a_newTree.tearID;
a_newTree.pts.push_back(a_hFeature->gapPt_0);
a_newTree.pts.push_back(a_hFeature->gapPt_1);
#endif
beltTearings_unknown.push_back(a_newTree);
SSG_tearProcessInfo a_procInfo;
memset(&a_procInfo, 0, sizeof(SSG_tearProcessInfo));
a_procInfo.tearID = a_newTree.tearID;
a_procInfo.hGap_depth_max = a_hFeature->gap_depth;
a_procInfo.hGap_width_max = a_hFeature->gap_width;
a_procInfo.hGap_width_sum = a_hFeature->gap_width;
a_procInfo.hGap_num = 1;
tearProcInfo.push_back(a_procInfo);
}
else
{
SSG_beltTearingInfo* a_matchTree;
int tree_id = hFeature_tree_id_pair[i].data_0;
if (0 == hFeature_tree_id_pair[i].data_1)
a_matchTree = &beltTearings_growing[tree_id];
else
a_matchTree = &beltTearings_unknown[tree_id];
//取相应的procInfo
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
a_matchTree->tearID,
tearProcInfo);
match_procInfo->hGap_depth_max = match_procInfo->hGap_depth_max < a_hFeature->gap_depth ? a_hFeature->gap_depth : match_procInfo->hGap_depth_max;
match_procInfo->hGap_width_max = match_procInfo->hGap_width_max < a_hFeature->gap_width ? a_hFeature->gap_width : match_procInfo->hGap_width_max;
match_procInfo->hGap_width_sum += a_hFeature->gap_width;
match_procInfo->hGap_num++;
#if OUTPUT_TEARING_POINTS
a_hFeature->gapPt_0.nPointIdx = a_matchTree->tearID;
a_hFeature->gapPt_1.nPointIdx = a_matchTree->tearID;
a_matchTree->pts.push_back(a_hFeature->gapPt_0);
a_matchTree->pts.push_back(a_hFeature->gapPt_1);
#endif
//
a_matchTree->endLineIdx = procLineIdx;
_combineROI(&a_matchTree->roi, &a_hFeature->roi);
if (keSG_tearType_CrossWise == a_matchTree->tearType)
{
a_matchTree->tearWidth = match_procInfo->hGap_width_max;
a_matchTree->tearDepth = match_procInfo->hGap_depth_max;
}
}
}
}
#endif
//判断生长树是否结果生成beltTearings_ended目标
if (beltTearings_growing.size() > 0)
{
int i_max = beltTearings_growing.size();
for (int i = i_max-1; i >= 0; i--) //从后往前处理,这样在删除时不会影响后续检查
{
if (beltTearings_growing[i].endLineIdx != procLineIdx)
{
int idx_diff;
if (procLineIdx > beltTearings_growing[i].endLineIdx)
idx_diff = procLineIdx - beltTearings_growing[i].endLineIdx;
else
idx_diff = INT_MAX - beltTearings_growing[i].endLineIdx + 1 + procLineIdx;
double dist = idx_diff * measureParam.scanXScale;
if (dist > measureParam.tearingMinGap)
{
beltTearings_growing[i].tearStatus = keSG_tearStatus_Ended; //结束
beltTearings_ended.push_back(beltTearings_growing[i]);
beltTearings_growing.erase(beltTearings_growing.begin() + i);
}
}
}
}
//处理unknown的撕裂生成beltTearings_new
if (beltTearings_unknown.size() > 0)
{
int i_max = beltTearings_unknown.size();
for (int i = i_max - 1; i >= 0; i--)//从后往前处理,这样在删除时不会影响后续检查
{
if (keSG_tearStatus_Invalid == beltTearings_unknown[i].tearStatus)
{
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
beltTearings_unknown[i].tearID,
tearProcInfo);
match_procInfo->tearID = -1;
beltTearings_unknown.erase(beltTearings_unknown.begin() + i);
}
else
{
if (beltTearings_unknown[i].endLineIdx == procLineIdx) //检查是否需要报警
{
//计算ROI的长宽
double w = beltTearings_unknown[i].roi.right - beltTearings_unknown[i].roi.left;
double h = beltTearings_unknown[i].roi.bottom - beltTearings_unknown[i].roi.top;
if ((w >= measureParam.tearingMinLen) || (h >= measureParam.tearingMinLen))
{
int lines = beltTearings_unknown[i].endLineIdx - beltTearings_unknown[i].statLineIdx + 1;
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
beltTearings_unknown[i].tearID,
tearProcInfo);
int vldLines = match_procInfo->hGap_num > match_procInfo->vGap_num ? match_procInfo->hGap_num : match_procInfo->vGap_num;
if (vldLines < lines / 2)
{
match_procInfo->tearID = -1;
beltTearings_unknown.erase(beltTearings_unknown.begin() + i);
}
else
{
bool isVTearing = true;
if ((match_procInfo->hGap_num > 0) && (match_procInfo->vGap_num == 0))
isVTearing = false;
else if (((match_procInfo->hGap_num > 0) && (match_procInfo->vGap_num > 0)) &&
(match_procInfo->hGap_width_max < match_procInfo->vGap_width_max))
isVTearing = false;
if (false == isVTearing)
{
beltTearings_unknown[i].tearType = keSG_tearType_CrossWise;
beltTearings_unknown[i].tearStatus = keSG_tearStatus_New;
beltTearings_unknown[i].tearDepth = match_procInfo->hGap_depth_max;
beltTearings_unknown[i].tearWidth = match_procInfo->hGap_width_max;
beltTearings_new.push_back(beltTearings_unknown[i]);
beltTearings_unknown.erase(beltTearings_unknown.begin() + i);
}
else
{
beltTearings_unknown[i].tearType = keSG_tearType_MachineDir;
beltTearings_unknown[i].tearStatus = keSG_tearStatus_New;
beltTearings_unknown[i].tearDepth = match_procInfo->vGap_depth_max;
beltTearings_unknown[i].tearWidth = match_procInfo->vGap_width_max;
beltTearings_new.push_back(beltTearings_unknown[i]);
beltTearings_unknown.erase(beltTearings_unknown.begin() + i);
}
}
}
}
else//检查是否是噪声
{
int idx_diff;
if (procLineIdx > beltTearings_unknown[i].endLineIdx)
idx_diff = procLineIdx - beltTearings_unknown[i].endLineIdx;
else
idx_diff = INT_MAX - beltTearings_unknown[i].endLineIdx + 1 + procLineIdx;
double dist = idx_diff * measureParam.scanXScale;
if (dist > measureParam.tearingMinGap)
{
SSG_tearProcessInfo* match_procInfo = _getProcInfo(
tearProcInfo_IdOffset,
beltTearings_unknown[i].tearID,
tearProcInfo);
match_procInfo->tearID = -1;
beltTearings_unknown.erase(beltTearings_unknown.begin() + i);
}
}
}
}
}
return;
}