diff --git a/beltTearingDetection_test/beltTearingDetection_test.vcxproj b/beltTearingDetection_test/beltTearingDetection_test.vcxproj index aaa99d0..a634840 100644 --- a/beltTearingDetection_test/beltTearingDetection_test.vcxproj +++ b/beltTearingDetection_test/beltTearingDetection_test.vcxproj @@ -42,13 +42,13 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode diff --git a/rodAndBarDetection/rodAndBarDetection.vcxproj b/rodAndBarDetection/rodAndBarDetection.vcxproj index 4bae6c4..6bae8c4 100644 --- a/rodAndBarDetection/rodAndBarDetection.vcxproj +++ b/rodAndBarDetection/rodAndBarDetection.vcxproj @@ -48,13 +48,13 @@ DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode diff --git a/rodAndBarDetection_test/rodAndBarDetection_test.cpp b/rodAndBarDetection_test/rodAndBarDetection_test.cpp index 06523df..e94b956 100644 --- a/rodAndBarDetection_test/rodAndBarDetection_test.cpp +++ b/rodAndBarDetection_test/rodAndBarDetection_test.cpp @@ -165,6 +165,49 @@ void _outputScanDataFile(char* fileName, std::vector& screwInfo) { std::ofstream sw(fileName); @@ -181,6 +224,23 @@ void _outputChanneltInfo(char* fileName, std::vector& scre sw.close(); } +void _outputRodtInfo(char* fileName, std::vector& rodInfo) +{ + std::ofstream sw(fileName); + + char dataStr[250]; + int objNum = (int)rodInfo.size(); + for (int i = 0; i < objNum; i++) + { + sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_axia( %g, %g, %g ), dir_normal_( %g, %g, %g )", + i + 1, rodInfo[i].center.x, rodInfo[i].center.y, rodInfo[i].center.z, + rodInfo[i].axialDir.x, rodInfo[i].axialDir.y, rodInfo[i].axialDir.z, + rodInfo[i].normalDir.x, rodInfo[i].normalDir.y, rodInfo[i].normalDir.z); + sw << dataStr << std::endl; + } + sw.close(); +} + void _outputRGBDScan_RGBD( char* fileName, std::vector>& scanLines, @@ -317,21 +377,161 @@ void _outputRGBDScan_RGBD( sw.close(); } -#define TEST_GROUP 1 -int main() +void _outputRGBDScan_RGBD_rodInfo( + char* fileName, + std::vector>& scanLines, + std::vector& rodInfo +) { - const char* dataPath[TEST_GROUP] = { + int lineNum = (int)scanLines.size(); + std::ofstream sw(fileName); + int realLines = lineNum; + int objNum = (int)rodInfo.size(); + if (objNum > 0) + realLines += 1; + + sw << "LineNum:" << realLines << std::endl; + sw << "DataType: 0" << std::endl; + sw << "ScanSpeed: 0" << std::endl; + sw << "PointAdjust: 1" << std::endl; + sw << "MaxTimeStamp: 0_0" << std::endl; + + int maxLineIndex = 0; + int max_stamp = 0; + + SG_color rgb = { 0, 0, 0 }; + + SG_color objColor[8] = { + {245,222,179},//淡黄色 + {210,105, 30},//巧克力色 + {240,230,140},//黄褐色 + {135,206,235},//天蓝色 + {250,235,215},//古董白 + {189,252,201},//薄荷色 + {221,160,221},//梅红色 + {188,143,143},//玫瑰红色 + }; + int size = 1; + int lineIdx = 0; + for (int line = 0; line < lineNum; line++) + { + int linePtNum = (int)scanLines[line].size(); + if (linePtNum == 0) + continue; + + sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl; + lineIdx++; + for (int i = 0; i < linePtNum; i++) + { + SVzNL3DPosition* pt3D = &scanLines[line][i]; + if (pt3D->nPointIdx > 0) + { + int centerFlag = pt3D->nPointIdx >> 4; + if (centerFlag > 0) + { + rgb = { 250, 0, 0 }; + size = 6; + } + else + { + rgb = objColor[pt3D->nPointIdx % 8]; + size = 3; + } + + + } + else //if (pt3D->nPointIdx == 0) + { + rgb = { 200, 200, 200 }; + size = 1; + } + float x = (float)pt3D->pt3D.x; + float y = (float)pt3D->pt3D.y; + float z = (float)pt3D->pt3D.z; + sw << "{" << x << "," << y << "," << z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl; + } + } + + if (objNum > 0) + { + sw << "Line_" << lineIdx << "_0_" << objNum << std::endl; + rgb = { 250, 0, 0 }; + size = 8; + for (int i = 0; i < objNum; i++) + { + float x = (float)rodInfo[i].center.x; + float y = (float)rodInfo[i].center.y; + float z = (float)rodInfo[i].center.z; + sw << "{" << x << "," << y << "," << z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl; + } + //多输出一个,修正显示工具bug + float x = (float)rodInfo[0].center.x; + float y = (float)rodInfo[0].center.y; + float z = (float)rodInfo[0].center.z; + sw << "{" << x << "," << y << "," << z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl; + + //输出法向 + size = 1; + double len = 60; + lineIdx = 0; + for (int i = 0; i < objNum; i++) + { + SVzNL3DPoint pt0 = { rodInfo[i].center.x - len * rodInfo[i].axialDir.x, + rodInfo[i].center.y - len * rodInfo[i].axialDir.y, + rodInfo[i].center.z - len * rodInfo[i].axialDir.z }; + SVzNL3DPoint pt1 = { rodInfo[i].center.x + len * rodInfo[i].axialDir.x, + rodInfo[i].center.y + len * rodInfo[i].axialDir.y, + rodInfo[i].center.z + len * rodInfo[i].axialDir.z }; + //显示法向量 + sw << "Poly_" << lineIdx << "_2" << std::endl; + sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl; + sw << "{" << pt1.x << "," << pt1.y << "," << pt1.z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl; + lineIdx++; + } + //多输出一个,修正显示工具bug + SVzNL3DPoint pt0 = { rodInfo[0].center.x - len * rodInfo[0].axialDir.x, + rodInfo[0].center.y - len * rodInfo[0].axialDir.y, + rodInfo[0].center.z - len * rodInfo[0].axialDir.z }; + SVzNL3DPoint pt1 = { rodInfo[0].center.x + len * rodInfo[0].axialDir.x, + rodInfo[0].center.y + len * rodInfo[0].axialDir.y, + rodInfo[0].center.z + len * rodInfo[0].axialDir.z }; + //显示法向量 + sw << "Poly_" << lineIdx << "_2" << std::endl; + sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl; + sw << "{" << pt1.x << "," << pt1.y << "," << pt1.z << "}-"; + sw << "{0,0}-{0,0}-"; + sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl; + lineIdx++; + } + sw.close(); +} +#define SCREW_TEST_GROUP 1 +void screwTest(void) +{ + const char* dataPath[SCREW_TEST_GROUP] = { "F:/ShangGu/项目/冠钦项目/螺杆测量/数据/模拟数据/", //0 }; - SVzNLRange fileIdx[TEST_GROUP] = { + SVzNLRange fileIdx[SCREW_TEST_GROUP] = { {1,4}, }; const char* ver = wd_rodAndBarDetectionVersion(); printf("ver:%s\n", ver); - for (int grp = 0; grp < TEST_GROUP; grp++) + for (int grp = 0; grp < SCREW_TEST_GROUP; grp++) { for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) { @@ -392,7 +592,113 @@ int main() _outputChanneltInfo(_scan_file, screwInfo); } } +} +#define ROD_POSITION_TEST_GROUP 1 +void rodPositionTest(void) +{ + const char* dataPath[ROD_POSITION_TEST_GROUP] = { + "F:/ShangGu/项目/冠钦项目/棒材抓取/", //0 + }; + + SVzNLRange fileIdx[ROD_POSITION_TEST_GROUP] = { + {1,8}, + }; + + const char* ver = wd_rodAndBarDetectionVersion(); + printf("ver:%s\n", ver); + + for (int grp = 0; grp < ROD_POSITION_TEST_GROUP; grp++) + { + SSG_planeCalibPara poseCalibPara; + //初始化成单位阵 + poseCalibPara.planeCalib[0] = 1.0; + poseCalibPara.planeCalib[1] = 0.0; + poseCalibPara.planeCalib[2] = 0.0; + poseCalibPara.planeCalib[3] = 0.0; + poseCalibPara.planeCalib[4] = 1.0; + poseCalibPara.planeCalib[5] = 0.0; + poseCalibPara.planeCalib[6] = 0.0; + poseCalibPara.planeCalib[7] = 0.0; + poseCalibPara.planeCalib[8] = 1.0; + poseCalibPara.planeHeight = -1.0; + for (int i = 0; i < 9; i++) + poseCalibPara.invRMatrix[i] = poseCalibPara.planeCalib[i]; + //char calibFile[250]; + //sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]); + //poseCalibPara = _readCalibPara(calibFile); + + for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) + { + fidx =1; + char _scan_file[256]; + sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx); + + std::vector> scanLines; + wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines); + + //转成plyTxt格式 + //sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx); + //wdSavePlyTxt(_scan_file, scanLines); + + long t1 = (long)GetTickCount64();//统计时间 + + SSX_rodParam rodParam; + rodParam.diameter = 52.0; //圆棒直径 + rodParam.len = 290; + + SSG_cornerParam cornerParam; + cornerParam.cornerTh = 60; //45度角 + cornerParam.scale = rodParam.diameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8; + cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4; + cornerParam.minEndingGap_z = 5.0; + cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平 + cornerParam.jumpCornerTh_2 = 60; + + SSG_outlierFilterParam filterParam; + filterParam.continuityTh = 5.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声 + filterParam.outlierTh = 5; + + SSG_treeGrowParam growParam; + growParam.maxLineSkipNum = 5; + growParam.yDeviation_max = 10.0; + growParam.maxSkipDistance = 10.0; + growParam.zDeviation_max = 10.0;// + growParam.minLTypeTreeLen = 100; //mm, 螺杆长度 + growParam.minVTypeTreeLen = 100; //mm + + bool isHorizonScan = true; //true:激光线平行槽道;false:激光线垂直槽道 + int errCode = 0; + std::vector rodInfo; + sx_rodPositioning( + scanLines, + poseCalibPara, + cornerParam, + filterParam, + growParam, + rodParam, + rodInfo, + &errCode); + + long t2 = (long)GetTickCount64(); + printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1)); + //输出测试结果 + sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx); + _outputRGBDScan_RGBD_rodInfo(_scan_file, scanLines, rodInfo); + sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx); + _outputRodtInfo(_scan_file, rodInfo); + } + } +} + +int main() +{ +#if 0 //螺杆定位测试 + screwTest(); +#else //棒材抓取定位测试 + rodPositionTest(); +#endif + return 0; } // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 diff --git a/rodAndBarDetection_test/rodAndBarDetection_test.vcxproj b/rodAndBarDetection_test/rodAndBarDetection_test.vcxproj index a5d5c8d..e1fed7d 100644 --- a/rodAndBarDetection_test/rodAndBarDetection_test.vcxproj +++ b/rodAndBarDetection_test/rodAndBarDetection_test.vcxproj @@ -42,13 +42,13 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode diff --git a/sourceCode/SG_baseAlgo_Export.h b/sourceCode/SG_baseAlgo_Export.h index a710163..be6d586 100644 --- a/sourceCode/SG_baseAlgo_Export.h +++ b/sourceCode/SG_baseAlgo_Export.h @@ -149,6 +149,14 @@ SG_APISHARED_EXPORT void wd_getRingArcFeature( SVzNLRangeD ringArcWidth, //ӵĻ std::vector& line_ringArcs // ); +//ݰArcĶZСֵZСֵĹս +SG_APISHARED_EXPORT void wd_getRodArcFeature_peakCornerMethod( + std::vector< SVzNL3DPosition>& lineData, + int lineIdx, + const double peakChkWin, + const SSG_cornerParam cornerPara, + std::vector& line_rodArcs // +); /// /// ȡϵĹյPSM LVTypeFeature, BQȹյ㷨Ļϵİ汾 @@ -269,6 +277,13 @@ SG_APISHARED_EXPORT void sg_getLineLocalPeaks( std::vector< SSG_basicFeature1D>& localMax, std::vector< SSG_basicFeature1D>& localMin); +SG_APISHARED_EXPORT void sg_getLineLocalPeaks_2( + std::vector& lineData, + int lineIdx, + const double scaleWin, + std::vector< SSG_basicFeature1D>& localZMax, + std::vector< SSG_basicFeature1D>& localZMin); + SG_APISHARED_EXPORT void sg_getFlatLineLocalPeaks_vector( std::vector& lineData, int lineIdx, @@ -303,6 +318,12 @@ SG_APISHARED_EXPORT void wd_getSegFeatureGrowingTrees( std::vector& feature_trees, SSG_treeGrowParam growParam); +//rodArcfeature +SG_APISHARED_EXPORT void wd_getRodArcFeatureGrowingTrees( + std::vector>& all_lineFeatures, + std::vector& feature_trees, + const SSG_treeGrowParam growParam); + SG_APISHARED_EXPORT void sg_lineFeaturesGrowing( int lineIdx, bool isLastLine, diff --git a/sourceCode/SG_baseDataType.h b/sourceCode/SG_baseDataType.h index 267b853..d6e497e 100644 --- a/sourceCode/SG_baseDataType.h +++ b/sourceCode/SG_baseDataType.h @@ -257,6 +257,18 @@ typedef struct double featureValue; }SWD_segFeature; +typedef struct +{ + int lineIdx; + int startPtIdx; + int endPtIdx; + int peakPtIdx; + SVzNL3DPoint startPt; + SVzNL3DPoint endPt; + SVzNL3DPoint peakPt; + double featureValue; +}SWD_rodArcFeature; + typedef struct { double sameGapTh; @@ -352,6 +364,15 @@ typedef struct std::vector< SWD_segFeature> treeNodes; }SWD_segFeatureTree; +typedef struct +{ + int treeState; + int sLineIdx; + int eLineIdx; + double tree_value; + std::vector< SWD_rodArcFeature> treeNodes; +}SWD_rodArcFeatureTree; + typedef struct { int vTreeFlag; @@ -549,6 +570,8 @@ typedef struct typedef struct { int pntIdx; + int forwardPntIdx; + int backwardPntIdx; int type; double forwardAngle; //ǰ double backwardAngle; // diff --git a/sourceCode/SG_featureGrow.cpp b/sourceCode/SG_featureGrow.cpp index 4f0044f..1610126 100644 --- a/sourceCode/SG_featureGrow.cpp +++ b/sourceCode/SG_featureGrow.cpp @@ -146,6 +146,36 @@ bool _segFeatureGrowing(SWD_segFeature& a_feature, const int lineIdx, std::vecto return false; } +//segment featuretreesѰҺʵûкʵ㣬 false +bool _rodArcFeatureGrowing(SWD_rodArcFeature& a_feature, const int lineIdx, std::vector& trees, const SSG_treeGrowParam growParam) +{ + for (int i = 0, i_max = (int)trees.size(); i < i_max; i++) + { + SWD_rodArcFeatureTree& a_tree = trees[i]; + if (TREE_STATE_DEAD == a_tree.treeState) + continue; + // + SWD_rodArcFeature last_node = a_tree.treeNodes.back(); + if (last_node.lineIdx == a_feature.lineIdx) //xΪlineIdxͬһɨϵIJ + continue; + + //ж + double y_diff_1 = abs(a_feature.peakPt.y - last_node.peakPt.y); + double z_diff_1 = abs(a_feature.peakPt.z - last_node.peakPt.z); + int line_diff = abs(a_feature.lineIdx - last_node.lineIdx); + double x_diff = abs(a_feature.peakPt.x - last_node.peakPt.x); + if ((y_diff_1 < growParam.yDeviation_max) && (z_diff_1 < growParam.zDeviation_max) && + ((line_diff < growParam.maxLineSkipNum) || (x_diff < growParam.maxSkipDistance))) + { + a_tree.eLineIdx = lineIdx; + a_tree.treeNodes.push_back(a_feature); + a_tree.tree_value += (a_feature.startPt.z + a_feature.endPt.z) / 2; + return true; + } + } + return false; +} + int _getMatchedTree_angleCheck( SSG_basicFeature1D& a_feature, const int lineIdx, @@ -638,7 +668,7 @@ void wd_getFeatureGrowingTrees_noTypeMatch( void wd_getSegFeatureGrowingTrees( std::vector>& all_lineFeatures, std::vector& feature_trees, - SSG_treeGrowParam growParam) + const SSG_treeGrowParam growParam) { for (int i = 0, i_max = (int)all_lineFeatures.size(); i < i_max; i++) { @@ -702,6 +732,76 @@ void wd_getSegFeatureGrowingTrees( } +void wd_getRodArcFeatureGrowingTrees( + std::vector>& all_lineFeatures, + std::vector& feature_trees, + SSG_treeGrowParam growParam) +{ + for (int i = 0, i_max = (int)all_lineFeatures.size(); i < i_max; i++) + { + if (i == 424) + int kkk = 1; + std::vector& a_lineFeatures = all_lineFeatures[i]; + for (int j = 0, j_max = (int)a_lineFeatures.size(); j < j_max; j++) + { + SWD_rodArcFeature& a_feature = a_lineFeatures[j]; + bool isMatched = _rodArcFeatureGrowing(a_feature, i, feature_trees, growParam); + if (false == isMatched) + { + //µ + SWD_rodArcFeatureTree a_newTree; + a_newTree.treeNodes.push_back(a_feature); + a_newTree.treeState = TREE_STATE_ALIVE; + a_newTree.sLineIdx = a_feature.lineIdx; + a_newTree.eLineIdx = a_feature.lineIdx; + a_newTree.tree_value = (a_feature.startPt.z + a_feature.endPt.z) / 2; + feature_trees.push_back(a_newTree); + } + } + //ֹͣ,١ + //ڵΪ1Ƴ + int lineIdx = i; + int m_max = (int)feature_trees.size(); + for (int m = m_max - 1; m >= 0; m--) //ӺǰɾӰѭ + { + if (TREE_STATE_ALIVE == feature_trees[m].treeState) + { + int line_diff = abs(lineIdx - feature_trees[m].treeNodes.back().lineIdx); + if (line_diff > 0) + { + SWD_rodArcFeature* first_node = &(feature_trees[m].treeNodes[0]); + SWD_rodArcFeature* last_node = &(feature_trees[m].treeNodes[feature_trees[m].treeNodes.size() - 1]); + double len = sqrt(pow(first_node->peakPt.x - last_node->peakPt.x, 2) + + pow(first_node->peakPt.y - last_node->peakPt.y, 2) + + pow(first_node->peakPt.z - last_node->peakPt.z, 2)); + int tree_lines = feature_trees[m].eLineIdx - feature_trees[m].sLineIdx; + if (tree_lines > 0) + { + double mean_stepping = len / tree_lines; + double x_skip = mean_stepping * line_diff; + if (((growParam.maxLineSkipNum > 0) && (line_diff > growParam.maxLineSkipNum)) || + ((growParam.maxLineSkipNum <= 0) && (x_skip > growParam.maxSkipDistance)) || + (i == i_max - 1)) + { + feature_trees[m].treeState = TREE_STATE_DEAD; + if (len <= growParam.minLTypeTreeLen) + feature_trees.erase(feature_trees.begin() + m); + } + } + } + } + } + } + //nodeΪ1treeȥʱ޷ȥnodeΪ1tree + int m_max = (int)feature_trees.size(); + for (int m = m_max - 1; m >= 0; m--) //ӺǰɾӰѭ + { + int tree_lines = feature_trees[m].eLineIdx - feature_trees[m].sLineIdx; + if (tree_lines == 0) + feature_trees.erase(feature_trees.begin() + m); + } +} + void sg_lineFeaturesGrowing( int lineIdx, bool isLastLine, diff --git a/sourceCode/SG_lineFeature.cpp b/sourceCode/SG_lineFeature.cpp index 0d8cdf9..9f2c1ec 100644 --- a/sourceCode/SG_lineFeature.cpp +++ b/sourceCode/SG_lineFeature.cpp @@ -443,6 +443,359 @@ void sg_lineDataRemoveOutlier_ptDistMethod(SVzNL3DPosition* lineData, int dataSi return; } +/// +/// ȡϵļֵ㣨ֵͼСֵ㣩 +/// +/// +void sg_getLineLocalPeaks( + SVzNL3DPosition* lineData, + int dataSize, + int lineIdx, + const double scaleWin, + std::vector< SSG_basicFeature1D>& localMax, + std::vector< SSG_basicFeature1D>& localMin) +{ + if (dataSize < 2) + return; + + int _state = 0; + int pre_i = -1; + int sEdgePtIdx = -1; + int eEdgePtIdx = -1; + SVzNL3DPosition* pre_data = NULL; + std::vector< SVzNL3DPosition> pkTop; + std::vector< SVzNL3DPosition> pkBtm; + for (int i = 0; i < dataSize; i++) + { + lineData[i].nPointIdx = i; + SVzNL3DPosition* curr_data = &lineData[i]; + if (curr_data->pt3D.z < 1e-4) + { + if (i == dataSize - 1) //һ + { + if (1 == _state) // + { + pkTop.push_back(lineData[eEdgePtIdx]); + } + else if (2 == _state) //½ + { + pkBtm.push_back(lineData[eEdgePtIdx]); + } + } + continue; + } + + if (NULL == pre_data) + { + sEdgePtIdx = i; + eEdgePtIdx = i; + pre_data = curr_data; + pre_i = i; + continue; + } + + eEdgePtIdx = i; + double z_diff = curr_data->pt3D.z - pre_data->pt3D.z; + switch (_state) + { + case 0: //̬ + if (z_diff > 0) //½ + { + _state = 2; + } + else if (z_diff < 0) // + { + _state = 1; + } + break; + case 1: // + if (z_diff > 0) //½ + { + pkTop.push_back(*pre_data); + _state = 2; + } + break; + case 2: //½ + if (z_diff < 0) // + { + pkBtm.push_back(*pre_data); + _state = 1; + } + break; + default: + _state = 0; + break; + } + pre_data = curr_data; + pre_i = i; + } + //ע⣺һΪλ + + //Сֵ㣨嶥 + //ֵȽϣڳ߶ȴѰҾֲֵ + double square_distTh = scaleWin * scaleWin; + for (int i = 0, i_max = (int)pkTop.size(); i < i_max; i++) + { + bool isPeak = true; + //ǰ + for (int j = i - 1; j >= 0; j--) + { + double dist = pow(pkTop[i].pt3D.y - pkTop[j].pt3D.y, 2); // + pow(pkTop[i].pt3D.x - pkTop[j].pt3D.x, 2) ; + if (dist > square_distTh) //߶ȴ + break; + + if (pkTop[i].pt3D.z > pkTop[j].pt3D.z) + { + isPeak = false; + break; + } + } + // + if (true == isPeak) + { + for (int j = i + 1; j < i_max; j++) + { + double dist = pow(pkTop[i].pt3D.y - pkTop[j].pt3D.y, 2); // +pow(pkTop[i].pt3D.x - pkTop[j].pt3D.x, 2); + if (dist > square_distTh) //߶ȴ + break; + + if (pkTop[i].pt3D.z > pkTop[j].pt3D.z) + { + isPeak = false; + break; + } + } + } + if (true == isPeak) + { + SSG_basicFeature1D a_feature; + a_feature.featureType = LINE_FEATURE_PEAK_TOP; + a_feature.jumpPos = pkTop[i].pt3D; + a_feature.jumpPos2D = { lineIdx, pkTop[i].nPointIdx }; + localMin.push_back(a_feature); + } + } + //ֵ㣨ȵף + for (int i = 0, i_max = (int)pkBtm.size(); i < i_max; i++) + { + bool isPeak = true; + //ǰ + for (int j = i - 1; j >= 0; j--) + { + double dist = pow(pkBtm[i].pt3D.y - pkBtm[j].pt3D.y, 2); // +pow(pkBtm[i].pt3D.x - pkBtm[j].pt3D.x, 2); + if (dist > square_distTh) //߶ȴ + break; + + if (pkBtm[i].pt3D.z < pkBtm[j].pt3D.z) + { + isPeak = false; + break; + } + } + // + if (true == isPeak) + { + for (int j = i + 1; j < i_max; j++) + { + double dist = pow(pkBtm[i].pt3D.y - pkBtm[j].pt3D.y, 2); // +pow(pkBtm[i].pt3D.x - pkBtm[j].pt3D.x, 2); + if (dist > square_distTh) //߶ȴ + break; + + if (pkBtm[i].pt3D.z < pkBtm[j].pt3D.z) + { + isPeak = false; + break; + } + } + } + if (true == isPeak) + { + SSG_basicFeature1D a_feature; + a_feature.featureType = LINE_FEATURE_PEAK_BOTTOM; + a_feature.jumpPos = pkBtm[i].pt3D; + a_feature.jumpPos2D = { lineIdx, pkBtm[i].nPointIdx }; + localMax.push_back(a_feature); + } + } + + return; +} + +void sg_getLineLocalPeaks_2( + std::vector& lineData, + int lineIdx, + const double scaleWin, + std::vector< SSG_basicFeature1D>& localZMax, + std::vector< SSG_basicFeature1D>& localZMin) +{ + int dataSize = (int)lineData.size(); + if (dataSize < 2) + return; + + int _state = 0; + int pre_i = -1; + int sEdgePtIdx = -1; + int eEdgePtIdx = -1; + SVzNL3DPosition* pre_data = NULL; + std::vector< SVzNL3DPosition> zTop; + std::vector< SVzNL3DPosition> zBtm; + for (int i = 0; i < dataSize; i++) + { + if (i == 355) + int kkk = 1; + lineData[i].nPointIdx = i; + SVzNL3DPosition* curr_data = &lineData[i]; + if (curr_data->pt3D.z < 1e-4) + { + if (i == dataSize - 1) //һ + { + if (1 == _state) // + { + zTop.push_back(lineData[eEdgePtIdx]); + } + else if (2 == _state) //½ + { + zBtm.push_back(lineData[eEdgePtIdx]); + } + } + continue; + } + + if (NULL == pre_data) + { + sEdgePtIdx = i; + eEdgePtIdx = i; + pre_data = curr_data; + pre_i = i; + continue; + } + + eEdgePtIdx = i; + double z_diff = curr_data->pt3D.z - pre_data->pt3D.z; + switch (_state) + { + case 0: //̬ + if (z_diff < 0) //½ + { + _state = 2; + } + else if (z_diff > 0) // + { + _state = 1; + } + break; + case 1: // + if (z_diff <0) //½ + { + zTop.push_back(*pre_data); + _state = 2; + } + break; + case 2: //½ + if (z_diff > 0) // + { + zBtm.push_back(*pre_data); + _state = 1; + } + break; + default: + _state = 0; + break; + } + pre_data = curr_data; + pre_i = i; + } + //ע⣺һΪλ + + //Сֵ㣨嶥 + //ֵȽϣڳ߶ȴѰҾֲֵ + double square_distTh = scaleWin * scaleWin; + for (int i = 0, i_max = (int)zTop.size(); i < i_max; i++) + { + bool isPeak = true; + //ǰ + for (int j = i - 1; j >= 0; j--) + { + double dist = pow(zTop[i].pt3D.y - zTop[j].pt3D.y, 2) + pow(zTop[i].pt3D.z - zTop[j].pt3D.z, 2) ; + if (dist > square_distTh) //߶ȴ + break; + + if (zTop[i].pt3D.z < zTop[j].pt3D.z) + { + isPeak = false; + break; + } + } + // + if (true == isPeak) + { + for (int j = i + 1; j < i_max; j++) + { + double dist = pow(zTop[i].pt3D.y - zTop[j].pt3D.y, 2) + pow(zTop[i].pt3D.z - zTop[j].pt3D.z, 2); + if (dist > square_distTh) //߶ȴ + break; + + if (zTop[i].pt3D.z < zTop[j].pt3D.z) + { + isPeak = false; + break; + } + } + } + if (true == isPeak) + { + SSG_basicFeature1D a_feature; + a_feature.featureType = LINE_FEATURE_PEAK_TOP; + a_feature.jumpPos = zTop[i].pt3D; + a_feature.jumpPos2D = { lineIdx, zTop[i].nPointIdx }; + localZMax.push_back(a_feature); + } + } + //ֵ㣨ȵף + for (int i = 0, i_max = (int)zBtm.size(); i < i_max; i++) + { + bool isPeak = true; + //ǰ + for (int j = i - 1; j >= 0; j--) + { + double dist = pow(zBtm[i].pt3D.y - zBtm[j].pt3D.y, 2) + pow(zBtm[i].pt3D.z - zBtm[j].pt3D.z, 2); + if (dist > square_distTh) //߶ȴ + break; + + if (zBtm[i].pt3D.z > zBtm[j].pt3D.z) + { + isPeak = false; + break; + } + } + // + if (true == isPeak) + { + for (int j = i + 1; j < i_max; j++) + { + double dist = pow(zBtm[i].pt3D.y - zBtm[j].pt3D.y, 2); pow(zBtm[i].pt3D.z - zBtm[j].pt3D.z, 2); + if (dist > square_distTh) //߶ȴ + break; + + if (zBtm[i].pt3D.z > zBtm[j].pt3D.z) + { + isPeak = false; + break; + } + } + } + if (true == isPeak) + { + SSG_basicFeature1D a_feature; + a_feature.featureType = LINE_FEATURE_PEAK_BOTTOM; + a_feature.jumpPos = zBtm[i].pt3D; + a_feature.jumpPos2D = { lineIdx, zBtm[i].nPointIdx }; + localZMin.push_back(a_feature); + } + } + return; +} + /// /// ȡɨеб£¼беڵ֮䡣 /// ͬʱ¼EndingûмӣֻҴʱEndingEnding֮СΪӿȵ1/4 @@ -3429,32 +3782,17 @@ void wd_getLineCornerFeature_PSM( bool compareByPtIdx(const SSG_basicFeature1D& a, const SSG_basicFeature1D& b) { return a.jumpPos2D.y < b.jumpPos2D.y; } -/// -/// ȡϵԲϰλԲĿȷ -/// seg˵㣺z -/// nPointIdx¶Feature -/// 㷨̣ -/// 1ǰǺͺ -/// 2սǣ˳ʱΪʱΪ -/// 3սǵļֵ -/// 4жϹսǷΪ -/// -void wd_getRingArcFeature( + +//ZԷֶ +void _lineDataSegment_zDist( std::vector< SVzNL3DPosition>& lineData, - int lineIdx, - const SSG_cornerParam cornerPara, - SVzNLRangeD ringArcWidth, // - std::vector& line_ringArcs // + std::vector< SVzNL3DPosition>& vldPts, + std::vector& segs, + std::vector& backIndexing, + const SSG_cornerParam cornerPara ) { int dataSize = (int)lineData.size(); - //ȥ - std::vector< SVzNL3DPosition> vldPts; - //std::vector< int> vldPtSegIdx; - std::vector segs; - std::vector backIndexing; - backIndexing.resize(dataSize); - int runIdx = 1; SSG_RUN_EX a_run = { 0, -1, 0, false, false }; //startIdx, len, lastIdx double pre_z = 0; @@ -3515,21 +3853,17 @@ void wd_getRingArcFeature( } if (a_run.len > 0) segs.push_back(a_run); +} -#if 0 - //ñ־ - for (int i = 0, i_max = (int)segs.size(); i < i_max; i++) - { - int idx1 = segs[i].start; - int idx2 = segs[i].start + segs[i].len - 1; - lineData[idx1].nPointIdx |= 0x100000; - lineData[idx2].nPointIdx |= 0x200000; - } -#endif - - //ǰǺͺ - std::vector< SSG_pntDirAngle> corners; - corners.resize(vldPts.size()); +//μ㷽 +void _computeDirAngle_perSeg( + std::vector< SVzNL3DPosition>& vldPts, + std::vector& segs, + const SSG_cornerParam cornerPara, + std::vector< SSG_pntDirAngle>& ptDirAngles +) +{ + ptDirAngles.resize(vldPts.size()); //ν int segSize = (int)segs.size(); for (int segIdx = 0; segIdx < segSize; segIdx++) @@ -3565,12 +3899,14 @@ void wd_getRingArcFeature( //ս if ((pre_i < 0) || (post_i < 0)) { - corners[i].pntIdx = -1; - corners[i].forwardAngle = 0; - corners[i].backwardAngle = 0; - corners[i].corner = 0; - corners[i].forwardDiffZ = 0; - corners[i].backwardDiffZ = 0; + ptDirAngles[i].pntIdx = -1; + ptDirAngles[i].forwardPntIdx = 0; + ptDirAngles[i].backwardPntIdx = 0; + ptDirAngles[i].forwardAngle = 0; + ptDirAngles[i].backwardAngle = 0; + ptDirAngles[i].corner = 0; + ptDirAngles[i].forwardDiffZ = 0; + ptDirAngles[i].backwardDiffZ = 0; } else { @@ -3578,15 +3914,134 @@ void wd_getRingArcFeature( double tanValue_post = (vldPts[post_i].pt3D.z - vldPts[i].pt3D.z) / abs(vldPts[post_i].pt3D.y - vldPts[i].pt3D.y); double forwardAngle = atan(tanValue_post) * 180.0 / PI; double backwardAngle = atan(tanValue_pre) * 180.0 / PI; - corners[i].pntIdx = i; - corners[i].forwardAngle = forwardAngle; - corners[i].backwardAngle = backwardAngle; - corners[i].corner = -(forwardAngle - backwardAngle); //ͼϵϵy෴С- - corners[i].forwardDiffZ = vldPts[post_i].pt3D.z - vldPts[i].pt3D.z; - corners[i].backwardDiffZ = vldPts[i].pt3D.z - vldPts[pre_i].pt3D.z; + ptDirAngles[i].pntIdx = i; + ptDirAngles[i].forwardPntIdx = post_i; + ptDirAngles[i].backwardPntIdx = pre_i; + ptDirAngles[i].forwardAngle = forwardAngle; + ptDirAngles[i].backwardAngle = backwardAngle; + ptDirAngles[i].corner = -(forwardAngle - backwardAngle); //ͼϵϵy෴С- + ptDirAngles[i].forwardDiffZ = vldPts[post_i].pt3D.z - vldPts[i].pt3D.z; + ptDirAngles[i].backwardDiffZ = vldPts[i].pt3D.z - vldPts[pre_i].pt3D.z; } } } +} + +//㷽(ֶΣ +void _computeDirAngle_wholeLine( + std::vector< SVzNL3DPosition>& line_data, + const SSG_cornerParam cornerPara, + std::vector< SSG_pntDirAngle>& ptDirAngles +) +{ + ptDirAngles.resize(line_data.size()); + int dataSize = (int)line_data.size(); + for (int i = 0; i < dataSize; i++) + { + if (line_data[i].pt3D.z < 1e-4) + { + ptDirAngles[i].pntIdx = i; + ptDirAngles[i].forwardPntIdx = 0; + ptDirAngles[i].backwardPntIdx = 0; + ptDirAngles[i].type = -1; + ptDirAngles[i].forwardAngle = 0; + ptDirAngles[i].backwardAngle = 0; + ptDirAngles[i].corner = 0; + ptDirAngles[i].forwardDiffZ = 0; + ptDirAngles[i].backwardDiffZ = 0; + continue; + + } + //ǰѰ + int pre_i = -1; + for (int j = i - 1; j >= 0; j--) + { + if (line_data[j].pt3D.z < 1e-4) + continue; + + double dist = sqrt(pow(line_data[i].pt3D.y - line_data[j].pt3D.y, 2) + + pow(line_data[i].pt3D.z - line_data[j].pt3D.z, 2)); + if (dist >= cornerPara.scale) + { + pre_i = j; + break; + } + } + //Ѱ + int post_i = -1; + for (int j = i + 1; j < dataSize; j++) + { + double dist = sqrt(pow(line_data[i].pt3D.y - line_data[j].pt3D.y, 2) + + pow(line_data[i].pt3D.z - line_data[j].pt3D.z, 2)); + if (dist >= cornerPara.scale) + { + post_i = j; + break; + } + } + //ս + if ((pre_i < 0) || (post_i < 0)) + { + ptDirAngles[i].pntIdx = i; + ptDirAngles[i].type = -1; + ptDirAngles[i].forwardAngle = 0; + ptDirAngles[i].backwardAngle = 0; + ptDirAngles[i].forwardPntIdx = 0; + ptDirAngles[i].backwardPntIdx = 0; + ptDirAngles[i].corner = 0; + ptDirAngles[i].forwardDiffZ = 0; + ptDirAngles[i].backwardDiffZ = 0; + } + else + { + double tanValue_pre = (line_data[i].pt3D.z - line_data[pre_i].pt3D.z) / abs(line_data[i].pt3D.y - line_data[pre_i].pt3D.y); + double tanValue_post = (line_data[post_i].pt3D.z - line_data[i].pt3D.z) / abs(line_data[post_i].pt3D.y - line_data[i].pt3D.y); + double forwardAngle = atan(tanValue_post) * 180.0 / PI; + double backwardAngle = atan(tanValue_pre) * 180.0 / PI; + ptDirAngles[i].pntIdx = i; + ptDirAngles[i].forwardPntIdx = post_i; + ptDirAngles[i].backwardPntIdx = pre_i; + ptDirAngles[i].type = 0; + ptDirAngles[i].forwardAngle = forwardAngle; + ptDirAngles[i].backwardAngle = backwardAngle; + ptDirAngles[i].corner = -(forwardAngle - backwardAngle); //ͼϵϵy෴С- + ptDirAngles[i].forwardDiffZ = line_data[post_i].pt3D.z - line_data[i].pt3D.z; + ptDirAngles[i].backwardDiffZ = line_data[i].pt3D.z - line_data[pre_i].pt3D.z; + } + } +} + +/// +/// ȡϵԲϰλԲĿȷ +/// seg˵㣺z +/// nPointIdx¶Feature +/// 㷨̣ +/// 1ǰǺͺ +/// 2սǣ˳ʱΪʱΪ +/// 3սǵļֵ +/// 4жϹսǷΪ +/// +void wd_getRingArcFeature( + std::vector< SVzNL3DPosition>& lineData, + int lineIdx, + const SSG_cornerParam cornerPara, + SVzNLRangeD ringArcWidth, // + std::vector& line_ringArcs // +) +{ + int dataSize = (int)lineData.size(); + //ȥ + std::vector< SVzNL3DPosition> vldPts; + //std::vector< int> vldPtSegIdx; + std::vector segs; + std::vector backIndexing; + backIndexing.resize(dataSize); + + //zԷֶ + _lineDataSegment_zDist(lineData, vldPts, segs, backIndexing, cornerPara); + //ǰǺͺ + std::vector< SSG_pntDirAngle> ptDirAngles; + _computeDirAngle_perSeg(vldPts, segs, cornerPara, ptDirAngles); //ѰĸcornerΡArcϵÿһ㶼Ǹcorner int vldPtSize = (int)vldPts.size(); @@ -3594,25 +4049,26 @@ void wd_getRingArcFeature( int endIdx = -1; double startAngle = 0; double endAngle = 0; + int segSize = (int)segs.size(); for (int segIdx = 0; segIdx < segSize; segIdx++) { int vPtIdxStart = segs[segIdx].start; int vPtIdxEnd = vPtIdxStart + segs[segIdx].len - 1; for (int i = vPtIdxStart; i <= vPtIdxEnd; i++) { - if (corners[i].corner < 0) + if (ptDirAngles[i].corner < 0) { if (startIdx < 0) { startIdx = i; endIdx = i; - startAngle = corners[i].backwardAngle; - endAngle = corners[i].forwardAngle; + startAngle = ptDirAngles[i].backwardAngle; + endAngle = ptDirAngles[i].forwardAngle; } else { endIdx = i; - endAngle = corners[i].forwardAngle; + endAngle = ptDirAngles[i].forwardAngle; if (i == dataSize - 1) { double totalCorner = abs(endAngle - startAngle); @@ -3631,7 +4087,7 @@ void wd_getRingArcFeature( SWD_segFeature a_ringFeautre; memset(&a_ringFeautre, 0, sizeof(SWD_segFeature)); a_ringFeautre.lineIdx = lineIdx; - if ((corners[preIdx].pntIdx < 0) && (corners[postIdx].pntIdx < 0)) + if ((ptDirAngles[preIdx].pntIdx < 0) && (ptDirAngles[postIdx].pntIdx < 0)) { a_ringFeautre.startPt = vldPts[vPtIdxStart].pt3D; a_ringFeautre.endPt = vldPts[vPtIdxEnd].pt3D; @@ -3671,7 +4127,7 @@ void wd_getRingArcFeature( SWD_segFeature a_ringFeautre; memset(&a_ringFeautre, 0, sizeof(SWD_segFeature)); a_ringFeautre.lineIdx = lineIdx; - if ((corners[preIdx].pntIdx < 0) && (corners[postIdx].pntIdx < 0)) + if ((ptDirAngles[preIdx].pntIdx < 0) && (ptDirAngles[postIdx].pntIdx < 0)) { a_ringFeautre.startPt = vldPts[vPtIdxStart].pt3D; a_ringFeautre.endPt = vldPts[vPtIdxEnd].pt3D; @@ -3700,6 +4156,154 @@ void wd_getRingArcFeature( return; } +//˴ǵZPeakвǵǼԳ߶Ϊ׼ԷΪ׼ +bool _chkRodArcFeature( + int pkIdx, double searchWin, + std::vector< SSG_pntDirAngle>& ptDirAngles, + std::vector< SVzNL3DPosition>& lineData, + const double arcPerPointCornerMinValue, //arcÿתСֵ + const double arcTotalCornerMinValue, //ArcתСֵ + SSG_intPair& a_rodPos) +{ + //pkIdxܻв + double realPkCorner = abs(ptDirAngles[pkIdx].forwardAngle + ptDirAngles[pkIdx].backwardAngle); + int realPkIdx = pkIdx; + //ǰ + for (int i = pkIdx - 1; i >= 0; i--) + { + if (lineData[i].pt3D.z < 1e-4) + continue; + + double dist = sqrt(pow(lineData[pkIdx].pt3D.y - lineData[i].pt3D.y, 2) + pow(lineData[pkIdx].pt3D.z - lineData[i].pt3D.z, 2)); + if (dist > searchWin) + break; + + double flatAngle = abs(ptDirAngles[i].forwardAngle + ptDirAngles[i].backwardAngle); + if (realPkCorner > flatAngle) + { + realPkCorner = flatAngle; + realPkIdx = i; + } + } + // + for (int i = pkIdx + 1; i < (int)lineData.size(); i++) + { + if (lineData[i].pt3D.z < 1e-4) + continue; + + double dist = sqrt(pow(lineData[pkIdx].pt3D.y - lineData[i].pt3D.y, 2) + pow(lineData[pkIdx].pt3D.z - lineData[i].pt3D.z, 2)); + if (dist > searchWin) + break; + + double flatAngle = abs(ptDirAngles[i].forwardAngle + ptDirAngles[i].backwardAngle); + if (realPkCorner > flatAngle) + { + realPkCorner = flatAngle; + realPkIdx = i; + } + } + + if ((ptDirAngles[realPkIdx].forwardAngle > 0) && (ptDirAngles[realPkIdx].backwardAngle < 0) && + (realPkCorner <10) &&(ptDirAngles[realPkIdx].corner < -arcPerPointCornerMinValue)) //ǰΪΪֵȣ<10), սΪֵ10 + { + //ǰ + int pre_idx = -1; + for (int i = realPkIdx - 1; i >= 0; i--) + { + if (ptDirAngles[i].type < 0) + continue; + if (ptDirAngles[i].corner < -arcPerPointCornerMinValue) + pre_idx = i; + else + break; + } + // + int post_idx = -1; + for (int i = realPkIdx + 1; i < (int)ptDirAngles.size(); i++) + { + if (ptDirAngles[i].type < 0) + continue; + if (ptDirAngles[i].corner < -arcPerPointCornerMinValue) + post_idx = i; + else + break; + } + if ((pre_idx >= 0) && (post_idx >= 0)) + { + double totalCornerAngle = ptDirAngles[post_idx].forwardAngle - ptDirAngles[pre_idx].backwardAngle; + if (totalCornerAngle > arcTotalCornerMinValue) //ԲҪ60ȵ + { + a_rodPos.idx = realPkIdx; + a_rodPos.data_0 = pre_idx; + a_rodPos.data_1 = post_idx; + return true; + } + } + } + return false; +} + +/// +/// ȡϵԲϰλ +/// seg˵㣺z +/// nPointIdx¶Feature +/// 㷨̣ +/// 1ǰǺͺ +/// 2ͬĹս +/// 2Zֵ +/// 2սǣ˳ʱΪʱΪ +/// 3սǵļֵ +/// 4жϹսǷΪ +/// +/// +void wd_getRodArcFeature_peakCornerMethod( + std::vector< SVzNL3DPosition>& lineData, + int lineIdx, + const double peakChkWin, + const SSG_cornerParam cornerPara, + std::vector& line_rodArcs // +) +{ + double arcPerPointCornerMinValue = 5; //arcÿתСֵ + double arcTotalCornerMinValue = 45; //ArcתСֵ + //ǰǺͺ + std::vector< SSG_pntDirAngle> ptDirAngles; + _computeDirAngle_wholeLine( lineData, cornerPara, ptDirAngles); + + int dataSize = (int)lineData.size(); + //zֵ + std::vector< SSG_basicFeature1D> localZMax; + std::vector< SSG_basicFeature1D> localZMin; + sg_getLineLocalPeaks_2( lineData, lineIdx, peakChkWin, localZMax, localZMin); + + //Сֵж + int peakNum = (int)localZMin.size(); + for (int i = 0; i < peakNum; i++) + { + int pkIdx = localZMin[i].jumpPos2D.y; + SSG_intPair a_rodPos; + bool isArc = _chkRodArcFeature( + pkIdx, cornerPara.scale, + ptDirAngles, lineData, + arcPerPointCornerMinValue, arcTotalCornerMinValue, + a_rodPos); + if (true == isArc) + { + SWD_rodArcFeature a_rodArc; + memset(&a_rodArc, 0, sizeof(SWD_rodArcFeature)); + a_rodArc.lineIdx = lineIdx; + a_rodArc.startPtIdx = a_rodPos.data_0; + a_rodArc.endPtIdx = a_rodPos.data_1; + a_rodArc.peakPtIdx = a_rodPos.idx; + a_rodArc.startPt = lineData[a_rodPos.data_0].pt3D; + a_rodArc.endPt = lineData[a_rodPos.data_1].pt3D; + a_rodArc.peakPt = lineData[a_rodPos.idx].pt3D; + a_rodArc.featureValue = ptDirAngles[a_rodPos.idx].corner; + line_rodArcs.push_back(a_rodArc); + } + } + return; +} //ȡcornerֵʵֺʹô˺дŻ void _searchCornerPeaks( std::vector< SSG_pntDirAngle>& corners, @@ -5463,184 +6067,6 @@ void wd_getLineGloveArcs( return; } -/// -/// ȡϵļֵ㣨ֵͼСֵ㣩 -/// -/// -void sg_getLineLocalPeaks( - SVzNL3DPosition* lineData, - int dataSize, - int lineIdx, - const double scaleWin, - std::vector< SSG_basicFeature1D>& localMax, - std::vector< SSG_basicFeature1D>& localMin) -{ - if (dataSize < 2) - return; - - int _state = 0; - int pre_i = -1; - int sEdgePtIdx = -1; - int eEdgePtIdx = -1; - SVzNL3DPosition* pre_data = NULL; - std::vector< SVzNL3DPosition> pkTop; - std::vector< SVzNL3DPosition> pkBtm; - for (int i = 0; i < dataSize; i++) - { - lineData[i].nPointIdx = i; - SVzNL3DPosition* curr_data = &lineData[i]; - if (curr_data->pt3D.z < 1e-4) - { - if (i == dataSize - 1) //һ - { - if ( 1 == _state ) // - { - pkTop.push_back(lineData[eEdgePtIdx]); - } - else if (2 == _state) //½ - { - pkBtm.push_back(lineData[eEdgePtIdx]); - } - } - continue; - } - - if (NULL == pre_data) - { - sEdgePtIdx = i; - eEdgePtIdx = i; - pre_data = curr_data; - pre_i = i; - continue; - } - - eEdgePtIdx = i; - double z_diff = curr_data->pt3D.z - pre_data->pt3D.z; - switch (_state) - { - case 0: //̬ - if (z_diff > 0) //½ - { - _state = 2; - } - else if (z_diff < 0) // - { - _state = 1; - } - break; - case 1: // - if (z_diff > 0) //½ - { - pkTop.push_back(*pre_data); - _state = 2; - } - break; - case 2: //½ - if (z_diff < 0) // - { - pkBtm.push_back(*pre_data); - _state = 1; - } - break; - default: - _state = 0; - break; - } - pre_data = curr_data; - pre_i = i; - } - //ע⣺һΪλ - - //Сֵ㣨嶥 - //ֵȽϣڳ߶ȴѰҾֲֵ - double square_distTh = scaleWin * scaleWin; - for (int i = 0, i_max = (int)pkTop.size(); i < i_max; i++) - { - bool isPeak = true; - //ǰ - for (int j = i - 1; j >= 0; j--) - { - double dist = pow(pkTop[i].pt3D.y - pkTop[j].pt3D.y, 2); // + pow(pkTop[i].pt3D.x - pkTop[j].pt3D.x, 2) ; - if (dist > square_distTh) //߶ȴ - break; - - if (pkTop[i].pt3D.z > pkTop[j].pt3D.z) - { - isPeak = false; - break; - } - } - // - if (true == isPeak) - { - for (int j = i + 1; j < i_max; j++) - { - double dist = pow(pkTop[i].pt3D.y - pkTop[j].pt3D.y, 2); // +pow(pkTop[i].pt3D.x - pkTop[j].pt3D.x, 2); - if (dist > square_distTh) //߶ȴ - break; - - if (pkTop[i].pt3D.z > pkTop[j].pt3D.z) - { - isPeak = false; - break; - } - } - } - if (true == isPeak) - { - SSG_basicFeature1D a_feature; - a_feature.featureType = LINE_FEATURE_PEAK_TOP; - a_feature.jumpPos = pkTop[i].pt3D; - a_feature.jumpPos2D = { lineIdx, pkTop[i].nPointIdx }; - localMin.push_back(a_feature); - } - } - //ֵ㣨ȵף - for (int i = 0, i_max = (int)pkBtm.size(); i < i_max; i++) - { - bool isPeak = true; - //ǰ - for (int j = i - 1; j >= 0; j--) - { - double dist = pow(pkBtm[i].pt3D.y - pkBtm[j].pt3D.y, 2); // +pow(pkBtm[i].pt3D.x - pkBtm[j].pt3D.x, 2); - if (dist > square_distTh) //߶ȴ - break; - - if (pkBtm[i].pt3D.z < pkBtm[j].pt3D.z) - { - isPeak = false; - break; - } - } - // - if (true == isPeak) - { - for (int j = i + 1; j < i_max; j++) - { - double dist = pow(pkBtm[i].pt3D.y - pkBtm[j].pt3D.y, 2); // +pow(pkBtm[i].pt3D.x - pkBtm[j].pt3D.x, 2); - if (dist > square_distTh) //߶ȴ - break; - - if (pkBtm[i].pt3D.z < pkBtm[j].pt3D.z) - { - isPeak = false; - break; - } - } - } - if (true == isPeak) - { - SSG_basicFeature1D a_feature; - a_feature.featureType = LINE_FEATURE_PEAK_BOTTOM; - a_feature.jumpPos = pkBtm[i].pt3D; - a_feature.jumpPos2D = { lineIdx, pkBtm[i].nPointIdx }; - localMax.push_back(a_feature); - } - } - - return; -} - #if 0 typedef struct { diff --git a/sourceCode/rodAndBarDetection.cpp b/sourceCode/rodAndBarDetection.cpp index 1d466aa..e5e4e26 100644 --- a/sourceCode/rodAndBarDetection.cpp +++ b/sourceCode/rodAndBarDetection.cpp @@ -6,12 +6,44 @@ #include //version 1.0.0 : base version release to customer -std::string m_strVersion = "1.0.0"; +//version 1.1.0 : ˵ƽͰĶλ +std::string m_strVersion = "1.1.0"; const char* wd_rodAndBarDetectionVersion(void) { return m_strVersion.c_str(); } +//һƽƽ +//пһƽͲοƽƽ棬ߵƽеƽ +//תΪƽƽ淨ΪֱIJ +SSG_planeCalibPara sx_rodPosition_getBaseCalibPara( + std::vector< std::vector>& scanLines) +{ + return sg_getPlaneCalibPara2(scanLines); +} + +//̬ƽȥ +void sx_rodPosition_lineDataR( + std::vector< SVzNL3DPosition>& a_line, + const double* camPoseR, + double groundH) +{ + lineDataRT_vector(a_line, camPoseR, groundH); +} + +SVzNL3DPoint _translatePoint(SVzNL3DPoint point, const double rMatrix[9]) +{ + SVzNL3DPoint result; + double x = point.x * rMatrix[0] + point.y * rMatrix[1] + point.z * rMatrix[2]; + double y = point.x * rMatrix[3] + point.y * rMatrix[4] + point.z * rMatrix[5]; + double z = point.x * rMatrix[6] + point.y * rMatrix[7] + point.z * rMatrix[8]; + result.x = x; + result.y = y; + result.z = z; + return result; +} + + SVzNL3DPoint getArcPeak( std::vector< std::vector>& scanLines, SWD_segFeature & a_arcFeature, @@ -420,5 +452,235 @@ SVzNL3DPoint _ptRotate(SVzNL3DPoint pt3D, double matrix3d[9]) } +void rodAarcFeatueDetection( + std::vector< std::vector>& scanLines, + const SSG_cornerParam cornerPara, + const SSG_outlierFilterParam filterParam, + const double rodDiameter, + std::vector>& arcFeatures) +{ + int lineNum = (int)scanLines.size(); + int linePtNum = (int)scanLines[0].size(); + for (int line = 0; line < lineNum; line++) + { + if (line == 424) + int kkk = 1; + std::vector& lineData = scanLines[line]; + + //˲˳쳣 + sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], linePtNum, filterParam); + //ȡrodArc + std::vector line_rodArcs; + wd_getRodArcFeature_peakCornerMethod(lineData, line, rodDiameter/2, cornerPara, line_rodArcs ); + arcFeatures.push_back(line_rodArcs); + } + return; +} + +void sx_rodPositioning( + std::vector< std::vector>& scanLines, + const SSG_planeCalibPara poseCalibPara, + const SSG_cornerParam cornerPara, + const SSG_outlierFilterParam filterParam, + const SSG_treeGrowParam growParam, + const SSX_rodParam rodParam, + std::vector& rodInfo, + int* errCode) +{ + *errCode = 0; + 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; + } + + for (int i = 0, i_max = (int)scanLines.size(); i < i_max; i++) + { + if (i == 14) + int kkk = 1; + //д + //ƽȥ + double cuttingZ = -1; + sx_rodPosition_lineDataR(scanLines[i], poseCalibPara.planeCalib, cuttingZ); + } + + //ˮƽɨ + std::vector> hLines_raw; + hLines_raw.resize(linePtNum); + for (int i = 0; i < linePtNum; i++) + hLines_raw[i].resize(lineNum); + for (int line = 0; line < lineNum; line++) + { + for (int j = 0; j < linePtNum; j++) + { + scanLines[line][j].nPointIdx = 0; //ԭʼݵ0תʹã + hLines_raw[j][line] = scanLines[line][j]; + hLines_raw[j][line].pt3D.x = scanLines[line][j].pt3D.y; + hLines_raw[j][line].pt3D.y = scanLines[line][j].pt3D.x; + } + } + + //ڴֱϷֱȡARC + std::vector> arcFeatures_v; + rodAarcFeatueDetection( scanLines, cornerPara, filterParam, rodParam.diameter, arcFeatures_v); + // + std::vector rodArcTrees_v; + wd_getRodArcFeatureGrowingTrees(arcFeatures_v, rodArcTrees_v, growParam); + + //ˮƽ + std::vector> arcFeatures_h; + rodAarcFeatueDetection(hLines_raw, cornerPara, filterParam, rodParam.diameter, arcFeatures_h); + // + std::vector rodArcTrees_h; + wd_getRodArcFeatureGrowingTrees(arcFeatures_h, rodArcTrees_h, growParam); + + if ((rodArcTrees_v.size() == 0) && (rodArcTrees_h.size() == 0)) + { + *errCode = SG_ERR_NOT_GRID_FORMAT; + return; + } + int objNum_v = (int)rodArcTrees_v.size(); + int objNum_h = (int)rodArcTrees_h.size(); + for (int line = 0; line < lineNum; line++) + { + for (int j = 0; j < linePtNum; j++) + { + scanLines[line][j].nPointIdx = 0; //ԭʼݵ0תʹã + } + } + //ñ־debug + for (int i = 0; i < objNum_v; i++) + { + int nodeNum = (int)rodArcTrees_v[i].treeNodes.size(); + for (int j = 0; j < nodeNum; j++) + { + int lineIdx = rodArcTrees_v[i].treeNodes[j].lineIdx; + int centerPtIdx = rodArcTrees_v[i].treeNodes[j].peakPtIdx; + for (int m = rodArcTrees_v[i].treeNodes[j].startPtIdx; m <= rodArcTrees_v[i].treeNodes[j].endPtIdx; m++) + scanLines[lineIdx][m].nPointIdx = 1; + scanLines[lineIdx][centerPtIdx].nPointIdx |= 0x10; + } + } + //ñ־debug + for (int i = 0; i < objNum_h; i++) + { + int nodeNum = (int)rodArcTrees_h[i].treeNodes.size(); + for (int j = 0; j < nodeNum; j++) + { + int ptIdx = rodArcTrees_h[i].treeNodes[j].lineIdx; + int centerLineIdx = rodArcTrees_h[i].treeNodes[j].peakPtIdx; + for (int m = rodArcTrees_h[i].treeNodes[j].startPtIdx; m <= rodArcTrees_h[i].treeNodes[j].endPtIdx; m++) + scanLines[m][ptIdx].nPointIdx |= 2; + scanLines[centerLineIdx][ptIdx].nPointIdx |= 0x20; + } + } + //Ŀж + //(1)ȹ + for (int i = 0; i < (int)rodArcTrees_v.size(); i++) + { + int nodeSize = rodArcTrees_v[i].treeNodes.size(); + SVzNL3DPoint startCenter = rodArcTrees_v[i].treeNodes[0].peakPt; + SVzNL3DPoint endCenter = rodArcTrees_v[i].treeNodes[nodeSize-1].peakPt; + double len = sqrt(pow(startCenter.x - endCenter.x, 2) + + pow(startCenter.y - endCenter.y, 2) + + pow(startCenter.z - endCenter.z, 2)); + double lenDiff = abs(len - rodParam.len); + if (lenDiff < 10.0) //validObj + { + //XYƽֱ + //Ϊ˷ֹ˲Ӱ죬 + std::vector fittingPoints; + for (int j = 0; j < nodeSize; j++) + { + double dist1 = sqrt(pow(rodArcTrees_v[i].treeNodes[j].peakPt.x - startCenter.x, 2) + + pow(rodArcTrees_v[i].treeNodes[j].peakPt.y - startCenter.y, 2) + + pow(rodArcTrees_v[i].treeNodes[j].peakPt.z - startCenter.z, 2)); + double dist2 = sqrt(pow(rodArcTrees_v[i].treeNodes[j].peakPt.x - endCenter.x, 2) + + pow(rodArcTrees_v[i].treeNodes[j].peakPt.y - endCenter.y, 2) + + pow(rodArcTrees_v[i].treeNodes[j].peakPt.z - endCenter.z, 2)); + if ((dist1 > rodParam.diameter / 2) && (dist2 > rodParam.diameter / 2)) + fittingPoints.push_back(rodArcTrees_v[i].treeNodes[j].peakPt); + } + if (fittingPoints.size() < 3) + continue; + // + double _a, _b, _c; + lineFitting_abc(fittingPoints, &_a, &_b, &_c); + int dataSize = (int)fittingPoints.size(); + SVzNL2DPointD foot1 = sx_getFootPoint_abc(fittingPoints[0].x, fittingPoints[0].y, _a, _b, _c); + SVzNL2DPointD foot2 = sx_getFootPoint_abc(fittingPoints[dataSize - 1].x, fittingPoints[dataSize - 1].y, _a, _b, _c); + //ֱߵ + SVzNL3DPoint axialDir = { foot2.x - foot1.x, foot2.y - foot1.y, fittingPoints[dataSize - 1].z - fittingPoints[0].z }; + double theta = atan2(foot2.y - foot1.y, foot2.x - foot1.x); + double sinTheta = sin(theta); + double cosTheta = cos(theta); + SVzNL3DPoint tmpDir = { sinTheta, -cosTheta, 0 }; + SVzNL3DPoint normalDir = { axialDir.y * tmpDir.z - tmpDir.y * axialDir.z, + axialDir.z * tmpDir.x - tmpDir.z * axialDir.x, + axialDir.x * tmpDir.y - tmpDir.x * axialDir.y }; + + SSX_rodPositionInfo a_objRod; + //ȷյ㣺ֱ߾С5mm + double tmpData = sqrt(_a * _a + _b * _b); + _a = _a / tmpData; + _b = _b / tmpData; + _c = _c / tmpData; + SVzNL3DPoint realStart, realEnd; + bool foundStart = false; + for (int j = 0; j < nodeSize; j++) + { + double dist = abs(rodArcTrees_v[i].treeNodes[j].peakPt.x * _a + + rodArcTrees_v[i].treeNodes[j].peakPt.y * _b + _c); + if (dist < 5.0) + { + realStart = rodArcTrees_v[i].treeNodes[j].peakPt; + foundStart = true; + break; + } + } + + + } + } + //2ڵж + + + + //ͶԭϵԱ۱궨ȷ + for (int i = 0; i < lineNum; i++) + sx_rodPosition_lineDataR(scanLines[i], poseCalibPara.invRMatrix, -1); + //Ͷԭϵ + for (int i = 0; i < (int)rodInfo.size(); i++) + { + SSX_rodPositionInfo& a_rod = rodInfo[i]; + SVzNL3DPoint rawObj = _translatePoint(a_rod.center, poseCalibPara.invRMatrix); + a_rod.center = rawObj; + rawObj = _translatePoint(a_rod.axialDir, poseCalibPara.invRMatrix); + a_rod.axialDir = rawObj; + rawObj = _translatePoint(a_rod.normalDir, poseCalibPara.invRMatrix); + a_rod.normalDir = rawObj; + } + return; +} + diff --git a/sourceCode/rodAndBarDetection_Export.h b/sourceCode/rodAndBarDetection_Export.h index 8b1a0fa..1c496bb 100644 --- a/sourceCode/rodAndBarDetection_Export.h +++ b/sourceCode/rodAndBarDetection_Export.h @@ -12,9 +12,38 @@ typedef struct double rotateAngle; //-30 - 30 }SSX_hexHeadScrewInfo; //ͷݸ +typedef struct +{ + double diameter; + double len; +}SSX_rodParam; //Ϣ + +typedef struct +{ + SVzNL3DPoint center; //ݸ˶˲ĵ + SVzNL3DPoint axialDir; // + SVzNL3DPoint normalDir; // + SVzNL3DPoint startPt; + SVzNL3DPoint endPt; +}SSX_rodPositionInfo; + //汾 SG_APISHARED_EXPORT const char* wd_rodAndBarDetectionVersion(void); +//һƽƽ +//пһƽͲοƽƽ棬ߵƽеƽ +//תΪƽƽ淨ΪֱIJ +SG_APISHARED_EXPORT SSG_planeCalibPara sx_rodPosition_getBaseCalibPara( + std::vector< std::vector>& scanLines); + +#if 0 +//̬ƽȥ +SG_APISHARED_EXPORT void sx_rodPosition_lineDataR( + std::vector< SVzNL3DPosition>& a_line, + const double* camPoseR, + double groundH); +#endif + //ͷݸ˶˲ĵ SG_APISHARED_EXPORT void sx_hexHeadScrewMeasure( std::vector< std::vector>& scanLines, @@ -25,3 +54,13 @@ SG_APISHARED_EXPORT void sx_hexHeadScrewMeasure( double rodDiameter, std::vector& screwInfo, int* errCode); + +SG_APISHARED_EXPORT void sx_rodPositioning( + std::vector< std::vector>& scanLines, + const SSG_planeCalibPara poseCalibPara, + const SSG_cornerParam cornerPara, + const SSG_outlierFilterParam filterParam, + const SSG_treeGrowParam growParam, + const SSX_rodParam rodParam, + std::vector& rodInfo, + int* errCode); \ No newline at end of file