algoLib/sourceCode/rodAndBarDetection.cpp

290 lines
7.3 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 "rodAndBarDetection_Export.h"
#include <opencv2/opencv.hpp>
#include <limits>
//version 1.0.0 : base version release to customer
std::string m_strVersion = "1.0.0";
const char* wd_rodAndBarDetectionVersion(void)
{
return m_strVersion.c_str();
}
void sx_hexHeadScrewMeasure(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
bool isHorizonScan, //true:激光线平行槽道false:激光线垂直槽道
const SSG_cornerParam cornerPara,
const SSG_outlierFilterParam filterParam,
const SSG_treeGrowParam growParam,
double rodRidius,
std::vector<SSX_hexHeadScrewInfo>& screwInfo,
int* errCode)
{
*errCode = 0;
SSX_hexHeadScrewInfo screwInfo;
memset(&screwInfo, 0, sizeof(SSX_hexHeadScrewInfo));
int lineNum = (int)scanLines.size();
if (lineNum == 0)
{
*errCode = SG_ERR_3D_DATA_NULL;
return;
}
int linePtNum = (int)scanLines[0].size();
//判断数据格式是否为grid。算法只能处理grid数据格式
bool isGridData = true;
for (int line = 0; line < lineNum; line++)
{
if (linePtNum != (int)scanLines[line].size())
{
isGridData = false;
break;
}
}
if (false == isGridData)//数据不是网格格式
{
*errCode = SG_ERR_NOT_GRID_FORMAT;
return;
}
std::vector< std::vector<SVzNL3DPosition>> data_lines;
if (false == isHorizonScan)
{
data_lines.resize(lineNum);
for (int line = 0; line < lineNum; line++)
{
data_lines[line].insert(data_lines[line].end(), scanLines[line].begin(), scanLines[line].end());
for (int j = 0, j_max = (int)data_lines[line].size(); j < j_max; j++)
{
data_lines[line][j].nPointIdx = j;
scanLines[line][j].nPointIdx = 0; //转义复用
}
}
}
else
{
data_lines.resize(linePtNum);
for (int i = 0; i < linePtNum; i++)
data_lines[i].resize(lineNum);
for (int line = 0; line < lineNum; line++)
{
for (int j = 0; j < linePtNum; j++)
{
scanLines[line][j].nPointIdx = 0; //将原始数据的序列清0会转义使用
data_lines[j][line] = scanLines[line][j];
data_lines[j][line].pt3D.x = scanLines[line][j].pt3D.y;
data_lines[j][line].pt3D.y = scanLines[line][j].pt3D.x;
}
}
lineNum = linePtNum;
linePtNum = (int)data_lines[0].size();
for (int line = 0; line < lineNum; line++)
{
for (int j = 0, j_max = (int)data_lines[line].size(); j < j_max; j++)
data_lines[line][j].nPointIdx = j;
}
}
std::vector<std::vector<SWD_segFeature>> arcFeatures;
for (int line = 0; line < lineNum; line++)
{
if (line == 44)
int kkk = 1;
std::vector<SVzNL3DPosition>& lineData = data_lines[line];
//滤波,滤除异常点
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], linePtNum, filterParam);
std::vector<SWD_segFeature> line_ringArcs;
int dataSize = (int)lineData.size();
//提取Arc特征
wd_getRingArcFeature(
lineData,
line, //当前扫描线序号
cornerPara,
rodRidius / 2, //环宽度
line_ringArcs //环
);
arcFeatures.push_back(line_ringArcs);
}
//特征生长
std::vector<SWD_segFeatureTree> growTrees;
wd_getSegFeatureGrowingTrees(
arcFeatures,
growTrees,
growParam);
if (growTrees.size() == 0)
{
*errCode = SG_ERR_NOT_GRID_FORMAT;
return;
}
int objNum = (int)growTrees.size();
for (int i = 0; i < objNum; i++)
{
//空间直线拟合
//投影
//
}
std::vector<SSG_basicFeatureGap>& nodes_1 = growTrees[0].treeNodes;
std::vector<SSG_basicFeatureGap>& nodes_2 = growTrees[1].treeNodes;
#if _OUTPUT_DEBUG_DATA
for (int i = 0, i_max = (int)nodes_1.size(); i < i_max; i++)
{
int lineIdx, ptIdx;
if (false == isHorizonScan)
{
lineIdx = nodes_1[i].lineIdx;
ptIdx = nodes_1[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 1;
ptIdx = nodes_1[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 2;
}
else
{
ptIdx = nodes_1[i].lineIdx;
lineIdx = nodes_1[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 1;
lineIdx = nodes_1[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 2;
}
}
for (int i = 0, i_max = (int)nodes_2.size(); i < i_max; i++)
{
int lineIdx, ptIdx;
if (false == isHorizonScan)
{
lineIdx = nodes_2[i].lineIdx;
ptIdx = nodes_2[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 1;
ptIdx = nodes_2[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 2;
}
else
{
ptIdx = nodes_2[i].lineIdx;
lineIdx = nodes_2[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 1;
lineIdx = nodes_2[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 2;
}
}
#endif
//按扫描线配对
std::vector<SSG_basicFeatureGap> line_1; //line_1和line_2为按扫描线对应的两个槽道上的Gap特征
std::vector<SSG_basicFeatureGap> line_2;
int i_idx = 0;
int j_idx = 0;
while (1)
{
int line_idx1 = nodes_1[i_idx].lineIdx;
int line_idx2 = nodes_2[j_idx].lineIdx;
if (line_idx1 == line_idx2)
{
line_1.push_back(nodes_1[i_idx]);
line_2.push_back(nodes_2[j_idx]);
i_idx++;
j_idx++;
}
else
{
if (line_idx1 < line_idx2)
i_idx++;
else
j_idx++;
}
if ((i_idx >= (int)nodes_1.size()) || (j_idx >= (int)nodes_2.size()))
break;
}
#if _OUTPUT_DEBUG_DATA
for (int i = 0, i_max = (int)line_1.size(); i < i_max; i++)
{
int lineIdx, ptIdx;
if (false == isHorizonScan)
{
lineIdx = line_1[i].lineIdx;
ptIdx = line_1[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 3;
ptIdx = line_1[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 4;
}
else
{
ptIdx = line_1[i].lineIdx;
lineIdx = line_1[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 3;
lineIdx = line_1[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 4;
}
}
for (int i = 0, i_max = (int)line_2.size(); i < i_max; i++)
{
int lineIdx, ptIdx;
if (false == isHorizonScan)
{
lineIdx = line_2[i].lineIdx;
ptIdx = line_2[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 3;
ptIdx = line_2[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 4;
}
else
{
ptIdx = line_2[i].lineIdx;
lineIdx = line_2[i].gapPt_0.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 3;
lineIdx = line_2[i].gapPt_1.nPointIdx;
scanLines[lineIdx][ptIdx].nPointIdx = 4;
}
}
#endif
//旋转保证扫描线与Gap垂直
double angleSearchWin = 30;
double angleStepping = 0.1;
int loop = (int)(angleSearchWin / angleStepping);
double bestSpace = 0;
double rotateAngle = 0;
for (int i = -loop; i <= loop; i++)
{
double angle = i * angleStepping;
std::vector<SSG_basicFeatureGap> rotate_line_1;
_XY_rotateLine(angle, line_1, rotate_line_1);
std::vector<SSG_basicFeatureGap> rotate_line_2;
_XY_rotateLine(angle, line_2, rotate_line_2);
double meanSpace = _computeChannelSpace(rotate_line_1, rotate_line_2);
if (bestSpace < meanSpace)
{
bestSpace = meanSpace;
rotateAngle = angle;
}
}
std::vector<SSG_basicFeatureGap> calib_line_1;
_XY_rotateLine(rotateAngle, line_1, calib_line_1);
std::vector<SSG_basicFeatureGap> calib_line_2;
_XY_rotateLine(rotateAngle, line_2, calib_line_2);
channelInfo.channelSpace = _computeChannelSpace(calib_line_1, calib_line_2);
channelInfo.channelWidth[0] = _computeGapMeanWidth(calib_line_1);
channelInfo.channelWidth[1] = _computeGapMeanWidth(calib_line_2);
channelInfo.channelDepth[0] = _computeGapMeanDepth(calib_line_1, data_lines);
channelInfo.channelDepth[1] = _computeGapMeanDepth(calib_line_2, data_lines);
return channelInfo;
}