algoLib/sourceCode/SG_clustering.cpp
jerryzeng 0231f54828 BQ_workpieceCornerExtraction version 1.4.1 :
(1)使用聚类方法寻找准确轮廓点(2)使用拐角和R极值方法判断目标类型
2026-03-19 00:43:39 +08:00

464 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
#include <vector>
#ifdef _WIN32
#include <corecrt_math_defines.h>
#endif
#include <cmath>
void _seedClustering(
std::vector< SVzNL3DPosition>& a_cluster,
std::vector< SVzNL3DPosition>& pts,
std::vector<int> flags,
double clusterDist)
{
int i = 0;
while (1)
{
if (i >= a_cluster.size())
break;
SVzNL3DPosition a_seed = a_cluster[i];
for (int j = 0, j_max = (int)pts.size(); j < j_max; j++)
{
if (flags[j] < 0)
continue;
double dist_x = abs(a_seed.pt3D.x - pts[j].pt3D.x);
double dist_y = abs(a_seed.pt3D.y - pts[j].pt3D.y);
if ( (dist_x < clusterDist) && (dist_y < clusterDist))
{
a_cluster.push_back(pts[j]);
flags[j] = -1;
}
}
i++;
}
return;
}
void _seedClustering_speedUp(
std::vector< SVzNL3DPosition>& a_cluster,
std::vector< SVzNL3DPosition>& pts,
std::vector<int>& flags,
double clusterDist,
std::vector<std::vector<int>>& indexing2D,
int lineNum, int ptSize, int clusterCheckWin) //ËÑË÷´°¿Ú
{
int i = 0;
while (1)
{
if (i >= a_cluster.size())
break;
SVzNL3DPosition a_seed = a_cluster[i];
int seed_line = a_seed.nPointIdx >> 16;
int seed_ptIdx =a_seed.nPointIdx & 0x0000FFFF;
for (int line = seed_line - clusterCheckWin; line <= seed_line + clusterCheckWin; line++)
{
if ((line >= 0) && (line < lineNum))
{
for (int ptIdx = seed_ptIdx - clusterCheckWin; ptIdx <= seed_ptIdx + clusterCheckWin; ptIdx++)
{
if ((ptIdx >= 0) && (ptIdx < ptSize))
{
int backIdx = indexing2D[line][ptIdx];
if (backIdx < 0)
continue;
if (flags[backIdx] < 0)
continue;
double dist = sqrt(pow(a_seed.pt3D.x - pts[backIdx].pt3D.x,2) + pow(a_seed.pt3D.y - pts[backIdx].pt3D.y,2));
if (dist < clusterDist)
{
a_cluster.push_back(pts[backIdx]);
flags[backIdx] = -1;
}
}
}
}
}
i++;
}
return;
}
void sg_pointClustering(
std::vector< SVzNL3DPosition>& pts,
double clusterDist,
std::vector<std::vector< SVzNL3DPosition>>& objClusters //result
)
{
int ptSize = (int)pts.size();
if (ptSize == 0)
return;
std::vector<int> flags;
flags.resize(ptSize);
std::fill(flags.begin(), flags.end(), 0);
while(pts.size() > 0)
{
SVzNL3DPosition a_pt = pts[0];
flags[0] = -1;//·ÀÖ¹ÖØ¸´±»¼ÆËã
//н¨Ò»¸öcluster
std::vector< SVzNL3DPosition> a_cluster;
a_cluster.push_back(a_pt);
//pts[0].nPointIdx = -1;
_seedClustering(
a_cluster,
pts,
flags,
clusterDist);
objClusters.push_back(a_cluster); //±£´æÒ»¸ö¾ÛÀà
//½«ptsÖд¦Àí¹ýµÄµãÈ¥³ý
int m_max = (int)pts.size();
for (int m = m_max - 1; m >= 0; m--) //´ÓºóÍùǰ£¬ÕâÑùɾ³ý²»»áÓ°ÏìÑ­»·
{
if (flags[m] < 0)
{
pts.erase(pts.begin() + m);
flags.erase(flags.begin() + m);
}
}
}
return;
}
//ʹÓÃSVzNL3DPositionµÄnPointIdx±íʾ2DÐÅÏ¢£¨¸ß16λLine£¬ µÍ16λptIdx£©
//ËÑË÷ʱËÑË÷ÁÚÓòÒÔ¼ÓËÙ
void wd_pointClustering_speedUp(
std::vector< SVzNL3DPosition>& pts,
int lineNum, int linePtSize, int clusterCheckWin, //ËÑË÷´°¿Ú
double clusterDist,
std::vector<std::vector< SVzNL3DPosition>>& objClusters //result
)
{
std::vector<std::vector<int>> indexing2D;
indexing2D.resize(lineNum);
for (int i = 0; i < lineNum; i++)
{
indexing2D[i].resize(linePtSize);
std::fill(indexing2D[i].begin(), indexing2D[i].end(), -1);
}
for (int i = 0; i < (int)pts.size(); i++)
{
int line = pts[i].nPointIdx >> 16;
int ptIdx = pts[i].nPointIdx & 0x0000FFFF;
indexing2D[line][ptIdx] = i;
}
int ptSize = (int)pts.size();
if (ptSize == 0)
return;
std::vector<int> flags;
flags.resize(ptSize);
std::fill(flags.begin(), flags.end(), 0);
int idx = 0;
while (idx < (int)pts.size())
{
SVzNL3DPosition a_pt = pts[idx];
if (flags[idx] >= 0)
{
flags[idx] = -1;//·ÀÖ¹ÖØ¸´±»¼ÆËã
//н¨Ò»¸öcluster
std::vector< SVzNL3DPosition> a_cluster;
a_cluster.push_back(a_pt);
//pts[0].nPointIdx = -1;
_seedClustering_speedUp(
a_cluster,
pts,
flags,
clusterDist,
indexing2D,
lineNum, linePtSize, clusterCheckWin);
objClusters.push_back(a_cluster); //±£´æÒ»¸ö¾ÛÀà
}
idx++;
}
return;
}
//¶ÔÌØÕ÷µãµÄ¾ÛÀà
void wd_gridPointClustering(
std::vector<std::vector<SSG_featureClusteringInfo>>& featureMask,
std::vector<std::vector<SVzNL3DPoint>>& feature3DInfo,
int clusterCheckWin, //ËÑË÷´°¿Ú
SSG_treeGrowParam growParam,//¾ÛÀàÌõ¼þ
int clusterID, //µ±Ç°ClusterµÄID
std::vector< SVzNL2DPoint>& a_cluster, //result
SVzNL3DRangeD& clusterRoi //roi3D
)
{
int i = 0;
int lineNum = (int)featureMask.size();
int linePtNum = (int)featureMask[0].size();
featureMask[a_cluster[0].x][a_cluster[0].y].flag = 1; //·ÀÖ¹µÚÒ»¸ö±»Öظ´Ìí¼Ó
while (1)
{
if (i >= a_cluster.size())
break;
SVzNL2DPoint a_seedPos = a_cluster[i];
if ((a_seedPos.x == 752) && (a_seedPos.y == 2399))
int kkk = 1;
SSG_featureClusteringInfo& a_seed = featureMask[a_seedPos.x][a_seedPos.y];
SVzNL3DPoint& seedValue = feature3DInfo[a_seedPos.x][a_seedPos.y];
if (0 == a_seed.clusterID) //clusterID == 0, δ±»´¦Àí£¬ËÑË÷ÁÚÓò
{
for (int i = -clusterCheckWin; i <= clusterCheckWin; i++)
{
for (int j = -clusterCheckWin; j <= clusterCheckWin; j++)
{
int y = j + a_seedPos.y;
int x = i + a_seedPos.x;
if ((x == 645) && (y == 2240))
int kkk = 1;
if ((x >= 0) && (x < lineNum) && (y >= 0) && (y < linePtNum))
{
SSG_featureClusteringInfo& chk_seed = featureMask[x][y];
if ((chk_seed.featurType ==0) || (chk_seed.clusterID > 0)) //Ö»¼ì²éδ¾ÛÀàµÄÌØÕ÷µã
continue;
SVzNL3DPoint& chkValue = feature3DInfo[x][y];
double y_diff = abs(seedValue.y - chkValue.y);
double z_diff = abs(seedValue.z - chkValue.z);
double x_diff = abs(seedValue.x - chkValue.x);
if ((y_diff < growParam.yDeviation_max) && (z_diff < growParam.zDeviation_max) &&
(x_diff < growParam.maxSkipDistance))
{
if (0 == chk_seed.flag)//·ÀÖ¹±»Öظ´Ìí¼Ó
{
chk_seed.flag = 1;
SVzNL2DPoint new_seed = { x, y };
a_cluster.push_back(new_seed);
}
}
}
}
}
}
a_seed.clusterID = clusterID;
//¸üÐÂROI
clusterRoi.xRange.min = clusterRoi.xRange.min > seedValue.x ? seedValue.x : clusterRoi.xRange.min;
clusterRoi.xRange.max = clusterRoi.xRange.max < seedValue.x ? seedValue.x : clusterRoi.xRange.max;
clusterRoi.yRange.min = clusterRoi.yRange.min > seedValue.y ? seedValue.y : clusterRoi.yRange.min;
clusterRoi.yRange.max = clusterRoi.yRange.max < seedValue.y ? seedValue.y : clusterRoi.yRange.max;
clusterRoi.zRange.min = clusterRoi.zRange.min > seedValue.z ? seedValue.z : clusterRoi.zRange.min;
clusterRoi.zRange.max = clusterRoi.zRange.max < seedValue.z ? seedValue.z : clusterRoi.zRange.max;
i++;
}
return;
}
//¶ÔɨÃèÊý¾ÝµÄ¾ÛÀà
//SSG_intPair³ÉÔ±±äÁ¿¶¨Òå:
// data_0: flag
// data_1: valid point flag
// idx: cluster ID
void wd_gridPointClustering_2(
std::vector<std::vector<SVzNL3DPosition>>& gridData,
std::vector<std::vector<SSG_intPair>>& pointMaskInfo, //·ÀÖ¹¾ÛÀàÊ±ÖØ¸´Ñ¡ÖÐ
int clusterCheckWin, //ËÑË÷´°¿Ú
SSG_treeGrowParam growParam,//¾ÛÀàÌõ¼þ
int clusterID, //µ±Ç°ClusterµÄID
std::vector< SVzNL2DPoint>& a_cluster, //result
SVzNL3DRangeD& clusterRoi //roi3D
)
{
int i = 0;
int lineNum = (int)gridData.size();
int linePtNum = (int)gridData[0].size();
pointMaskInfo[a_cluster[0].x][a_cluster[0].y].data_0 = 1; //·ÀÖ¹µÚÒ»¸ö±»Öظ´Ìí¼Ó
while (1)
{
if (i >= a_cluster.size())
break;
SVzNL2DPoint a_seedPos = a_cluster[i];
if ((a_seedPos.x == 390) && (a_seedPos.y == 949))
int kkk = 1;
SSG_intPair& a_seed = pointMaskInfo[a_seedPos.x][a_seedPos.y];
SVzNL3DPosition& seedValue = gridData[a_seedPos.x][a_seedPos.y];
if (0 == a_seed.idx) //clusterID == 0, δ±»´¦Àí£¬ËÑË÷ÁÚÓò
{
for (int i = -clusterCheckWin; i <= clusterCheckWin; i++)
{
for (int j = -clusterCheckWin; j <= clusterCheckWin; j++)
{
int y = j + a_seedPos.y;
int x = i + a_seedPos.x;
if ((x == 390) && (y == 949))
int kkk = 1;
if ((x >= 0) && (x < lineNum) && (y >= 0) && (y < linePtNum))
{
SSG_intPair& chk_seed = pointMaskInfo[x][y];
if ((chk_seed.data_1 == 0) || (chk_seed.idx > 0)) //idx:clusterID, data_1:valid point
continue;
SVzNL3DPosition& chkValue = gridData[x][y];
double y_diff = abs(seedValue.pt3D.y - chkValue.pt3D.y);
double z_diff = abs(seedValue.pt3D.z - chkValue.pt3D.z);
double x_diff = abs(seedValue.pt3D.x - chkValue.pt3D.x);
if ((y_diff < growParam.yDeviation_max) && (z_diff < growParam.zDeviation_max) &&
(x_diff < growParam.maxSkipDistance))
{
if (0 == chk_seed.data_0)//·ÀÖ¹±»Öظ´Ìí¼Ó
{
chk_seed.data_0 = 1;
SVzNL2DPoint new_seed = { x, y };
a_cluster.push_back(new_seed);
}
}
}
}
}
}
a_seed.idx = clusterID;
//¸üÐÂROI
clusterRoi.xRange.min = clusterRoi.xRange.min > seedValue.pt3D.x ? seedValue.pt3D.x : clusterRoi.xRange.min;
clusterRoi.xRange.max = clusterRoi.xRange.max < seedValue.pt3D.x ? seedValue.pt3D.x : clusterRoi.xRange.max;
clusterRoi.yRange.min = clusterRoi.yRange.min > seedValue.pt3D.y ? seedValue.pt3D.y : clusterRoi.yRange.min;
clusterRoi.yRange.max = clusterRoi.yRange.max < seedValue.pt3D.y ? seedValue.pt3D.y : clusterRoi.yRange.max;
clusterRoi.zRange.min = clusterRoi.zRange.min > seedValue.pt3D.z ? seedValue.pt3D.z : clusterRoi.zRange.min;
clusterRoi.zRange.max = clusterRoi.zRange.max < seedValue.pt3D.z ? seedValue.pt3D.z : clusterRoi.zRange.max;
i++;
}
return;
}
//ʹÓþÛÀà·½·¨Íê³É8Á¬Í¨Á¬Í¨Óò·ÖÎö
void wd_gridPointClustering_labelling(
std::vector<std::vector<SSG_featureClusteringInfo>>& featureMask,
std::vector<std::vector<SVzNL3DPoint>>& feature3DInfo,
int clusterID, //µ±Ç°ClusterµÄID
std::vector< SVzNL2DPoint>& a_cluster, //result
SVzNLRect& clusterRoi //roi2D
)
{
int i = 0;
int lineNum = (int)featureMask.size();
int linePtNum = (int)featureMask[0].size();
while (1)
{
if (i >= a_cluster.size())
break;
SVzNL2DPoint a_seedPos = a_cluster[i];
if ((a_seedPos.x == 390) && (a_seedPos.y == 949))
int kkk = 1;
SSG_featureClusteringInfo& a_seed = featureMask[a_seedPos.x][a_seedPos.y];
if (0 == a_seed.clusterID) //clusterID == 0, δ±»´¦Àí£¬ËÑË÷ÁÚÓò
{
//8Á¬Í¨
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
int y = j + a_seedPos.y;
int x = i + a_seedPos.x;
if ((x == 390) && (y == 949))
int kkk = 1;
if ((x >= 0) && (x < lineNum) && (y >= 0) && (y < linePtNum))
{
SSG_featureClusteringInfo& chk_seed = featureMask[x][y];
if ((chk_seed.featurType == 0) || (chk_seed.clusterID > 0)) //Ö»¼ì²éδ¾ÛÀàµÄÌØÕ÷µã
continue;
if (0 == chk_seed.flag)//·ÀÖ¹±»Öظ´Ìí¼Ó
{
chk_seed.flag = 1;
SVzNL2DPoint new_seed = { x, y };
a_cluster.push_back(new_seed);
}
}
}
}
}
a_seed.clusterID = clusterID;
//¸üÐÂROI
clusterRoi.left = clusterRoi.left > a_seedPos.x ? a_seedPos.x : clusterRoi.left;
clusterRoi.right = clusterRoi.right < a_seedPos.x ? a_seedPos.x : clusterRoi.right;
clusterRoi.top = clusterRoi.top > a_seedPos.y ? a_seedPos.y : clusterRoi.top;
clusterRoi.bottom = clusterRoi.bottom < a_seedPos.y ? a_seedPos.y : clusterRoi.bottom;
i++;
}
return;
}
//ʹÓþÛÀà·½·¨Íê³É8Á¬Í¨Á¬Í¨Óò·ÖÎö
void wd_gridPointClustering_labelling_2(
std::vector<std::vector<SVzNL3DPoint>>& srcData,
std::vector<std::vector<SSG_clusterLabel>>& labelMask,
int clusterID, //µ±Ç°ClusterµÄID
std::vector< SVzNL2DPoint>& a_cluster, //result
SVzNL3DRangeD& clusterRoi //roi3D
)
{
int i = 0;
int lineNum = (int)srcData.size();
int linePtNum = (int)srcData[0].size();
SVzNL2DPoint& inputSeed = a_cluster[0];
labelMask[inputSeed.x][inputSeed.y].flag = 1; //µÚÒ»¸öÖÖ×Ó
while (1)
{
if (i >= a_cluster.size())
break;
SVzNL2DPoint a_seedPos = a_cluster[i];
if ((a_seedPos.x == 390) && (a_seedPos.y == 949))
int kkk = 1;
SSG_clusterLabel& a_seed = labelMask[a_seedPos.x][a_seedPos.y];
SVzNL3DPoint& a_feature3DValue = srcData[a_seedPos.x][a_seedPos.y];
if (0 == a_seed.clusterID) //clusterID == 0, δ±»´¦Àí£¬ËÑË÷ÁÚÓò
{
//8Á¬Í¨
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
int y = j + a_seedPos.y;
int x = i + a_seedPos.x;
if ((x == 390) && (y == 949))
int kkk = 1;
if ((x >= 0) && (x < lineNum) && (y >= 0) && (y < linePtNum))
{
SSG_clusterLabel& chk_seed = labelMask[x][y];
if ((chk_seed.validFlag == 0) || (chk_seed.clusterID > 0)) //Ö»¼ì²éδ¾ÛÀàµÄÌØÕ÷µã
continue;
if (0 == chk_seed.flag)//·ÀÖ¹±»Öظ´Ìí¼Ó
{
chk_seed.flag = 1;
SVzNL2DPoint new_seed = { x, y };
a_cluster.push_back(new_seed);
}
}
}
}
}
a_seed.clusterID = clusterID;
//¸üÐÂROI
clusterRoi.xRange.min = clusterRoi.xRange.min > a_feature3DValue.x ? a_feature3DValue.x : clusterRoi.xRange.min;
clusterRoi.xRange.max = clusterRoi.xRange.max < a_feature3DValue.x ? a_feature3DValue.x : clusterRoi.xRange.max;
clusterRoi.yRange.min = clusterRoi.yRange.min > a_feature3DValue.y ? a_feature3DValue.y : clusterRoi.yRange.min;
clusterRoi.yRange.max = clusterRoi.yRange.max < a_feature3DValue.y ? a_feature3DValue.y : clusterRoi.yRange.max;
clusterRoi.zRange.min = clusterRoi.zRange.min > a_feature3DValue.z ? a_feature3DValue.z : clusterRoi.zRange.min;
clusterRoi.zRange.max = clusterRoi.zRange.max < a_feature3DValue.z ? a_feature3DValue.z : clusterRoi.zRange.max;
i++;
}
return;
}