#include "SG_baseDataType.h" #include "SG_baseAlgo_Export.h" #include #include //在searchWin中搜索最高点(z最小) void _findPeak(SVzNL3DLaserLine* scanLines, int lineNum, SVzNL2DPoint LTpos, SSG_localPkParam searchWin, SSG_2DValueI* pkPos) { int line_end = LTpos.x + searchWin.seachW_lines; if (line_end >= lineNum) line_end = lineNum; int ptNum = scanLines->nPositionCnt; int pt_end = LTpos.y + searchWin.searchW_pts; if (pt_end >= ptNum) pt_end = ptNum; SSG_2DValueI peak = { -1, -1, 0, 0}; double minZ = -1; for (int i = LTpos.x; i < line_end; i++) { for (int j = LTpos.y; j < pt_end; j++) { SVzNL3DPosition* a_pt = &scanLines[i].p3DPosition[j]; if (a_pt->pt3D.z < 1e-4) continue; if (minZ < 0) { peak = { i, j , 0, a_pt->pt3D.z }; minZ = a_pt->pt3D.z; } else { if (minZ > a_pt->pt3D.z) { peak = { i, j, 0, a_pt->pt3D.z }; minZ = a_pt->pt3D.z; } } } } *pkPos = peak; return; } ///搜索局部最高点(z最小点)。 ///搜索方法:每次步进搜索窗口长度的一半。对局部最高点进行标记,防止被重复记录。 void sg_getLocalPeaks(SVzNL3DLaserLine* scanLines, int lineNum, std::vector& peaks, SSG_localPkParam searchWin) { int ptNum = scanLines->nPositionCnt; cv::Mat mask = cv::Mat::zeros(ptNum, lineNum, CV_32SC1); int winNum_cols = lineNum / (searchWin.seachW_lines/2); if ((lineNum % (searchWin.seachW_lines/2)) > 0) winNum_cols = winNum_cols + 1; int winNum_rows = ptNum / (searchWin.searchW_pts/2); if ((ptNum % (searchWin.searchW_pts/2)) > 0) winNum_rows = winNum_rows + 1; for (int i = 0; i < winNum_rows; i++) { for (int j = 0; j < winNum_cols; j++) { SVzNL2DPoint LTpos = {i* searchWin.seachW_lines / 2, j* searchWin.searchW_pts / 2 }; SSG_2DValueI pkPos = { -1, -1, 0, 0 }; _findPeak(scanLines, lineNum, LTpos, searchWin, &pkPos); if ((pkPos.x >= 0) && (pkPos.y >= 0)) { //边界处的极值点去除 if ((pkPos.x != LTpos.x) && (pkPos.x != (LTpos.x + searchWin.seachW_lines - 1)) && (pkPos.y != LTpos.y) && (pkPos.y != (LTpos.y + searchWin.searchW_pts - 1))) { int maskValue = mask.at(pkPos.y, pkPos.x); if (maskValue == 0) { peaks.push_back(pkPos); mask.at(pkPos.y, pkPos.x) = 1; } } } } } return; } void _polarScan(cv::Mat& edgeMask, SVzNL2DPoint scanSeed, SSG_polarScanParam polarScanParam, std::vector< SSG_2DValueI>& contours, int* maxEdgeId) { int scanTime = (int)(360.0 / polarScanParam.angleStep); int edgeId = 0; for (int i = 0; i < scanTime; i++) { double angle = i * polarScanParam.angleStep; double sinTheta = sin(angle * PI / 180); double cosTheta = cos(angle * PI / 180); double r = 0; while (1) { r += polarScanParam.radiusStep; int x = (int)(scanSeed.x + r * cosTheta); int y = (int)(scanSeed.y - r * sinTheta); if ((x >= edgeMask.cols) || (x < 0) || (y >= edgeMask.rows) || (y < 0)) { //SSG_2DValueI edge_pt = { -1,-1, -1, -1 }; //contours.push_back(edge_pt); break; } else { int maskValue = edgeMask.at(y, x); if (maskValue > 0) { edgeId = edgeId < maskValue ? maskValue : edgeId; SSG_2DValueI edge_pt = { x, y, maskValue, r }; contours.push_back(edge_pt); break; } } } } *maxEdgeId = edgeId; return; } void _getRgnVldContour(std::vector< SSG_2DValueI>& contourPts, std::vector< SSG_2DValueI>& vldContour, int maxEdgeId, const int noiseRunLenTh) { std::vector idIndexing(maxEdgeId + 1); //游程分析 std::vector< SSG_RUN> contourRuns; SSG_RUN a_run = { -1,-1,-1}; for (int i = 0, i_max = (int)contourPts.size(); i < i_max; i++) { SSG_2DValueI* a_pt = &contourPts[i]; if (a_pt->x < 0) continue; if (a_run.start < 0) { a_run.start = i; a_run.len = 1; a_run.value = a_pt->value; } else { if (a_run.value == a_pt->value) a_run.len++; else { contourRuns.push_back(a_run); //新的游程 a_run.start = i; a_run.len = 1; a_run.value = a_pt->value; } } } //处理最后一个 if (contourRuns.size() > 0) { //检查是否和第一个合并 SSG_RUN* first_run = &contourRuns[0]; if (first_run->value == a_run.value) { first_run->start = a_run.start; first_run->len += a_run.len; } else contourRuns.push_back(a_run); } else contourRuns.push_back(a_run); if (contourRuns.size() > 0) { //保留长的边界,小的短的边界可能是噪声 for (int i = 0, i_max = (int)contourRuns.size(); i < i_max; i++) { SSG_RUN* curr_run = &contourRuns[i]; if(curr_run->len > noiseRunLenTh) { idIndexing[curr_run->value] = 1; } } for (int i = 0, i_max = (int)contourPts.size(); i < i_max; i++) { SSG_2DValueI a_pt = contourPts[i]; if (a_pt.x < 0) continue; if (idIndexing[a_pt.value] > 0) vldContour.push_back(a_pt); } } return; } /// /// 区域生长法:以局部最高点作为生长种子进行生长 /// 生长方法与一般的区域生长不同:以种子点为圆心作圆周扫描,记录扫描到的边界 /// /// /// /// /// void sg_peakPolarScan(cv::Mat& edgeMask, SVzNL2DPoint a_peak, SSG_polarScanParam polarScanParam, std::vector< SSG_2DValueI>& rgnContour) { std::vector< SSG_2DValueI> contours; int maxEdgeId = 0; _polarScan(edgeMask, a_peak, polarScanParam, contours, &maxEdgeId); int noiseRunLenTh = (int)(11.25 / polarScanParam.angleStep); //小于22.5度的边界为噪声 _getRgnVldContour(contours, rgnContour, maxEdgeId, noiseRunLenTh); return; } //取出指定的contour点 void sg_getContourPts( std::vector< SSG_lineConotours>& contour_all, int vldEdgeId, std::vector< SSG_2DValueI>& contourFilter, int* lowLevelFlag) { *lowLevelFlag = 0; //生成有效contour //统计block(遮挡)的比例 int blockPtNum = 0; for (int m = 0, m_max = (int)contour_all.size(); m < m_max; m++) { std::vector& a_line_contourPts = contour_all[m].contourPts; for (int i = 0, i_max = (int)a_line_contourPts.size(); i < i_max; i++) { SSG_contourPtInfo* a_contourPt = &a_line_contourPts[i]; int an_edgeIdx = a_contourPt->edgeId; if (an_edgeIdx == vldEdgeId) { if (a_contourPt->blockFlag > 0) blockPtNum++; SSG_2DValueI a_filterPt = { a_contourPt->x, a_contourPt->y, a_contourPt->type, a_contourPt->edgePt.z }; contourFilter.push_back(a_filterPt); } } } blockPtNum = blockPtNum * 2; if (blockPtNum > contourFilter.size()) *lowLevelFlag = 1; return; } //取出指定的contour点 void sg_getPairingContourPts( std::vector& contourPairs, std::vector& idPairs, std::vector< SSG_conotourPair>& contourFilter, SVzNLRangeD range, bool isTBDir, int* lowLevelFlag_0, int* lowLevelFlag_1) { *lowLevelFlag_0 = 0; *lowLevelFlag_1 = 0; //生成有效contour //统计block(遮挡)的比例 int blockPtNum_0 = 0; int blockPtNum_1 = 0; for (int m = 0, m_max = (int)contourPairs.size(); m < m_max; m++) { SSG_conotourPair& a_ptPair = contourPairs[m]; for (int i = 0, i_max = (int)idPairs.size(); i < i_max; i++) { SSG_intPair& a_idPair = idPairs[i]; if ( (a_ptPair.edgeId_0 == a_idPair.data_0) && (a_ptPair.edgeId_1 == a_idPair.data_1)) { bool isValid = false; if (true == isTBDir) { if ((a_ptPair.contourPt_0.edgePt.x > range.min) && (a_ptPair.contourPt_0.edgePt.x < range.max) && (a_ptPair.contourPt_1.edgePt.x > range.min) && (a_ptPair.contourPt_1.edgePt.x < range.max)) isValid = true; } else { if ((a_ptPair.contourPt_0.edgePt.y > range.min) && (a_ptPair.contourPt_0.edgePt.y < range.max) && (a_ptPair.contourPt_1.edgePt.y > range.min) && (a_ptPair.contourPt_1.edgePt.y < range.max)) isValid = true; } if (true == isValid) { if (a_ptPair.contourPt_0.blockFlag > 0) blockPtNum_0++; if (a_ptPair.contourPt_1.blockFlag > 0) blockPtNum_1++; contourFilter.push_back(contourPairs[m]); break; } } } } int totalNum = (int)contourFilter.size(); if(blockPtNum_0 > totalNum/2) *lowLevelFlag_0 = 1; if (blockPtNum_1 > totalNum / 2) *lowLevelFlag_1 = 1; return; } //取出contour点 void sg_contourPostProc(std::vector< SSG_contourPtInfo>& contour, int maxEdgeIdx, double sameConturDistTh, std::vector< SSG_2DValueI>& contourFilter, int sideID, int* blockFlag) { *blockFlag = 0; if (contour.size() == 0) return; std::vector< SSG_contourEdgeInfo> edgeInfo; edgeInfo.resize(maxEdgeIdx + 1); std::vector egdeIndexing; for (int i = 0, i_max = (int)contour.size(); i < i_max; i++) { SSG_contourPtInfo* a_contourPt = &contour[i]; int edgeIdx = a_contourPt->edgeId; if (edgeInfo[edgeIdx].ptNum == 0) //新的Edge { edgeInfo[edgeIdx].sPt = a_contourPt->edgePt; egdeIndexing.push_back(edgeIdx); } edgeInfo[edgeIdx].ePt = a_contourPt->edgePt; edgeInfo[edgeIdx].scanDist += a_contourPt->scanDist; edgeInfo[edgeIdx].ptNum += 1; } //计算平均scanDist //保留scanDist最小的,只有点数大于总点数的10%才是有效edge int lenTh = (int)(contour.size() * 3) / 10; int nearestIdx = -1; double minScanDist = -1; for (int i = 0; i < egdeIndexing.size(); i++) { int edgeId = egdeIndexing[i]; edgeInfo[edgeId].scanDist = edgeInfo[edgeId].scanDist / edgeInfo[edgeId].ptNum; if (edgeInfo[edgeId].ptNum > lenTh) { if (minScanDist < 0) { nearestIdx = i; minScanDist = edgeInfo[edgeId].scanDist; } else { if (minScanDist > edgeInfo[edgeId].scanDist) { nearestIdx = i; minScanDist = edgeInfo[edgeId].scanDist; } } } else edgeInfo[edgeId].ptNum = 0; //invalid } if (nearestIdx < 0) return; //以最小距离为基础,检查其余线段与此线段的距离。小于sameConturDistTh为同一线段 //生成有效contour //统计block(遮挡)的比例 int blockPtNum = 0; for (int i = 0; i < egdeIndexing.size(); i++) { int edgeId = egdeIndexing[i]; if (0 == edgeInfo[edgeId].ptNum) continue; double scanDist = edgeInfo[edgeId].scanDist; double dist_diff = scanDist - minScanDist; if (dist_diff < sameConturDistTh) { for (int m = 0, m_max = (int)contour.size(); m < m_max; m++) { SSG_contourPtInfo* a_contourPt = &contour[m]; int an_edgeIdx = a_contourPt->edgeId; if (an_edgeIdx == edgeId) { if (a_contourPt->blockFlag > 0) blockPtNum++; SSG_2DValueI a_filterPt = { a_contourPt->x, a_contourPt->y, a_contourPt->type, a_contourPt->edgePt.z, sideID }; contourFilter.push_back(a_filterPt); } } } } blockPtNum = blockPtNum * 2; if (blockPtNum > contourFilter.size()) *blockFlag = 1; return; } void _checkVEdgePt( SVzNL3DLaserLine* laser3DPoints, int lineNum, int px, int py, int linePtNum, SSG_2DValueI a_peak, SVzNL3DPosition* a_pt, int* a_pt_edgeId, double pk_y, bool rgnPtAsEdge, double scanDistTh, bool dirUp, SSG_contourPtInfo* edgePt, bool* stopFlag, bool* foundHScanEdge) { int ptNum = laser3DPoints[0].nPositionCnt; int objId = (a_pt->nPointIdx >> 8) & 0xff; int vType = (a_pt->nPointIdx) & 0x00ff;//屏蔽rgnID int hType = vType >> 4; vType &= 0x0f; *stopFlag = false; double scanDist = abs(pk_y - a_pt->pt3D.y); if ((vType > 0) || (py == 0) ||(py == linePtNum-1)|| ((true == rgnPtAsEdge) && (objId > 0))) { //碰撞检测(检测是否为下层目标) if ((vType == 0) && ((true == rgnPtAsEdge) && (objId > 0))) { vType = LINE_FEATURE_RGN_EDGE; if (true == dirUp) *a_pt_edgeId = 5; else *a_pt_edgeId = 6; } int blockFlag = 0; if (true == dirUp) { if ((LINE_FEATURE_L_JUMP_H2L == vType) || (LINE_FEATURE_L_SLOPE_H2L == vType)) blockFlag = 1; } else { if ((LINE_FEATURE_L_JUMP_L2H == vType) || (LINE_FEATURE_L_SLOPE_L2H == vType)) blockFlag = 1; } if (scanDist > scanDistTh) *stopFlag = true; if (false == *stopFlag) { *edgePt = { px, py, vType, *a_pt_edgeId, blockFlag, scanDist, a_pt->pt3D }; if ((LINE_FEATURE_RGN_EDGE == vType) || (LINE_FEATURE_L_JUMP_H2L == vType) || (LINE_FEATURE_L_JUMP_L2H == vType) || (LINE_FEATURE_LINE_ENDING_0 == vType) || (LINE_FEATURE_LINE_ENDING_1 == vType))// || //(LINE_FEATURE_CORNER_V == vType)) *stopFlag = true; else if((*a_pt_edgeId == 5) || (*a_pt_edgeId == 6)) *stopFlag = true; } } #if 1 else if ((vType == 0) && (hType > 0)) { // if ((LINE_FEATURE_L_JUMP_H2L == hType) || (LINE_FEATURE_L_JUMP_L2H == hType)) { //继续向前检测5步 bool tmp_flag = true; for (int m = 0; m < 5; m++) { int chk_y; if (true == dirUp) { chk_y = py - m; if (chk_y < 0) break; } else { chk_y = py + m; if (chk_y >= ptNum) break; } int chk_vType = (laser3DPoints[px].p3DPosition[chk_y].nPointIdx) & 0x000f;//屏蔽rgnID if (chk_vType > 0) { tmp_flag = false; break; } } if (true == tmp_flag) { *foundHScanEdge = true; *stopFlag = true; } } } #endif return; } void _checkHEdgePt( SVzNL3DLaserLine* laser3DPoints, int lineNum, int px, int py, SSG_2DValueI a_peak, SVzNL3DPosition* a_pt, int* a_pt_edgeId, double pk_x, bool rgnPtAsEdge, double scanDistTh, bool dirLeft, SSG_contourPtInfo* edgePt, bool* stopFlag, bool* foundVScanEdge) { int objId = (a_pt->nPointIdx >> 8) & 0xff; int vType = (a_pt->nPointIdx) & 0x00ff;//屏蔽rgnID int hType = vType >> 4; vType &= 0x0f; *stopFlag = false; double scanDist = abs(pk_x - a_pt->pt3D.x); if ((hType > 0) || (px == 0) ||(px == lineNum-1)|| ((true == rgnPtAsEdge) && (objId > 0))) { //碰撞检测(检测是否为下层目标) if ((hType == 0) && ((true == rgnPtAsEdge) && (objId > 0))) { hType = LINE_FEATURE_RGN_EDGE; if (true == dirLeft) *a_pt_edgeId = 7; else *a_pt_edgeId = 8; } int blockFlag = 0; if (true == dirLeft) { if ((LINE_FEATURE_L_JUMP_H2L == hType) || (LINE_FEATURE_L_SLOPE_H2L == hType)) blockFlag = 1; } else { if ((LINE_FEATURE_L_JUMP_L2H == hType) || (LINE_FEATURE_L_SLOPE_L2H == hType)) blockFlag = 1; } if (scanDist > scanDistTh) *stopFlag = true; if (false == *stopFlag) { *edgePt = { px, py, hType, *a_pt_edgeId, blockFlag, scanDist, a_pt->pt3D }; if ((LINE_FEATURE_RGN_EDGE == hType) || (LINE_FEATURE_L_JUMP_H2L == hType) || (LINE_FEATURE_L_JUMP_L2H == hType) || (LINE_FEATURE_LINE_ENDING_0 == hType) || (LINE_FEATURE_LINE_ENDING_1 == hType))//|| //(LINE_FEATURE_CORNER_V == hType)) *stopFlag = true; else if ((*a_pt_edgeId == 7) || (*a_pt_edgeId == 8)) *stopFlag = true; } } #if 1 else if ((hType == 0) && ( vType > 0)) { if ((LINE_FEATURE_L_JUMP_H2L == vType) || (LINE_FEATURE_L_JUMP_L2H == vType)) { //继续向前检测5步 bool tmp_flag = true; for (int m = 0; m < 5; m++) { int chk_x; if (true == dirLeft) { chk_x = px - m; if (chk_x < 0) break; } else { chk_x = px + m; if (chk_x >= lineNum) break; } int chk_hType = (laser3DPoints[chk_x].p3DPosition[py].nPointIdx) & 0x00f0;//屏蔽rgnID if (chk_hType > 0) { tmp_flag = false; break; } } if (true == tmp_flag) { *foundVScanEdge = true; *stopFlag = true; } } } #endif return; } void _searchUpDownEdgePts( SVzNL3DLaserLine* laser3DPoints, int lineNum, cv::Mat& featureEdgeMask, SSG_2DValueI a_peak, int scan_x, bool rgnPtAsEdge, double scanDistTh, bool searchDir_up, std::vector< SSG_contourPtInfo>& edgePts, bool* foundHScanEdge ) { *foundHScanEdge = false; double pk_y = laser3DPoints[a_peak.x].p3DPosition[a_peak.y].pt3D.y; int ptNum = laser3DPoints[0].nPositionCnt; if (true == searchDir_up) { SSG_contourPtInfo pre_pt; memset(&pre_pt, 0, sizeof(SSG_contourPtInfo)); for (int y = a_peak.y; y >= 0; y--) { if (y == 84) int kkk = 1; SVzNL3DPosition* a_pt = &laser3DPoints[scan_x].p3DPosition[y]; int edgeId = featureEdgeMask.at(y, scan_x)[0]; SSG_contourPtInfo _top; memset(&_top, 0, sizeof(SSG_contourPtInfo)); _top.x = -1; //无效 bool stopFlag = false; _checkVEdgePt( laser3DPoints, lineNum, scan_x, y, ptNum, a_peak, a_pt, &edgeId, pk_y, rgnPtAsEdge, scanDistTh, true, //Dir_UP &_top, &stopFlag, foundHScanEdge); if ( (_top.x >= 0) && (_top.type > 0) && (edgeId > 0)) { if ((_top.type > 0) && (_top.y >= a_peak.y - 1)) //在区域外面 stopFlag = true; else { //进行Edge检查,检查Edge有没有突然变化 if (((LINE_FEATURE_L_JUMP_H2L == pre_pt.type) || (LINE_FEATURE_L_JUMP_L2H == pre_pt.type)) && ((LINE_FEATURE_L_JUMP_H2L == _top.type) || (LINE_FEATURE_L_JUMP_L2H == _top.type) )) //(LINE_FEATURE_LINE_ENDING_0 == _top.type) || (LINE_FEATURE_LINE_ENDING_1 == _top.type))) { double dist_diff = abs(pre_pt.scanDist - _top.scanDist); if (dist_diff > 100) { stopFlag = true; *foundHScanEdge = true; } else edgePts.push_back(_top); } else edgePts.push_back(_top); } } if (true == stopFlag) break; pre_pt = _top; } } else { SSG_contourPtInfo pre_pt; memset(&pre_pt, 0, sizeof(SSG_contourPtInfo)); for (int y = a_peak.y; y < ptNum; y++) { if (y == 336) int kkk = 1; SVzNL3DPosition* a_pt = &laser3DPoints[scan_x].p3DPosition[y]; int edgeId = featureEdgeMask.at(y, scan_x)[0]; SSG_contourPtInfo _btm; memset(&_btm, 0, sizeof(SSG_contourPtInfo)); _btm.x = -1; //无效 bool stopFlag = false; _checkVEdgePt( laser3DPoints, lineNum, scan_x, y, ptNum, a_peak, a_pt, &edgeId, pk_y, rgnPtAsEdge, scanDistTh, false, //dir_down &_btm, &stopFlag, foundHScanEdge); if ( (_btm.x >= 0) && (_btm.type > 0) && (edgeId > 0)) { if ((_btm.type > 0) && (_btm.y <= a_peak.y + 1))//在区域外面 stopFlag = true; else { //进行Edge检查,检查Edge有没有突然变化 if (((LINE_FEATURE_L_JUMP_H2L == pre_pt.type) || (LINE_FEATURE_L_JUMP_L2H == pre_pt.type)) && ((LINE_FEATURE_L_JUMP_H2L == _btm.type) || (LINE_FEATURE_L_JUMP_L2H == _btm.type)))// || //(LINE_FEATURE_LINE_ENDING_0 == _btm.type) || (LINE_FEATURE_LINE_ENDING_1 == _btm.type))) { double dist_diff = abs(pre_pt.scanDist - _btm.scanDist); if (dist_diff > 100) { stopFlag = true; *foundHScanEdge = true; } else edgePts.push_back(_btm); } else edgePts.push_back(_btm); } } if (true == stopFlag) break; pre_pt = _btm; } } } void _searchLeftRightEdgePts( SVzNL3DLaserLine* laser3DPoints, int lineNum, cv::Mat& featureEdgeMask, SSG_2DValueI a_peak, int scan_y, bool rgnPtAsEdge, double scanDistTh, bool searchDir_left, std::vector< SSG_contourPtInfo>& edgePts, bool* foundVScanEdge) { *foundVScanEdge = false; double pk_x = laser3DPoints[a_peak.x].p3DPosition[a_peak.y].pt3D.x; if (true == searchDir_left) { SSG_contourPtInfo pre_pt; memset(&pre_pt, 0, sizeof(SSG_contourPtInfo)); for (int x = a_peak.x; x >= 0; x--) { if (x == 4) int kkk = 1; SVzNL3DPosition* a_pt = &laser3DPoints[x].p3DPosition[scan_y]; int edgeId = featureEdgeMask.at(scan_y, x)[0]; SSG_contourPtInfo _left; memset(&_left, 0, sizeof(SSG_contourPtInfo)); _left.x = -1; //无效 bool stopFlag = false; _checkHEdgePt( laser3DPoints, lineNum, x, scan_y, a_peak, a_pt, &edgeId, pk_x, rgnPtAsEdge, scanDistTh, true, //DIR_left &_left, &stopFlag, foundVScanEdge); if ((_left.x >= 0) && (_left.type > 0) && (edgeId > 0)) { if ((_left.type > 0) && (_left.x >= a_peak.x - 1)) //在区域外面 stopFlag = true; else { //进行Edge检查,检查Edge有没有突然变化 if (((LINE_FEATURE_L_JUMP_H2L == pre_pt.type) || (LINE_FEATURE_L_JUMP_H2L == pre_pt.type)) && ((LINE_FEATURE_L_JUMP_H2L == _left.type) || (LINE_FEATURE_L_JUMP_H2L == _left.type)))// || //(LINE_FEATURE_LINE_ENDING_0 == _left.type) || (LINE_FEATURE_LINE_ENDING_1 == _left.type))) { double dist_diff = abs(pre_pt.scanDist - _left.scanDist); if (dist_diff > 100) { stopFlag = true; *foundVScanEdge = true; } else edgePts.push_back(_left); } else edgePts.push_back(_left); } } if (true == stopFlag) break; pre_pt = _left; } } else { SSG_contourPtInfo pre_pt; memset(&pre_pt, 0, sizeof(SSG_contourPtInfo)); for (int x = a_peak.x; x < lineNum; x++) { if (x == 374) int kkk = 1; SVzNL3DPosition* a_pt = &laser3DPoints[x].p3DPosition[scan_y]; int edgeId = featureEdgeMask.at(scan_y, x)[0]; SSG_contourPtInfo _right; memset(&_right, 0, sizeof(SSG_contourPtInfo)); _right.x = -1; //无效 bool stopFlag = false; _checkHEdgePt( laser3DPoints, lineNum, x, scan_y, a_peak, a_pt, &edgeId, pk_x, rgnPtAsEdge, scanDistTh, false, //DIR_right &_right, &stopFlag, foundVScanEdge); if ( (_right.x >= 0) && (_right.type > 0) && (edgeId > 0)) { if ((_right.type > 0) && (_right.x <= a_peak.x + 1))//在区域外面 stopFlag = true; else { //进行Edge检查,检查Edge有没有突然变化 if (((LINE_FEATURE_L_JUMP_H2L == pre_pt.type) || (LINE_FEATURE_L_JUMP_H2L == pre_pt.type)) && ((LINE_FEATURE_L_JUMP_H2L == _right.type) || (LINE_FEATURE_L_JUMP_H2L == _right.type))) //|| // (LINE_FEATURE_LINE_ENDING_0 == _right.type) || (LINE_FEATURE_LINE_ENDING_1 == _right.type))) { double dist_diff = abs(pre_pt.scanDist - _right.scanDist); if (dist_diff > 100) { stopFlag = true; *foundVScanEdge = true; } else edgePts.push_back(_right); } else edgePts.push_back(_right); } } if (true == stopFlag) break; pre_pt = _right; } } } //从Peak点进行水平垂直扫描得到区域边界 void sg_peakXYScan( SVzNL3DLaserLine* laser3DPoints, int lineNum, cv::Mat& featureEdgeMask, SSG_2DValueI a_peak, SSG_treeGrowParam growParam, SSG_bagParam bagParam, bool rgnPtAsEdge, //int stopEdgeId_T, int stopEdgeId_B, int stopEdgeId_L, int stopEdgeId_R, std::vector< SSG_lineConotours>& topContour, std::vector< SSG_lineConotours>& bottomContour, std::vector< SSG_lineConotours>& leftContour, std::vector< SSG_lineConotours>& rightContour, int* maxEdgeId_top, int* maxEdgeId_btm, int* maxEdgeId_left, int* maxEdgeId_right) { if (featureEdgeMask.at(a_peak.y, a_peak.x)[3] == 0) return; int ptNum = laser3DPoints[0].nPositionCnt; double pk_x = laser3DPoints[a_peak.x].p3DPosition[a_peak.y].pt3D.x; double pk_y = laser3DPoints[a_peak.x].p3DPosition[a_peak.y].pt3D.y; *maxEdgeId_top = 0; *maxEdgeId_btm = 0; double scanDistTh = bagParam.bagL -a_peak.valueD /2; //从Peak点向左扫描 for (int x = a_peak.x; x >= 0; x--) { if (x == 0) int kkk = 1; //最多扫描bagL宽度 double curr_x = laser3DPoints[x].p3DPosition[a_peak.y].pt3D.x; double x_diff = abs(curr_x - pk_x); if (x_diff > scanDistTh) break; bool foundHScanEdge = false; std::vector< SSG_contourPtInfo> a_line_upEdgePts; _searchUpDownEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, x, rgnPtAsEdge, scanDistTh, true, //searchDir_up, a_line_upEdgePts, &foundHScanEdge); std::vector< SSG_contourPtInfo> a_line_downEdgePts; _searchUpDownEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, x, rgnPtAsEdge, scanDistTh, false, //searchDir_down, a_line_downEdgePts, &foundHScanEdge); if ( true == foundHScanEdge) break; else { for (int m = 0, m_max = (int)a_line_upEdgePts.size(); m < m_max; m++) { if (*maxEdgeId_top < a_line_upEdgePts[m].edgeId) *maxEdgeId_top = a_line_upEdgePts[m].edgeId; } if (a_line_upEdgePts.size() > 0) { SSG_lineConotours _line_upContours = { x,a_line_upEdgePts }; topContour.insert(topContour.begin(), _line_upContours); } for (int m = 0, m_max = (int)a_line_downEdgePts.size(); m < m_max; m++) { if (*maxEdgeId_btm < a_line_downEdgePts[m].edgeId) *maxEdgeId_btm = a_line_downEdgePts[m].edgeId; } if (a_line_downEdgePts.size() > 0) { SSG_lineConotours _line_downContours = { x,a_line_downEdgePts }; bottomContour.insert(bottomContour.begin(), _line_downContours); } } } //从Peak点向右扫描 for (int x = a_peak.x+1; x < lineNum; x++) { if (x == 34) int kkk = 1; //最多扫描bagL宽度 double curr_x = laser3DPoints[x].p3DPosition[a_peak.y].pt3D.x; double x_diff = abs(curr_x - pk_x); if (x_diff > scanDistTh) break; bool foundHScanEdge = false; std::vector< SSG_contourPtInfo> a_line_upEdgePts; _searchUpDownEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, x, rgnPtAsEdge, scanDistTh, true, //searchDir_up, a_line_upEdgePts, &foundHScanEdge); std::vector< SSG_contourPtInfo> a_line_downEdgePts; _searchUpDownEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, x, rgnPtAsEdge, scanDistTh, false, //searchDir_down, a_line_downEdgePts, &foundHScanEdge); if (true == foundHScanEdge) break; else { for (int m = 0, m_max = (int)a_line_upEdgePts.size(); m < m_max; m++) { if (*maxEdgeId_top < a_line_upEdgePts[m].edgeId) *maxEdgeId_top = a_line_upEdgePts[m].edgeId; } if (a_line_upEdgePts.size() > 0) { SSG_lineConotours _line_upContours = { x,a_line_upEdgePts }; topContour.push_back(_line_upContours); } for (int m = 0, m_max = (int)a_line_downEdgePts.size(); m < m_max; m++) { if (*maxEdgeId_btm < a_line_downEdgePts[m].edgeId) *maxEdgeId_btm = a_line_downEdgePts[m].edgeId; } if (a_line_downEdgePts.size() > 0) { SSG_lineConotours _line_downContours = { x,a_line_downEdgePts }; bottomContour.push_back(_line_downContours); } } } *maxEdgeId_left = 0; *maxEdgeId_right = 0; //从Peak点向上扫描 for (int y= a_peak.y; y >= 0; y--) { if (y == 380) int kkk = 1; //最多扫描bagL宽度 double curr_y = laser3DPoints[a_peak.x].p3DPosition[y].pt3D.y; double y_diff = abs(curr_y - pk_y); if (y_diff > scanDistTh) break; bool foundVScanEdge = false; std::vector< SSG_contourPtInfo> a_line_leftPts; _searchLeftRightEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, y, rgnPtAsEdge, scanDistTh, true,// searchDir_left, a_line_leftPts, &foundVScanEdge); std::vector< SSG_contourPtInfo> a_line_rightPts; _searchLeftRightEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, y, rgnPtAsEdge, scanDistTh, false,// searchDir_right, a_line_rightPts, &foundVScanEdge); if ( true == foundVScanEdge) break; else { for (int m = 0, m_max = (int)a_line_leftPts.size(); m < m_max; m++) { if (*maxEdgeId_left < a_line_leftPts[m].edgeId) *maxEdgeId_left = a_line_leftPts[m].edgeId; } if (a_line_leftPts.size() > 0) { SSG_lineConotours _line_leftContours = { y, a_line_leftPts }; leftContour.insert(leftContour.begin(), _line_leftContours); } for (int m = 0, m_max = (int)a_line_rightPts.size(); m < m_max; m++) { if (*maxEdgeId_right < a_line_rightPts[m].edgeId) *maxEdgeId_right = a_line_rightPts[m].edgeId; } if (a_line_rightPts.size() > 0) { SSG_lineConotours _line_rightContours = { y, a_line_rightPts }; rightContour.insert(rightContour.begin(), _line_rightContours); } } } //从Peak点向下扫描 for (int y = a_peak.y+1; y < ptNum; y++) { if (y == 285) int kkk = 1; //最多扫描bagL宽度 double curr_y = laser3DPoints[a_peak.x].p3DPosition[y].pt3D.y; double y_diff = abs(curr_y - pk_y); if (y_diff > scanDistTh) break; bool foundVScanEdge = false; std::vector< SSG_contourPtInfo> a_line_leftPts; _searchLeftRightEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, y, rgnPtAsEdge, scanDistTh, true,// searchDir_left, a_line_leftPts, &foundVScanEdge); std::vector< SSG_contourPtInfo> a_line_rightPts; _searchLeftRightEdgePts( laser3DPoints, lineNum, featureEdgeMask, a_peak, y, rgnPtAsEdge, scanDistTh, false,// searchDir_right, a_line_rightPts, &foundVScanEdge); if (true == foundVScanEdge) break; else { for (int m = 0, m_max = (int)a_line_leftPts.size(); m < m_max; m++) { if (*maxEdgeId_left < a_line_leftPts[m].edgeId) *maxEdgeId_left = a_line_leftPts[m].edgeId; } if (a_line_leftPts.size() > 0) { SSG_lineConotours _line_leftContours = { y, a_line_leftPts }; leftContour.push_back( _line_leftContours); } for (int m = 0, m_max = (int)a_line_rightPts.size(); m < m_max; m++) { if (*maxEdgeId_right < a_line_rightPts[m].edgeId) *maxEdgeId_right = a_line_rightPts[m].edgeId; } if (a_line_rightPts.size() > 0) { SSG_lineConotours _line_rightContours = { y, a_line_rightPts }; rightContour.push_back(_line_rightContours); } } } return; } float EDistance(int x1, int y1, int x2, int y2) { return sqrt(float((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))); } float MDistance(int x1, int y1, int x2, int y2) { return (float)abs(x1 - x2) + (float)abs(y1 - y2); } float CDistance(int x1, int y1, int x2, int y2) { return std::max((float)abs(x1 - x2), (float)abs(y1 - y2)); } float Distance(int x1, int y1, int x2, int y2, int type) { if (type == 0) { return EDistance(x1, y1, x2, y2); } else if (type == 1) { return MDistance(x1, y1, x2, y2); } else //if (type == 2) { return CDistance(x1, y1, x2, y2); } } /// /// 距离变换 /// /// float型 /// /// /// mask1 /// q1 q2 /// q3 P /// q4 ///mask2 /// q4 /// P q3 /// q1 q2 void sg_distanceTrans(const cv::Mat input, cv::Mat& output, int distType) { cv::Mat BinaryImage = input.clone(); float* pRowOne; float* pRowNext; float distance; float Mindis; for (int i = 1; i < BinaryImage.rows - 1; i++) { pRowOne = BinaryImage.ptr(i); for (int j = 1; j < BinaryImage.cols; j++) { pRowNext = BinaryImage.ptr(i - 1); distance = Distance(i, j, i - 1, j - 1, distType);//q1 Mindis = std::min((float)pRowOne[j], distance + pRowNext[j - 1]); distance = Distance(i, j, i - 1, j, distType);//q2 Mindis = std::min(Mindis, distance + pRowNext[j]); pRowNext = BinaryImage.ptr(i); distance = Distance(i, j, i, j - 1, distType);//q3 Mindis = std::min(Mindis, distance + pRowNext[j-1]); pRowNext = BinaryImage.ptr(i + 1);//q4 distance = Distance(i, j, i + 1, j - 1, distType); Mindis = std::min(Mindis, distance + pRowNext[j - 1]); pRowOne[j] = Mindis; } } for (int i = BinaryImage.rows - 2; i > 0; i--) { pRowOne = BinaryImage.ptr(i); for (int j = BinaryImage.cols - 2; j >= 0; j--) { pRowNext = BinaryImage.ptr(i + 1); distance = Distance(i, j, i + 1, j, distType);//q1 Mindis = std::min((float)pRowOne[j], distance + pRowNext[j]); distance = Distance(i, j, i + 1, j + 1, distType);//q2 Mindis = std::min(Mindis, distance + pRowNext[j + 1]); pRowNext = BinaryImage.ptr(i);//q3 distance = Distance(i, j, i, j + 1, distType); Mindis = std::min(Mindis, distance + pRowNext[j + 1]); pRowNext = BinaryImage.ptr(i - 1);//q4 distance = Distance(i, j, i - 1, j + 1, distType); Mindis = std::min(Mindis, distance + pRowNext[j + 1]); pRowOne[j] = Mindis; } } //将周边一圈置0 float* row_0 = BinaryImage.ptr(0); float* row_last = BinaryImage.ptr(input.rows - 1); for (int i = 0; i < BinaryImage.cols; i++) { row_0[i] = 0; row_last[i] = 0; } for (int i = 0; i < input.rows; i++) { BinaryImage.ptr(i)[0] = 0; BinaryImage.ptr(i)[input.cols - 1] = 0; } output = BinaryImage; } //在searchWin中搜索距离变换最高点 void _findDistTransformPeak(cv::Mat& distTransform, SVzNL2DPoint LTpos, SSG_localPkParam searchWin, SSG_2DValueI* pkPos) { int line_end = LTpos.x + searchWin.seachW_lines; if (line_end >= distTransform.cols) line_end = distTransform.cols; int pt_end = LTpos.y + searchWin.searchW_pts; if (pt_end >= distTransform.rows) pt_end = distTransform.rows; SSG_2DValueI peak = { -1, -1, 0, 0, 0 }; double maxValue = -1; for (int i = LTpos.x; i < line_end; i++) { for (int j = LTpos.y; j < pt_end; j++) { float value = distTransform.at(j, i); if (maxValue < 0) { peak = { i, j , 0, value }; maxValue = value; } else { if (maxValue /// 以5x5方式寻找localPeaks /// /// /// void sg_getLocalPeaks_distTransform(cv::Mat& input, std::vector& peaks, SSG_localPkParam searchWin) { cv::Mat mask = cv::Mat::zeros(input.rows,input.cols, CV_32SC1); int winNum_cols = input.cols / (searchWin.seachW_lines / 2); if ((input.cols % (searchWin.seachW_lines / 2)) > 0) winNum_cols = winNum_cols + 1; int winNum_rows = input.rows / (searchWin.searchW_pts / 2); if ((input.rows % (searchWin.searchW_pts / 2)) > 0) winNum_rows = winNum_rows + 1; for (int i = 0; i < winNum_rows; i++) { for (int j = 0; j < winNum_cols; j++) { SVzNL2DPoint LTpos = { j * searchWin.searchW_pts / 2 , i * searchWin.seachW_lines / 2 }; SSG_2DValueI pkPos = { -1, -1, 0, 0 }; _findDistTransformPeak(input, LTpos, searchWin, &pkPos); if ((pkPos.x >= 0) && (pkPos.y >= 0)) { //边界处的极值点去除 if ((pkPos.x != LTpos.x) && (pkPos.x != (LTpos.x + searchWin.seachW_lines - 1)) && (pkPos.y != LTpos.y) && (pkPos.y != (LTpos.y + searchWin.searchW_pts - 1))) { int maskValue = mask.at(pkPos.y, pkPos.x); if (maskValue == 0) { peaks.push_back(pkPos); mask.at(pkPos.y, pkPos.x) = 1; } } } } } return; }