diff --git a/BQ_workpieceCornerExtract_test/BQ_workpieceCornerExtract_test.cpp b/BQ_workpieceCornerExtract_test/BQ_workpieceCornerExtract_test.cpp index 8355732..92f6c10 100644 --- a/BQ_workpieceCornerExtract_test/BQ_workpieceCornerExtract_test.cpp +++ b/BQ_workpieceCornerExtract_test/BQ_workpieceCornerExtract_test.cpp @@ -649,7 +649,7 @@ void _outputRGBDScanLapWeld_RGBD( #define CONVERT_TO_GRID 0 #define TEST_COMPUTE_CALIB_PARA 0 #define TEST_COMPUTE_CORNER 1 -#define TEST_GROUP 8 +#define TEST_GROUP 9 int main() { const char* dataPath[TEST_GROUP] = { @@ -661,10 +661,11 @@ int main() "F:/ShangGu/项目/冠钦_博清科技/数据/工件点云/", //5 "F:/ShangGu/项目/冠钦_博清科技/数据/顶板样式/", //6 "F:/ShangGu/项目/冠钦_博清科技/定位纠偏/现场数据/0107/", //7 + "F:/ShangGu/项目/冠钦_博清科技/定位纠偏/现场数据/LaserDetectResult/", //8 }; SVzNLRange fileIdx[TEST_GROUP] = { - {1,3}, {6,8}, {6,8}, {6,8}, {6,8}, {9,11}, {2,4}, {1,4} + {1,3}, {6,8}, {6,8}, {6,8}, {6,8}, {9,11}, {2,4}, {1,4}, {1,10} }; #if CONVERT_TO_GRID @@ -690,8 +691,9 @@ int main() #endif #if TEST_COMPUTE_CALIB_PARA + int cvt_grp = 8; char _calib_datafile[256]; - sprintf_s(_calib_datafile, "%sLaserline_1.txt", dataPath[7]); + sprintf_s(_calib_datafile, "%s1.txt", dataPath[cvt_grp]); int lineNum = 0; float lineV = 0.0f; int dataCalib = 0; @@ -727,10 +729,10 @@ int main() } // char calibFile[250]; - sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[7]); + sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[cvt_grp]); _outputCalibPara(calibFile, calibPara); char _out_file[256]; - sprintf_s(_out_file, "%sscanData_ground_1_calib.txt", dataPath[7]); + sprintf_s(_out_file, "%sscanData_ground_1_calib.txt", dataPath[cvt_grp]); int headNullLines = 0; _outputScanDataFile_vector(_out_file, scanData, false, &headNullLines); printf("%s: calib done!\n", _calib_datafile); @@ -741,7 +743,7 @@ int main() const char* ver = wd_BQWorkpieceCornerVersion(); printf("ver:%s\n", ver); - for (int grp = 7; grp <= 7; grp++) + for (int grp = 8; grp <= 8; grp++) { SSG_planeCalibPara poseCalibPara; //初始化成单位阵 @@ -763,7 +765,7 @@ int main() for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) { - //fidx =4; + fidx =7; char _scan_file[256]; if(0 == grp) sprintf_s(_scan_file, "%sscanData_%d_grid.txt", dataPath[grp], fidx); @@ -771,6 +773,8 @@ int main() sprintf_s(_scan_file, "%s节点%d.txt", dataPath[grp], fidx); else if (7 == grp) sprintf_s(_scan_file, "%sLaserline_%d.txt", dataPath[grp], fidx); + else if (8 == grp) + sprintf_s(_scan_file, "%s%d.txt", dataPath[grp], fidx); else sprintf_s(_scan_file, "%s%d_LazerData_Hi229229.txt", dataPath[grp], fidx); std::vector> scanLines; @@ -800,7 +804,7 @@ int main() } #if 0 char _out_file[256]; - sprintf_s(_out_file, "%sscanData_%d_calib.txt", dataPath[grp], fidx); + sprintf_s(_out_file, "%s_%d_leveling.txt", dataPath[grp], fidx); int headNullLines = 0; _outputScanDataFile_vector(_out_file, scanLines, false, &headNullLines); #endif diff --git a/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.cpp b/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.cpp index 3a5556f..829dbd3 100644 --- a/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.cpp +++ b/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.cpp @@ -929,7 +929,7 @@ SSG_planeCalibPara _readCalibPara(char* fileName) #define TEST_COMPUTE_CALIB_PARA 0 #define TEST_COMPUTE_GRASP_POS 1 #define TEST_GROUP 1 -int main() +void sheetPosition_test(void) { const char* dataPath[TEST_GROUP] = { "F:/ShangGu/项目/冠钦项目/温州优匠工品薄片抓取/温州优匠工品薄片数据/", //0 @@ -1097,5 +1097,188 @@ int main() #endif printf("all done!\n"); + return; } +void sheetKeyHeighth_test(void) +{ + const char* dataPath[TEST_GROUP] = { + "F:/ShangGu/项目/吕宁项目/测高/", //0 + }; + + SVzNLRange fileIdx[TEST_GROUP] = { + {1,6} }; + +#if TEST_COMPUTE_CALIB_PARA + int cvt_grp = 0; + char _calib_datafile[256]; + sprintf_s(_calib_datafile, "%s样品_grid_5.txt", dataPath[cvt_grp]); + std::vector> scanLines; + wdReadLaserScanPointFromFile_XYZ_vector(_calib_datafile, scanLines); + if (scanLines.size() > 0) + { + //getROIdata + std::vector> roiScanLines; + SSG_ROIRectD roi2D = { 237.0, 340.0, -60, 6.0 }; + + getROIdata(roi2D, scanLines, roiScanLines); + char calibFile[250]; + sprintf_s(calibFile, "%sgroundData_ROI.txt", dataPath[cvt_grp]); + _outputScanDataFile(calibFile, roiScanLines, 0, 0, 0); + + SSG_planeCalibPara calibPara = wd_sheetPosition_getBaseCalibPara(roiScanLines); + //结果进行验证 + int lineNum = (int)scanLines.size(); + for (int i = 0; i < lineNum; i++) + { + if (i == 14) + int kkk = 1; + //行处理 + //调平,去除地面 + wd_sheetPosition_lineDataR(scanLines[i], calibPara.planeCalib, -1);// calibPara.planeHeight); + } + // + sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[cvt_grp]); + _outputCalibPara(calibFile, calibPara); + char _out_file[256]; + sprintf_s(_out_file, "%sground_grid_calib_verify.txt", dataPath[cvt_grp]); + _outputScanDataFile(_out_file, scanLines, 0, 0, 0); + printf("%s: calib done!\n", _calib_datafile); +#if 1 + for (int fidx = fileIdx[cvt_grp].nMin; fidx <= fileIdx[cvt_grp].nMax; fidx++) + { + char _scan_file[256]; + sprintf_s(_scan_file, "%s样品_grid_%d.txt", dataPath[cvt_grp], fidx); + std::vector> dataLines; + vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, dataLines); + if (dataLines.size() == 0) + continue; + lineNum = (int)dataLines.size(); + for (int i = 0; i < lineNum; i++) + { + if (i == 14) + int kkk = 1; + //行处理 + //调平,去除地面 + wd_sheetPosition_lineDataR(dataLines[i], calibPara.planeCalib, -1);// calibPara.planeHeight); + } + sprintf_s(_out_file, "%s样品_grid_%d_leveling.txt", dataPath[cvt_grp], fidx); + _outputScanDataFile(_out_file, dataLines, 0, 0, 0); + printf("%s: leveling done!\n", _out_file); + } +#endif + } +#endif + +#if TEST_COMPUTE_GRASP_POS + int endGroup = TEST_GROUP - 1; + for (int grp = 0; grp <= endGroup; 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 = 645.0; + for (int i = 0; i < 9; i++) + poseCalibPara.invRMatrix[i] = poseCalibPara.planeCalib[i]; + char calibFile[250]; +#if 1 + if (grp == 0) + { + sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]); + poseCalibPara = _readCalibPara(calibFile); + } +#endif + + SWD_sheetKeyParam sheetKeyParam; + sheetKeyParam.keySize = {8.0, 6.0}; //薄片按键大小 + sheetKeyParam.sheetSize = {41.0,11.0}; //薄片大小 + sheetKeyParam.keyToEdgeDistance = 8.0; //薄片按键距离最近的边的距离 + sheetKeyParam.sheetThickness = 0.4; //薄片厚度0.4mm + sheetKeyParam.nominalKeyHeight = 0.5; + + SWD_sheetAlgoParam algoParam; + memset(&algoParam, 0, sizeof(SWD_sheetAlgoParam)); + algoParam.cornerParam.cornerTh = 40; //45度角 + algoParam.cornerParam.scale = sheetKeyParam.sheetThickness*1.25; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8; + algoParam.cornerParam.minEndingGap = 5; + algoParam.cornerParam.minEndingGap_z = sheetKeyParam.sheetThickness * 0.5; + algoParam.cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平 + algoParam.cornerParam.jumpCornerTh_2 = 30; + SSG_outlierFilterParam filterParam; + algoParam.filterParam.continuityTh = 20.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声 + algoParam.filterParam.outlierTh = 5; + SSG_treeGrowParam growParam; + algoParam.growParam.maxLineSkipNum = 5; + algoParam.growParam.yDeviation_max = 3.0; + algoParam.growParam.maxSkipDistance = 3.0; + algoParam.growParam.zDeviation_max = 3.0;// algoParam.bagParam.bagH / 2; //袋子高度1/2 + algoParam.growParam.minLTypeTreeLen = 100; //mm + algoParam.growParam.minVTypeTreeLen = 100; //mm + + for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) + { + SWD_gripState stateMachine; + memset(&stateMachine, 0, sizeof(SWD_gripState)); + //fidx = 4; + int lineNum = 0; + float lineV = 0.0f; + int dataCalib = 0; + int maxTimeStamp = 0; + int clockPerSecond = 0; + + char _scan_file[256]; + sprintf_s(_scan_file, "%s样品_grid_%d.txt", dataPath[grp], fidx); + std::vector> scanLines; + vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines); + if (scanLines.size() == 0) + continue; + + long t1 = GetTickCount64(); + int errCode = 0; + std::vector resultObjPositions; + wd_computeSheetKeyHeigth( + scanLines, + sheetKeyParam, + poseCalibPara, + algoParam, + &stateMachine, //操作状态机。指示当前状态 + &errCode, + resultObjPositions); + long t2 = GetTickCount64(); + + char _dbg_file[256]; +#if 1 + sprintf_s(_dbg_file, "%sresult\\样品_grid_%d_result.txt", dataPath[grp], fidx); + _outputScanDataFile_RGBD_obj(_dbg_file, scanLines, 0, 0, 0, resultObjPositions); + sprintf_s(_dbg_file, "%sresult\\样品_grid_%d_result_img.png", dataPath[grp], fidx); + cv::String imgName(_dbg_file); + double rpy[3] = { -30, 15, 0 }; //{ 0,-45, 0 }; // + //_genXOYProjectionImage(imgName, laser3DPoints, lineNum, rpy); +#endif + printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1)); + } + } + +#endif + printf("all done!\n"); +} + +int main() +{ +#if 0 + sheetPosition_test(); +#else + sheetKeyHeighth_test(); +#endif + + return 0; + +} \ No newline at end of file diff --git a/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.vcxproj b/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.vcxproj index 18317d6..13edd09 100644 --- a/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.vcxproj +++ b/YouJiang_sheetPositioning_test/YouJiang_sheetPositioning_test.vcxproj @@ -24,6 +24,7 @@ {80cbf888-79f3-424f-a094-17edfd452e1e} YouJiangsheetPositioningtest 10.0 + YouJiang_sheetPositioning_test diff --git a/sourceCode/BQ_workpieceCornerExtraction.cpp b/sourceCode/BQ_workpieceCornerExtraction.cpp index 5b97a5a..4bf9e9e 100644 --- a/sourceCode/BQ_workpieceCornerExtraction.cpp +++ b/sourceCode/BQ_workpieceCornerExtraction.cpp @@ -9,7 +9,8 @@ //version 1.2.0 : add position length output //version 1.2.1 : fix bugs for ver1.2.0 //version 1.3.0 : 㷨ͬһbrachж˾ж -std::string m_strVersion = "1.3.0"; +//version 1.4.0 : ʹսжĿ +std::string m_strVersion = "1.4.0"; const char* wd_BQWorkpieceCornerVersion(void) { return m_strVersion.c_str(); @@ -585,6 +586,256 @@ bool checkSameBranch(SWD_polarPt& corner_1, SWD_polarPt& corner_2, } +//УβXOYƽǰǺͺԼսǡ ǰǣ+ ǣ- +void _computeClosedPntListDirCorners(std::vector& polarPoints, double scale, std::vector< SSG_dirCornerAngle>& dirCornerAngles) +{ + int pntSize = (int)polarPoints.size(); + //std::fill(dirCornerAngles.begin(), dirCornerAngles.end(), SSG_dirCornerAngle{ 0, 0, 0, 0, 0, 0 }); + dirCornerAngles.resize(pntSize); + for (int i = 0; i < pntSize; i++) + { + memset(&dirCornerAngles[i], 0, sizeof(SSG_dirCornerAngle)); + SWD_polarPt& a_polarPt = polarPoints[i]; + //ǰѰ + int minus_i = -1; + for (int loop = i - 1; loop >= i-pntSize; loop--) + { + int j = loop >= 0 ? loop : (loop + pntSize); + double dist = sqrt(pow(polarPoints[i].x - polarPoints[j].x, 2) + + pow(polarPoints[i].y - polarPoints[j].y, 2)); + if (dist >= scale) + { + minus_i = j; + break; + } + } + //Ѱ + int plus_i = -1; + for (int loop = i + 1; loop < i+pntSize; loop++) + { + int j = loop % pntSize; + double dist = sqrt(pow(polarPoints[i].x - polarPoints[j].x, 2) + + pow(polarPoints[i].y - polarPoints[j].y, 2)); + if (dist >= scale) + { + plus_i = j; + break; + } + } + //ս + if ((minus_i >= 0) && (plus_i >= 0)) + { + double backwardAngle = atan2(polarPoints[i].y - polarPoints[minus_i].y, polarPoints[i].x - polarPoints[minus_i].x) * 180.0 / PI; + double forwardAngle = atan2(polarPoints[plus_i].y - polarPoints[i].y, polarPoints[plus_i].x - polarPoints[i].x) * 180.0 / PI; + dirCornerAngles[i].forwardAngle = forwardAngle; + dirCornerAngles[i].backwardAngle = backwardAngle; + + double corner = forwardAngle - backwardAngle; + if (corner < -180) + corner += 360; + else if (corner > 180) + corner = corner - 360; + dirCornerAngles[i].corner = corner; //ͼϵϵy෴С- + dirCornerAngles[i].pntIdx = i; + dirCornerAngles[i].forward_pntIdx = plus_i; + dirCornerAngles[i].backward_pntIdx = minus_i; + dirCornerAngles[i].point = polarPoints[i]; + } + } +} + +//ȡcornerֵʵֺʹô˺дŻ +void _searchPlusCornerPeaks( + std::vector< SSG_dirCornerAngle>& corners, + std::vector< SSG_dirCornerAngle>& cornerPlusPeaks +) +{ + std::vector peakCorners; + int cornerSize = (int)corners.size(); + //սǼֵ + int _state = 0; + int pre_i = -1; + int sEdgePtIdx = -1; + int eEdgePtIdx = -1; + SSG_dirCornerAngle* pre_data = NULL; + for (int i = 0, i_max = cornerSize; i < i_max; i++) + { + if (i == 275) + int kkk = 1; + SSG_dirCornerAngle* curr_data = &corners[i]; + if (NULL == pre_data) + { + sEdgePtIdx = i; + eEdgePtIdx = i; + pre_data = curr_data; + pre_i = i; + continue; + } + + eEdgePtIdx = i; + double cornerDiff = curr_data->corner - pre_data->corner; + switch (_state) + { + case 0: //̬ + if (cornerDiff < 0) //½ + { + _state = 2; + } + else if (cornerDiff > 0) // + { + _state = 1; + } + break; + case 1: // + if (cornerDiff < 0) //½ + { + if (pre_data->corner > 10) //ʹ10Ϊޣ˳㲨µĽǶȱ仯 + peakCorners.push_back(*pre_data); + _state = 2; + } + break; + case 2: //½ + if (cornerDiff > 0) // + _state = 1; + break; + default: + _state = 0; + break; + } + pre_data = curr_data; + pre_i = i; + } + //ע⣺һΪλ + + //Сֵ㣨嶥 + //ֵȽϣڳ߶ȴѰҾֲֵ + for (int i = 0, i_max = (int)peakCorners.size(); i < i_max; i++) + { + bool isPeak = true; + SSG_dirCornerAngle& a_dirAngle = peakCorners[i]; + int curr_dist1 = a_dirAngle.pntIdx - a_dirAngle.backward_pntIdx; + if (curr_dist1 < 0) + curr_dist1 += cornerSize; + int curr_dist2 = a_dirAngle.forward_pntIdx - a_dirAngle.pntIdx; + if (curr_dist2 < 0) + curr_dist2 += cornerSize; + + //minusѰ + int minus_i = i; + while (1) + { + minus_i--; + if (minus_i < 0) + minus_i += i_max; + SSG_dirCornerAngle& minus_dirAngle = peakCorners[minus_i]; + int pntDist_0 = a_dirAngle.pntIdx - minus_dirAngle.pntIdx; + if (pntDist_0 < 0) + pntDist_0 += cornerSize; + if (pntDist_0 > curr_dist1) + break; + + if (a_dirAngle.corner < minus_dirAngle.corner) + { + isPeak = false; + break; + } + } + //plusѰ + int plus_i = i; + while (1) + { + plus_i++; + if (plus_i >= i_max) + plus_i = 0; + SSG_dirCornerAngle& plus_dirAngle = peakCorners[plus_i]; + int pntDist_0 = plus_dirAngle.pntIdx - a_dirAngle.pntIdx; + if (pntDist_0 < 0) + pntDist_0 += cornerSize; + if (pntDist_0 > curr_dist2) + break; + + if (a_dirAngle.corner < plus_dirAngle.corner) + { + isPeak = false; + break; + } + } + if (true == isPeak) + { + double corner_curr = a_dirAngle.corner; + double corner_1 = corners[a_dirAngle.forward_pntIdx].corner; + double corner_2 = corners[a_dirAngle.backward_pntIdx].corner; + double diff_1 = corner_curr - corner_1; + double diff_2 = corner_curr - corner_2; + if ((diff_1 > corner_curr / 2) && (diff_2 > corner_curr / 2)) + cornerPlusPeaks.push_back(a_dirAngle); + } + } +} + +//ĽǵBranch жǷȱǡȱʱͨϷʽȫ +// std::vector& polarPoints: ѭ +//branchCornerAngle: ֧ѰҲͬǶȵBranchbranchCornerAngleָ90Ϊֱǡ +//angleTh: ǶΧΪ90ֱǣʵʼӹ +//cutLineDeviationTh:Խؽߣؽϵ㵽ֱߵƫ롣֤ؽֱ +void _computeBranchesFromCornerPeaks(std::vector& polarPoints, std::vector< SSG_dirCornerAngle>& cornerPlusPeaks, std::vector& branches, double branchCornerAngle, double angleTh, double cutLineDeviationTh) +{ + int ringBuffSize = (int)polarPoints.size(); + //жǷȱ + int size_peaks = (int)cornerPlusPeaks.size(); + std::vector cutPairFlags; + cutPairFlags.resize(size_peaks); + std::fill(cutPairFlags.begin(), cutPairFlags.end(), 0); + int cutPairID = 1; + for (int i = 0; i < size_peaks; i++) + { + if (cutPairFlags[i] > 0) + continue; + + SSG_dirCornerAngle& corner_1 = cornerPlusPeaks[i]; + int tmpIdx = (i + 1) % size_peaks; + SSG_dirCornerAngle& corner_2 = cornerPlusPeaks[tmpIdx]; + if (corner_2.pntIdx < 0) + continue; + + double sumCorner = corner_1.corner + corner_2.corner; + double angleDiff = abs(sumCorner - branchCornerAngle); + if (angleDiff < angleTh) + { + //ƫж + // + double a, b, c; + compute2ptLine_2( + corner_1.point.x, corner_1.point.y, + corner_2.point.x, corner_2.point.y, + &a, &b, &c); + double tmp = sqrt(a * a + b * b); + a = a / tmp; + b = b / tmp; + c = c / tmp; + + double maxDist = 0; + int number = corner_2.pntIdx - corner_1.pntIdx; + if (number < 0) + number += ringBuffSize; + for (int m = 0; m < number; m++) + { + int idx = (m + corner_1.pntIdx) % ringBuffSize; + double dist = abs(a * polarPoints[idx].x + b * polarPoints[m].y + c); + if (maxDist < dist) + maxDist = dist; + } + if (maxDist < cutLineDeviationTh) //жΪؽ + { + cutPairFlags[i] = cutPairID; + cutPairFlags[i+1] = cutPairID; + cutPairID++; + } + } + } + //һΣѭBuff, Ҫ¼βϲ + +} SSX_BQworkpieceResult sx_BQ_getWorkpieceCorners( std::vector< std::vector>& scanLines, @@ -876,6 +1127,17 @@ SSX_BQworkpieceResult sx_BQ_getWorkpieceCorners( for (int pi = 0; pi < contourPtSize; pi++) polarPoints[pi].cptIndex = pi; // index + //ԵĽǶȱ仯 2026.03.06 + std::vector< SSG_dirCornerAngle> dirCornerAngles; + double scale = 20.0; + _computeClosedPntListDirCorners(polarPoints, scale, dirCornerAngles); + //ȡǹյ(ֵ + std::vector< SSG_dirCornerAngle> cornerPlusPeaks; + _searchPlusCornerPeaks(dirCornerAngles, cornerPlusPeaks); + //ʹRˣжǷȱ + std::vector branches; + _computeBranchesFromCornerPeaks(cornerPlusPeaks, branches); + //ȡRֵ double minR = -1, maxR = -1; //СRûз֧minRmaxRСʱΪԲλ8Σûз֧ int minRPos = -1; @@ -1035,6 +1297,9 @@ SSX_BQworkpieceResult sx_BQ_getWorkpieceCorners( branchPeakInfo.erase(branchPeakInfo.begin() + m); } } + + + int branchNum = (int)branchPeaks.size(); if (branchNum == 2) { @@ -1169,6 +1434,9 @@ SSX_BQworkpieceResult sx_BQ_getWorkpieceCorners( debug_contours.push_back(a_branchDebug); #endif } + + + workpieceCorners.workpieceType = workpieceType; if (workpieceType == 1) //4branch { diff --git a/sourceCode/SG_baseAlgo_Export.h b/sourceCode/SG_baseAlgo_Export.h index 254bc41..a58de4f 100644 --- a/sourceCode/SG_baseAlgo_Export.h +++ b/sourceCode/SG_baseAlgo_Export.h @@ -512,7 +512,8 @@ SG_APISHARED_EXPORT bool leastSquareParabolaFitEigen( //Zֵ SG_APISHARED_EXPORT double computeMeanZ(std::vector< SVzNL3DPoint>& pts); - +SG_APISHARED_EXPORT double computeROIMeanZ(std::vector>& scanLines, SVzNLRect roi); +SG_APISHARED_EXPORT void computeROIZCutLabel(std::vector>& scanLines, SVzNLRect roi, double cutZ, int labelID); //ǶȲֵ0-180ȷΧ SG_APISHARED_EXPORT double computeAngleDiff(double theta1, double theta2); diff --git a/sourceCode/SG_baseDataType.h b/sourceCode/SG_baseDataType.h index d818c94..8fc7e60 100644 --- a/sourceCode/SG_baseDataType.h +++ b/sourceCode/SG_baseDataType.h @@ -100,6 +100,12 @@ typedef struct double bottom; }SSG_ROIRectD; +typedef struct +{ + double width; + double height; +}SSG_size2D; + typedef struct { SVzNL3DPoint center; @@ -526,6 +532,20 @@ typedef struct double invRMatrix[9]; //ת󣬻صԭϵ }SSG_planeCalibPara; +typedef struct +{ + int pkId; + int lineIdx; + int ptIdx; + int cptIndex; //Բɨϵĵ + //double cornerAngle; //ԵΪĵҵļн + double R; + double angle; + double x; + double y; + double z; +}SWD_polarPt; + typedef struct { int pntIdx; @@ -541,6 +561,17 @@ typedef struct double backward_z; }SSG_pntDirAngle; +typedef struct +{ + double forwardAngle; //ǰ + double backwardAngle; // + double corner; //ս + int pntIdx; + int forward_pntIdx; + int backward_pntIdx; + SWD_polarPt point; +}SSG_dirCornerAngle; + // ͼݽṹ typedef struct { int width; @@ -562,20 +593,6 @@ typedef struct SVzNL3DPoint pt2; }SWD_3DPointPair; -typedef struct -{ - int pkId; - int lineIdx; - int ptIdx; - int cptIndex; //Բɨϵĵ - //double cornerAngle; //ԵΪĵҵļн - double R; - double angle; - double x; - double y; - double z; -}SWD_polarPt; - typedef struct { int cptIndex; diff --git a/sourceCode/SG_baseFunc.cpp b/sourceCode/SG_baseFunc.cpp index 5b402de..25922ee 100644 --- a/sourceCode/SG_baseFunc.cpp +++ b/sourceCode/SG_baseFunc.cpp @@ -298,6 +298,40 @@ double computeMeanZ(std::vector< SVzNL3DPoint>& pts) return 0; } +double computeROIMeanZ(std::vector>& scanLines, SVzNLRect roi) +{ + int vldNum = 0; + double sumZ = 0; + for (int line = roi.left; line <= roi.right; line++) + { + for (int i = roi.top; i <= roi.bottom; i++) + { + if (scanLines[line][i].pt3D.z > 1e-4) + { + sumZ += scanLines[line][i].pt3D.z; + vldNum++; + } + } + } + if (vldNum > 0) + return (sumZ / vldNum); + else + return 0; +} + +void computeROIZCutLabel(std::vector>& scanLines, SVzNLRect roi, double cutZ, int labelID) +{ + for (int line = roi.left; line <= roi.right; line++) + { + for (int i = roi.top; i <= roi.bottom; i++) + { + if ( (scanLines[line][i].pt3D.z > 1e-4) && (scanLines[line][i].pt3D.z < cutZ)) + scanLines[line][i].nPointIdx = labelID; + } + } + return; +} + SVzNL3DPoint computeLineCrossPt_abs(double a1, double b1, double c1, double a2, double b2, double c2) { SVzNL3DPoint crossPt; diff --git a/sourceCode/YouJiang_sheetPositioning.cpp b/sourceCode/YouJiang_sheetPositioning.cpp index 9a127be..e598388 100644 --- a/sourceCode/YouJiang_sheetPositioning.cpp +++ b/sourceCode/YouJiang_sheetPositioning.cpp @@ -30,16 +30,14 @@ void wd_sheetPosition_lineDataR( lineDataRT_vector(a_line, camPoseR, groundH); } -//Ƭλ -//ʹģƥ䣺1ȡ2ƥ䱡Ƭ -void wd_YouJiang_getSheetPosition( +//ȡԵĿıԵ +void wd_computeClosedEdgeClusters( std::vector< std::vector>& scanLines, - const SWD_sheetTemplateParam templateParam, const SSG_planeCalibPara groundCalibPara, const SWD_sheetAlgoParam algoParam, - SWD_gripState* opState, //״ָ̬ʾǰ״̬ int* errCode, - std::vector& resultObjPositions) + std::vector>& clusters, //ֻ¼λ + std::vector& clustersRoi3D) { int lineNum = (int)scanLines.size(); if (lineNum == 0) @@ -51,7 +49,7 @@ void wd_YouJiang_getSheetPosition( bool isGridData = true; int linePtNum = (int)scanLines[0].size(); for (int i = 0; i < lineNum; i++) - { + { if (linePtNum != (int)scanLines[i].size()) isGridData = false;//д //ƽȥ @@ -198,8 +196,6 @@ void wd_YouJiang_getSheetPosition( // //õ˼룬ع˼·иЧ - std::vector> clusters; //ֻ¼λ - std::vector clustersRoi3D; int clusterID = 1; int clusterCheckWin = 3; for (int y = 0; y < lineNum_h_raw; y++) @@ -236,8 +232,32 @@ void wd_YouJiang_getSheetPosition( clusterID++; } } - int clusterNum = (int)clusters.size(); +} + +//Ƭλ +//ʹģƥ䣺1ȡ2ƥ䱡Ƭ +void wd_YouJiang_getSheetPosition( + std::vector< std::vector>& scanLines, + const SWD_sheetTemplateParam templateParam, + const SSG_planeCalibPara groundCalibPara, + const SWD_sheetAlgoParam algoParam, + SWD_gripState* opState, //״ָ̬ʾǰ״̬ + int* errCode, + std::vector& resultObjPositions) +{ + std::vector> clusters;//ֻ¼λ + std::vector clustersRoi3D; + //ȡԵĿıԵ + wd_computeClosedEdgeClusters( + scanLines, + groundCalibPara, + algoParam, + errCode, + clusters, //ֻ¼λ + clustersRoi3D); + + int clusterNum = (int)clusters.size(); //ͶӰͱעͶӰĿģƥʱ1mmΪλ.¼clusterID SVzNL3DRangeD roi3D = sg_getScanDataROI_vector(scanLines); double projectionScale = 1.0; //1mmΪͶӰ߶ @@ -250,12 +270,14 @@ void wd_YouJiang_getSheetPosition( for (int i = 0; i < clusterNum; i++) { std::vector< SVzNL2DPoint>& a_cluster = clusters[i]; - for (int j = 0; j < (int)clusters.size(); j++) + for (int j = 0; j < (int)a_cluster.size(); j++) { - SVzNL2DPoint& a_pt = a_cluster[i]; + SVzNL2DPoint& a_pt = a_cluster[j]; SVzNL3DPosition& a_pt3d = scanLines[a_pt.x][a_pt.y]; int px = (int)((a_pt3d.pt3D.x - roi3D.xRange.min) / projectionScale); int py = (int)((a_pt3d.pt3D.y - roi3D.yRange.min) / projectionScale); + if ((px < 0) || (px >= projecction_xw) || (py < 0) || (py >= projecction_yh)) + int kkk = 1; projectionClusters[px][py] = i + 1; //clusterID = index + 1 } } @@ -288,4 +310,113 @@ void wd_YouJiang_getSheetPosition( +} + + +typedef struct +{ + cv::RotatedRect rect; + cv::Point2f vertices[4]; +}_RectParam; +//Ƭ߶Ȳ +void wd_computeSheetKeyHeigth( + std::vector< std::vector>& scanLines, + const SWD_sheetKeyParam sheetKeyParam, + const SSG_planeCalibPara groundCalibPara, + const SWD_sheetAlgoParam algoParam, + SWD_gripState* opState, //״ָ̬ʾǰ״̬ + int* errCode, + std::vector& resultObjPositions) +{ + std::vector> clusters;//ֻ¼λ + std::vector clustersRoi3D; + //ȡԵĿıԵ + wd_computeClosedEdgeClusters( + scanLines, + groundCalibPara, + algoParam, + errCode, + clusters, //ֻ¼λ + clustersRoi3D); + int clusterNum = (int)clusters.size(); + + // + //ݴСȷƬ + const double sameSizeTh_w = sheetKeyParam.sheetSize.width * 0.05; + const double sameSizeTh_h = sheetKeyParam.sheetSize.height * 0.05; + const double zAreaWin = 5; + + std::vector<_RectParam> clustersRect; + clustersRect.resize(clusters.size()); +#if 1 + std::vector validIndice; + + for (int i = 0; i < clusterNum; i++) + { + std::vector< SVzNL2DPoint>& a_cluster = clusters[i]; + if (a_cluster.size() < 4) + continue; + //СӾ + std::vector points; + SVzNLRect roi = { -1,-1,-1,-1 }; + for (int j = 0; j < (int)a_cluster.size(); j++) + { + SVzNL2DPoint& a_pt = a_cluster[j]; + SVzNL3DPosition& a_pt3d = scanLines[a_pt.x][a_pt.y]; + //ROI + if (roi.left < 0) + roi = { a_pt.x ,a_pt.x , a_pt.y, a_pt.y }; + else + { + if (roi.left > a_pt.x) + roi.left = a_pt.x; + if (roi.right < a_pt.x) + roi.right = a_pt.x; + if (roi.top > a_pt.y) + roi.top = a_pt.y; + if (roi.bottom < a_pt.y) + roi.bottom = a_pt.y; + } + float x = (float)a_pt3d.pt3D.x; + float y = (float)a_pt3d.pt3D.y; + points.push_back(cv::Point2f(x, y)); + } + if (points.size() == 0) + continue; + + // СӾ + cv::RotatedRect rect = minAreaRect(points); + cv::Point2f vertices[4]; + rect.points(vertices); + double width = rect.size.width; //ͶӰĿ͸ߣ ӦӵijͿ + double height = rect.size.height; + if (width < height) + { + double tmp = height; + height = width; + width = tmp; + } + + int cx = (roi.left + roi.right) / 2; + int cy = (roi.top + roi.bottom) / 2; + //б + double w_diff = abs(width - sheetKeyParam.sheetSize.width); + double h_diff = abs(height - sheetKeyParam.sheetSize.height); + if ((w_diff < sameSizeTh_w) && (h_diff < sameSizeTh_h)) + { + //ѰҵĿ + //ȡĵ㣬ĵ㸽Z + int cx = (roi.left + roi.right) / 2; + int cy = (roi.top + roi.bottom) / 2; + SVzNLRect meanZRoi = { cx - zAreaWin , cx + zAreaWin , cy - zAreaWin , cy + zAreaWin }; + double meanZ = computeROIMeanZ(scanLines, meanZRoi); + //ZֵΪ޽и + double cutZ = meanZ - sheetKeyParam.nominalKeyHeight * 0.75; + int labelID = i + 100; //ID100ʼ + computeROIZCutLabel(scanLines, roi, cutZ, labelID); + } + } +#endif + + } \ No newline at end of file diff --git a/sourceCode/YouJiang_sheetPositioning_Export.h b/sourceCode/YouJiang_sheetPositioning_Export.h index 31a521a..c05936c 100644 --- a/sourceCode/YouJiang_sheetPositioning_Export.h +++ b/sourceCode/YouJiang_sheetPositioning_Export.h @@ -17,6 +17,15 @@ typedef struct double centerBossHeight; //Ƭ͹߶ }SWD_sheetTemplateParam; +typedef struct +{ + SSG_size2D keySize; //ƬС + SSG_size2D sheetSize; //ƬС + double keyToEdgeDistance; //ıߵľ + double sheetThickness; //Ƭ + double nominalKeyHeight; //尴߶ +}SWD_sheetKeyParam; + typedef struct { SSG_outlierFilterParam filterParam; @@ -64,4 +73,14 @@ SG_APISHARED_EXPORT void wd_YouJiang_getSheetPosition( const SWD_sheetAlgoParam algoParam, SWD_gripState* opState, //״ָ̬ʾǰ״̬ int* errCode, + std::vector& resultObjPositions); + +//Ƭ߶Ȳ +SG_APISHARED_EXPORT void wd_computeSheetKeyHeigth( + std::vector< std::vector>& scanLines, + const SWD_sheetKeyParam sheetKeyParam, + const SSG_planeCalibPara groundCalibPara, + const SWD_sheetAlgoParam algoParam, + SWD_gripState* opState, //״ָ̬ʾǰ״̬ + int* errCode, std::vector& resultObjPositions); \ No newline at end of file