SX_lapWeldDetection
version 1.2.0 :焊缝(平缝)识别添加博清模拟数据中的凸起焊缝,通过参数选择识别类型(不支持自动识别)
This commit is contained in:
parent
8d49089a57
commit
737d741406
@ -744,6 +744,19 @@ void _removeZeroLines_XYZ(std::vector<std::vector< SVzNL3DPosition>>& scanData)
|
||||
return;
|
||||
}
|
||||
|
||||
void _outputWeldInfo(char* outFileName, std::vector<SVzNL3DPoint>& weldRawPoints)
|
||||
{
|
||||
std::ofstream sw(outFileName);
|
||||
char dataStr[250];
|
||||
|
||||
for (int i = 0; i < (int)weldRawPoints.size(); i++)
|
||||
{
|
||||
sprintf_s(dataStr, 250, "id_%d: (%g, %g, %g)", i+1, weldRawPoints[i].x, weldRawPoints[i].y, weldRawPoints[i].z);
|
||||
sw << dataStr << std::endl;
|
||||
}
|
||||
sw.close();
|
||||
}
|
||||
|
||||
#define CONVERT_TO_GRID 0
|
||||
#define TEST_COMPUTE_CALIB_PARA 0
|
||||
#define TEST_COMPUTE_POSITION 1
|
||||
@ -916,15 +929,16 @@ void lapWeldTest()
|
||||
|
||||
#define TEST_BQ_CALIB_PARA 0
|
||||
#define TEST_BQ_WELD_SEAM 1
|
||||
#define BQ_TEST_GROUP 1
|
||||
#define BQ_TEST_GROUP 2
|
||||
void BQ_thinWeldSeamTest()
|
||||
{
|
||||
const char* dataPath[BQ_TEST_GROUP] = {
|
||||
"F:/ShangGu/项目/冠钦_博清科技/焊缝识别/数据/", //0
|
||||
"F:/ShangGu/项目/冠钦_博清科技/焊缝识别/博清实验室模拟数据/", //0
|
||||
};
|
||||
|
||||
SVzNLRange fileIdx[BQ_TEST_GROUP] = {
|
||||
{1,4},
|
||||
{1,4},{1,2}
|
||||
};
|
||||
|
||||
|
||||
@ -1003,7 +1017,7 @@ void BQ_thinWeldSeamTest()
|
||||
|
||||
#if TEST_BQ_WELD_SEAM
|
||||
//for (int group = 0; group < TEST_GROUPS; group++)
|
||||
for (int grp = 0; grp < BQ_TEST_GROUP; grp++)
|
||||
for (int grp = 1; grp < BQ_TEST_GROUP; grp++)
|
||||
{
|
||||
SSG_planeCalibPara groundCalibPara;
|
||||
//初始化成单位阵
|
||||
@ -1020,8 +1034,11 @@ void BQ_thinWeldSeamTest()
|
||||
for (int i = 0; i < 9; i++)
|
||||
groundCalibPara.invRMatrix[i] = groundCalibPara.planeCalib[i];
|
||||
char calibFile[250];
|
||||
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
|
||||
groundCalibPara = _readCalibPara(calibFile);
|
||||
if (0 == grp)
|
||||
{
|
||||
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
|
||||
groundCalibPara = _readCalibPara(calibFile);
|
||||
}
|
||||
|
||||
double para_chkWidth_wide = 2.5f;
|
||||
|
||||
@ -1029,22 +1046,32 @@ void BQ_thinWeldSeamTest()
|
||||
SVzNLRangeD gapParam;
|
||||
|
||||
SWD_valleyParam valleyParam;
|
||||
valleyParam.chkWin_width = 2.5; //mm, 检测2.5mm宽的V型
|
||||
valleyParam.chkWin_width = 5.0; // 2.5; //mm, 检测2.5mm宽的V型
|
||||
valleyParam.maxWidth = 20.0; //最大宽度20mm,用于过滤虚假信号
|
||||
valleyParam.minHeight = 1.0;
|
||||
valleyParam.minHeight = 0.5;
|
||||
|
||||
SSG_treeGrowParam growParam;
|
||||
growParam.maxLineSkipNum = 50;
|
||||
growParam.yDeviation_max = 1.0;
|
||||
growParam.yDeviation_max = 1.5;
|
||||
growParam.maxSkipDistance = 30.0;
|
||||
growParam.zDeviation_max = 5.0;//
|
||||
growParam.minLTypeTreeLen = 50; //mm,
|
||||
growParam.minVTypeTreeLen = 50; //mm
|
||||
|
||||
EWD_FlawType detectType;
|
||||
if(0 == grp)
|
||||
detectType = keWD_FlawType_Depression;
|
||||
else
|
||||
detectType = keWD_FlawType_Protrusion;
|
||||
|
||||
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
|
||||
{
|
||||
//fidx = 2;
|
||||
char _scan_file[256];
|
||||
sprintf_s(_scan_file, "%s%d_LaserData_Jl26C077.txt", dataPath[grp], fidx);
|
||||
if(0 == grp)
|
||||
sprintf_s(_scan_file, "%s%d_LaserData_Jl26C077.txt", dataPath[grp], fidx);
|
||||
else
|
||||
sprintf_s(_scan_file, "%s%d_LaserData_Jh26B083.txt", dataPath[grp], fidx);
|
||||
printf("process: %s......\n", _scan_file);
|
||||
|
||||
std::vector<std::vector< SVzNL3DPosition>> scanLines;
|
||||
@ -1059,6 +1086,9 @@ void BQ_thinWeldSeamTest()
|
||||
std::vector<SSG_gapFeatureTree> trees;
|
||||
for (int i = 0; i < (int)scanLines.size(); i++)
|
||||
{
|
||||
if (i == 117)
|
||||
int kkk = 1;
|
||||
|
||||
std::vector<SVzNL3DPosition>& a_line = scanLines[i];
|
||||
std::vector< SSG_basicFeatureGap> line_valleys;
|
||||
sx_lineDataR(scanLines[i], groundCalibPara.planeCalib, -1);//调平,去除地面
|
||||
@ -1074,11 +1104,12 @@ void BQ_thinWeldSeamTest()
|
||||
a_line,
|
||||
i,
|
||||
valleyParam,
|
||||
detectType,
|
||||
line_valleys);
|
||||
|
||||
#endif
|
||||
bool isLastLine = i == ((int)scanLines.size() - 1) ? true : false;
|
||||
sg_lineGapsGrowing(
|
||||
sg_lineGapsGrowing_treeFirst(
|
||||
i,
|
||||
isLastLine,
|
||||
line_valleys,
|
||||
@ -1127,6 +1158,9 @@ void BQ_thinWeldSeamTest()
|
||||
std::vector< std::vector<SVzNL3DPoint>> multiSeam;
|
||||
multiSeam.push_back(weldOps);
|
||||
_outputRGBDScanLapWeld_RGBD(outFileName, scanLines, multiSeam, true);
|
||||
sprintf_s(outFileName, "%sresult\\LaserLine%d_weldInfo.txt", dataPath[grp], fidx);
|
||||
_outputWeldInfo(outFileName, weldOps);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1133,4 +1133,5 @@ SG_APISHARED_EXPORT void wd_getLineVFlaws(
|
||||
std::vector<SVzNL3DPosition>& a_line,
|
||||
const int lineIdx,
|
||||
const SWD_valleyParam valleyParam,
|
||||
const EWD_FlawType detectFlawType,
|
||||
std::vector< SSG_basicFeatureGap>& valleys);
|
||||
|
||||
@ -6,6 +6,14 @@
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
typedef enum
|
||||
{
|
||||
keWD_FlawType_Uknown = 0,
|
||||
keWD_FlawType_Depression, //凹陷
|
||||
keWD_FlawType_Protrusion, //凸起
|
||||
keSG_FlawType_Dep_Prot, //凹陷和凸起混合
|
||||
} EWD_FlawType;
|
||||
|
||||
// 定义欧拉角结构体(单位:度)
|
||||
typedef struct{
|
||||
double roll; // 绕X轴旋转(横滚)
|
||||
@ -90,6 +98,12 @@ typedef struct
|
||||
int end;
|
||||
}SWD_Interval; //区间
|
||||
|
||||
typedef struct SWD_IndexedValue
|
||||
{
|
||||
int idx;
|
||||
double value;
|
||||
}SWD_IndexedValue;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool validFlag; //指示结果是否有效
|
||||
|
||||
@ -9702,7 +9702,7 @@ if (i == 98)
|
||||
return;
|
||||
}
|
||||
|
||||
enum STATES { null = 0, UP, DOWN };
|
||||
enum STATES { null = 0, UP, DOWN, USED };
|
||||
struct posAttri
|
||||
{
|
||||
int peakPos;
|
||||
@ -9797,8 +9797,17 @@ float _computeHeight(SVzNL3DPoint& startPt, SVzNL3DPoint& endPt, SVzNL3DPoint& v
|
||||
float height = fabs(_a * valleyPt.y + _b * valleyPt.z + _c) / sqrt(pow(_a, 2) + pow(_b, 2));
|
||||
return height;
|
||||
}
|
||||
|
||||
bool _sortFormZMaxToMin(const SWD_IndexedValue& a, const SWD_IndexedValue& b) {
|
||||
return a.value > b.value;
|
||||
}
|
||||
bool _sortFormZMinToMax(const SWD_IndexedValue& a, const SWD_IndexedValue& b) {
|
||||
return a.value < b.value;
|
||||
}
|
||||
|
||||
/* startId, endId: 有效点的起止位置。对于栅格数据格式,开始的空点和结束的空点都不是有效点 */
|
||||
void _valleyDetect(
|
||||
//凹陷检测(depression)
|
||||
void _depressionDetect(
|
||||
std::vector<SVzNL3DPosition>& a_line,
|
||||
const int lineIdx, const int startId, const int endId,
|
||||
std::vector<posAttri>& deriv_1_peaks,
|
||||
@ -9816,129 +9825,300 @@ void _valleyDetect(
|
||||
double y_start = a_line[startId].pt3D.y;
|
||||
double y_end = a_line[endId].pt3D.y;
|
||||
|
||||
//逐个peak检测:正peak
|
||||
//按peak(DOWN)值进行排序
|
||||
std::vector<SWD_IndexedValue> indexedPeaks;
|
||||
for (int i = 0; i < deriv_2_peaks.size(); i++)
|
||||
{
|
||||
if (i == 153)
|
||||
int kkk = 1;
|
||||
posAttri a_pos = deriv_2_peaks[i];
|
||||
if ((a_pos.peakState == DOWN) && (deriv_2[a_pos.peakPos] < 0))
|
||||
{
|
||||
//检查两侧
|
||||
int preEdge = -1;
|
||||
for (int j = a_pos.peakPos - 1; j > 0; j--)
|
||||
SWD_IndexedValue a_indexdPeak;
|
||||
a_indexdPeak.idx = i;
|
||||
a_indexdPeak.value = a_line[a_pos.peakPos].pt3D.z;
|
||||
indexedPeaks.push_back(a_indexdPeak);
|
||||
}
|
||||
}
|
||||
std::sort(indexedPeaks.begin(), indexedPeaks.end(), _sortFormZMaxToMin);
|
||||
//逐个peak检测:正peak
|
||||
for (int i = 0; i < (int)indexedPeaks.size(); i++)
|
||||
{
|
||||
int idx = indexedPeaks[i].idx;
|
||||
if (idx == 153)
|
||||
int kkk = 1;
|
||||
posAttri a_pos = deriv_2_peaks[idx];
|
||||
//检查两侧
|
||||
int preEdge = -1;
|
||||
for (int j = a_pos.peakPos - 1; j > 0; j--)
|
||||
{
|
||||
if ( (buff[j].peakState == DOWN)|| (buff[j].peakState == USED))
|
||||
break;
|
||||
else if (buff[j].peakState == UP)
|
||||
{
|
||||
if (buff[j].peakState == DOWN)
|
||||
break;
|
||||
else if (buff[j].peakState == UP)
|
||||
{
|
||||
if (deriv_1[j] > 0)
|
||||
preEdge = j;
|
||||
break;
|
||||
}
|
||||
if (deriv_1[j] > 0)
|
||||
preEdge = j;
|
||||
break;
|
||||
}
|
||||
int postEdge = -1;
|
||||
for (int j = a_pos.peakPos + 1; j < (int)a_line.size(); j++)
|
||||
}
|
||||
int postEdge = -1;
|
||||
for (int j = a_pos.peakPos + 1; j < (int)a_line.size(); j++)
|
||||
{
|
||||
if ((buff[j].peakState == UP)|| (buff[j].peakState == USED))
|
||||
break;
|
||||
else if (buff[j].peakState == DOWN)
|
||||
{
|
||||
if (buff[j].peakState == UP)
|
||||
break;
|
||||
else if (buff[j].peakState == DOWN)
|
||||
{
|
||||
if (deriv_1[j] < 0)
|
||||
postEdge = j;
|
||||
break;
|
||||
}
|
||||
if (deriv_1[j] < 0)
|
||||
postEdge = j;
|
||||
break;
|
||||
}
|
||||
//
|
||||
if ((preEdge >= 0) && (postEdge >= 0)) //初步符合凹陷特点
|
||||
}
|
||||
//
|
||||
if ((preEdge >= 0) && (postEdge >= 0)) //初步符合凹陷特点
|
||||
{
|
||||
float edge_value_pre = deriv_1[preEdge];
|
||||
float edge_value_post = deriv_1[postEdge];
|
||||
//检测对称性
|
||||
float min_value, max_value;
|
||||
if (edge_value_pre < (-edge_value_post))
|
||||
{
|
||||
float edge_value_pre = deriv_1[preEdge];
|
||||
float edge_value_post = deriv_1[postEdge];
|
||||
//检测对称性
|
||||
float min_value, max_value;
|
||||
if (edge_value_pre < (-edge_value_post))
|
||||
min_value = edge_value_pre;
|
||||
max_value = -edge_value_post;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_value = edge_value_pre;
|
||||
min_value = -edge_value_post;
|
||||
}
|
||||
if (min_value > max_value / 10) //2023.05.02: 放宽。当凹陷在斜面上时,不再是maxValue/2的理想情况
|
||||
{
|
||||
//检查凹陷宽度深度,滤除噪声
|
||||
float th_pre = edge_value_pre * 0.5;
|
||||
int edge_pos_pre = -1;
|
||||
for (int j = preEdge; j >= 0; j--)
|
||||
{
|
||||
min_value = edge_value_pre;
|
||||
max_value = -edge_value_post;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_value = edge_value_pre;
|
||||
min_value = -edge_value_post;
|
||||
}
|
||||
if (min_value > max_value / 10) //2023.05.02: 放宽。当凹陷在斜面上时,不再是maxValue/2的理想情况
|
||||
{
|
||||
//检查凹陷宽度深度,滤除噪声
|
||||
float th_pre = edge_value_pre * 0.5;
|
||||
int edge_pos_pre = -1;
|
||||
for (int j = preEdge; j >= 0; j--)
|
||||
if ( (deriv_1[j] <= th_pre) && (a_line[j].nPointIdx >= 0)) //非填充点
|
||||
{
|
||||
if ( (deriv_1[j] <= th_pre) && (a_line[j].nPointIdx >= 0)) //非填充点
|
||||
{
|
||||
edge_pos_pre = j;
|
||||
break;
|
||||
}
|
||||
edge_pos_pre = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float th_post = edge_value_post * 0.5;
|
||||
int edge_pos_post = -1;
|
||||
for (int j = postEdge; j < (int)a_line.size(); j++)
|
||||
float th_post = edge_value_post * 0.5;
|
||||
int edge_pos_post = -1;
|
||||
for (int j = postEdge; j < (int)a_line.size(); j++)
|
||||
{
|
||||
if ((deriv_1[j] >= th_post) && (a_line[j].nPointIdx >= 0)) //非填充点
|
||||
{
|
||||
if ((deriv_1[j] >= th_post) && (a_line[j].nPointIdx >= 0)) //非填充点
|
||||
{
|
||||
edge_pos_post = j;
|
||||
break;
|
||||
}
|
||||
edge_pos_post = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//检测宽度
|
||||
if ((edge_pos_pre >= 0) && (edge_pos_post >= 0))
|
||||
//检测宽度
|
||||
if ((edge_pos_pre >= 0) && (edge_pos_post >= 0))
|
||||
{
|
||||
//float width = a_line->m_p3DPositiont[edge_pos_post].pt3D.y - a_line->m_p3DPositiont[edge_pos_pre].pt3D.y;
|
||||
float width = a_line[postEdge].pt3D.y - a_line[preEdge].pt3D.y;
|
||||
if (width < valleyParam.maxWidth)
|
||||
{
|
||||
//float width = a_line->m_p3DPositiont[edge_pos_post].pt3D.y - a_line->m_p3DPositiont[edge_pos_pre].pt3D.y;
|
||||
float width = a_line[postEdge].pt3D.y - a_line[preEdge].pt3D.y;
|
||||
if (width < valleyParam.maxWidth)
|
||||
float height = _computeHeight(a_line[edge_pos_pre].pt3D,
|
||||
a_line[edge_pos_post].pt3D,
|
||||
a_line[a_pos.peakPos].pt3D);
|
||||
if (height > valleyParam.minHeight)
|
||||
{
|
||||
float height = _computeHeight(a_line[edge_pos_pre].pt3D,
|
||||
a_line[edge_pos_post].pt3D,
|
||||
a_line[a_pos.peakPos].pt3D);
|
||||
if (height > valleyParam.minHeight)
|
||||
//精确确定peak点
|
||||
int realPeakPos = preEdge;
|
||||
for (int m = preEdge; m <= postEdge; m++)
|
||||
{
|
||||
//精确确定peak点
|
||||
int realPeakPos = preEdge;
|
||||
for (int m = preEdge; m <= postEdge; m++)
|
||||
{
|
||||
if ((a_line[realPeakPos].pt3D.z < a_line[m].pt3D.z) && (a_line[m].nPointIdx >= 0))
|
||||
realPeakPos = m;
|
||||
}
|
||||
|
||||
SSG_basicFeatureGap a_valley;
|
||||
memset(&a_valley, 0, sizeof(SSG_basicFeatureGap));
|
||||
a_valley.gapPeak.nPointIdx = realPeakPos;
|
||||
a_valley.gapPeak.pt3D = a_line[realPeakPos].pt3D;
|
||||
a_valley.gapPt_0.nPointIdx = edge_pos_pre;
|
||||
a_valley.gapPt_0.pt3D = a_line[edge_pos_pre].pt3D;
|
||||
a_valley.gapPt_1.nPointIdx = edge_pos_post;
|
||||
a_valley.gapPt_1.pt3D = a_line[edge_pos_post].pt3D;
|
||||
a_valley.lineIdx = lineIdx;
|
||||
a_valley.gap_start = a_line[preEdge].pt3D.y;
|
||||
a_valley.gap_width = width;
|
||||
a_valley.gap_depth = height;
|
||||
valleys.push_back(a_valley);
|
||||
if ((a_line[realPeakPos].pt3D.z < a_line[m].pt3D.z) && (a_line[m].nPointIdx >= 0))
|
||||
realPeakPos = m;
|
||||
}
|
||||
|
||||
SSG_basicFeatureGap a_valley;
|
||||
memset(&a_valley, 0, sizeof(SSG_basicFeatureGap));
|
||||
a_valley.gapPeak.nPointIdx = realPeakPos;
|
||||
a_valley.gapPeak.pt3D = a_line[realPeakPos].pt3D;
|
||||
a_valley.gapPt_0.nPointIdx = edge_pos_pre;
|
||||
a_valley.gapPt_0.pt3D = a_line[edge_pos_pre].pt3D;
|
||||
a_valley.gapPt_1.nPointIdx = edge_pos_post;
|
||||
a_valley.gapPt_1.pt3D = a_line[edge_pos_post].pt3D;
|
||||
a_valley.lineIdx = lineIdx;
|
||||
a_valley.gap_start = a_line[preEdge].pt3D.y;
|
||||
a_valley.gap_width = width;
|
||||
a_valley.gap_depth = height;
|
||||
valleys.push_back(a_valley);
|
||||
|
||||
buff[preEdge].peakState = USED;
|
||||
buff[postEdge].peakState = USED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//凸起检测(protrusion)
|
||||
void _protrusionDetect(
|
||||
std::vector<SVzNL3DPosition>& a_line,
|
||||
const int lineIdx, const int startId, const int endId,
|
||||
std::vector<posAttri>& deriv_1_peaks,
|
||||
std::vector<posAttri>& deriv_2_peaks,
|
||||
std::vector<double>& deriv_1,
|
||||
std::vector<double>& deriv_2,
|
||||
std::vector<SSG_basicFeatureGap>& valleys,
|
||||
const SWD_valleyParam valleyParam)
|
||||
{
|
||||
std::vector< posAttri> buff;
|
||||
buff.resize(a_line.size());
|
||||
for (int i = 0; i < deriv_1_peaks.size(); i++)
|
||||
buff[deriv_1_peaks[i].peakPos] = deriv_1_peaks[i];
|
||||
|
||||
double y_start = a_line[startId].pt3D.y;
|
||||
double y_end = a_line[endId].pt3D.y;
|
||||
|
||||
//按peak(UP)值进行排序
|
||||
std::vector<SWD_IndexedValue> indexedPeaks;
|
||||
for (int i = 0; i < deriv_2_peaks.size(); i++)
|
||||
{
|
||||
posAttri a_pos = deriv_2_peaks[i];
|
||||
if ((a_pos.peakState == UP) && (deriv_2[a_pos.peakPos] > 0))
|
||||
{
|
||||
SWD_IndexedValue a_indexdPeak;
|
||||
a_indexdPeak.idx = i;
|
||||
a_indexdPeak.value = a_line[a_pos.peakPos].pt3D.z;
|
||||
indexedPeaks.push_back(a_indexdPeak);
|
||||
}
|
||||
}
|
||||
std::sort(indexedPeaks.begin(), indexedPeaks.end(), _sortFormZMinToMax);
|
||||
|
||||
//逐个peak检测:正peak
|
||||
for (int i = 0; i < (int)indexedPeaks.size(); i++)
|
||||
{
|
||||
if (i == 153)
|
||||
int kkk = 1;
|
||||
int idx = indexedPeaks[i].idx;
|
||||
posAttri a_pos = deriv_2_peaks[idx];
|
||||
|
||||
//检查两侧
|
||||
int preEdge = -1;
|
||||
for (int j = a_pos.peakPos - 1; j > 0; j--)
|
||||
{
|
||||
if ( (buff[j].peakState == UP)|| (buff[j].peakState == USED))
|
||||
break;
|
||||
else if (buff[j].peakState == DOWN)
|
||||
{
|
||||
if (deriv_1[j] < 0)
|
||||
preEdge = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int postEdge = -1;
|
||||
for (int j = a_pos.peakPos + 1; j < (int)a_line.size(); j++)
|
||||
{
|
||||
if ( (buff[j].peakState == DOWN) || (buff[j].peakState == USED))
|
||||
break;
|
||||
else if (buff[j].peakState == UP)
|
||||
{
|
||||
if (deriv_1[j] > 0)
|
||||
postEdge = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
if ((preEdge >= 0) && (postEdge >= 0)) //初步符合凸起特点
|
||||
{
|
||||
float edge_value_pre = deriv_1[preEdge];
|
||||
float edge_value_post = deriv_1[postEdge];
|
||||
//检测对称性
|
||||
float min_value, max_value;
|
||||
if ((-edge_value_pre) < edge_value_post)
|
||||
{
|
||||
min_value = -edge_value_pre;
|
||||
max_value = edge_value_post;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_value = -edge_value_pre;
|
||||
min_value = edge_value_post;
|
||||
}
|
||||
if (min_value > max_value / 5) //2023.05.02: 放宽。当凹陷在斜面上时,不再是maxValue/2的理想情况
|
||||
{
|
||||
//检查凹陷宽度深度,滤除噪声
|
||||
float th_pre = edge_value_pre * 0.5;
|
||||
int edge_pos_pre = -1;
|
||||
for (int j = preEdge; j >= 0; j--)
|
||||
{
|
||||
if ((deriv_1[j] >= th_pre) && (a_line[j].nPointIdx >= 0)) //非填充点
|
||||
{
|
||||
edge_pos_pre = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float th_post = edge_value_post * 0.5;
|
||||
int edge_pos_post = -1;
|
||||
for (int j = postEdge; j < (int)a_line.size(); j++)
|
||||
{
|
||||
if ((deriv_1[j] <= th_post) && (a_line[j].nPointIdx >= 0)) //非填充点
|
||||
{
|
||||
edge_pos_post = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//检测宽度
|
||||
if ((edge_pos_pre >= 0) && (edge_pos_post >= 0))
|
||||
{
|
||||
//float width = a_line->m_p3DPositiont[edge_pos_post].pt3D.y - a_line->m_p3DPositiont[edge_pos_pre].pt3D.y;
|
||||
float width = a_line[postEdge].pt3D.y - a_line[preEdge].pt3D.y;
|
||||
if (width < valleyParam.maxWidth)
|
||||
{
|
||||
float height = _computeHeight(a_line[edge_pos_pre].pt3D,
|
||||
a_line[edge_pos_post].pt3D,
|
||||
a_line[a_pos.peakPos].pt3D);
|
||||
if (height > valleyParam.minHeight)
|
||||
{
|
||||
//精确确定peak点
|
||||
int realPeakPos = preEdge;
|
||||
for (int m = preEdge; m <= postEdge; m++)
|
||||
{
|
||||
if ((a_line[realPeakPos].pt3D.z > a_line[m].pt3D.z) && (a_line[m].nPointIdx >= 0))
|
||||
realPeakPos = m;
|
||||
}
|
||||
|
||||
SSG_basicFeatureGap a_valley;
|
||||
memset(&a_valley, 0, sizeof(SSG_basicFeatureGap));
|
||||
a_valley.gapPeak.nPointIdx = realPeakPos;
|
||||
a_valley.gapPeak.pt3D = a_line[realPeakPos].pt3D;
|
||||
a_valley.gapPt_0.nPointIdx = edge_pos_pre;
|
||||
a_valley.gapPt_0.pt3D = a_line[edge_pos_pre].pt3D;
|
||||
a_valley.gapPt_1.nPointIdx = edge_pos_post;
|
||||
a_valley.gapPt_1.pt3D = a_line[edge_pos_post].pt3D;
|
||||
a_valley.lineIdx = lineIdx;
|
||||
a_valley.gap_start = a_line[preEdge].pt3D.y;
|
||||
a_valley.gap_width = width;
|
||||
a_valley.gap_depth = height;
|
||||
valleys.push_back(a_valley);
|
||||
|
||||
buff[preEdge].peakState = USED;
|
||||
buff[postEdge].peakState = USED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 支持栅格数据(要求输入栅格数据) */
|
||||
//提取扫描线上的V型Valley
|
||||
void wd_getLineVFlaws(
|
||||
std::vector<SVzNL3DPosition>& a_line,
|
||||
const int lineIdx,
|
||||
const SWD_valleyParam valleyParam,
|
||||
const EWD_FlawType detectFlawType,
|
||||
std::vector< SSG_basicFeatureGap>& valleys)
|
||||
{
|
||||
if (lineIdx == 286)
|
||||
@ -10004,7 +10184,11 @@ void wd_getLineVFlaws(
|
||||
//使用窄窗口
|
||||
//凹陷:二阶导为极值,在极值的两边有一负一正的一阶导极值。
|
||||
//float innerPara_max_valley_width = 20.0; //内部参数。控制最大凹陷检测宽度,用于过滤虚假凹陷
|
||||
_valleyDetect(a_line, lineIdx, startId, endId, deriv_1_peaks, deriv_2_peaks, deriv_1_narrow, deriv_2_narrow, valleys, valleyParam);
|
||||
if(keWD_FlawType_Depression == detectFlawType)
|
||||
_depressionDetect(a_line, lineIdx, startId, endId, deriv_1_peaks, deriv_2_peaks, deriv_1_narrow, deriv_2_narrow, valleys, valleyParam);
|
||||
else if (keWD_FlawType_Protrusion == detectFlawType)
|
||||
_protrusionDetect(a_line, lineIdx, startId, endId, deriv_1_peaks, deriv_2_peaks, deriv_1_narrow, deriv_2_narrow, valleys, valleyParam);
|
||||
//else if (keSG_FlawType_Dep_Prot == detectFlawType)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
|
||||
//version 1.0.0 :焊缝(平缝)识别检测算法初始发布
|
||||
//version 1.1.0 :焊缝(平缝)识别修正回归测试中发现的bug
|
||||
std::string m_strVersion = "weldSeamAlgo_1.1.0";
|
||||
//version 1.2.0 :焊缝(平缝)识别添加博清模拟数据中的凸起焊缝,通过参数选择识别类型(不支持自动识别)
|
||||
std::string m_strVersion = "weldSeamAlgo_1.2.0";
|
||||
|
||||
const char* wd_weldSeamAlgoVersion(void)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user