algoLib/sourceCode/wheelArchHeigthMeasure.cpp

495 lines
15 KiB
C++
Raw Normal View History

#include <vector>
#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
#include "wheelArchHeigthMeasure_Export.h"
#include <opencv2/opencv.hpp>
#include <limits>
//version 1.0.0 : base version release to customer
//version 1.1.0 : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD>
//version 1.2.0 : <20><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת180<38><30>
std::string m_strVersion = "1.2.0";
const char* wd_wheelArchHeigthMeasureVersion(void)
{
return m_strVersion.c_str();
}
//<2F><><EFBFBD><EFBFBD>ˮƽ<CBAE><C6BD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>Z<EFBFBD><5A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD>е<EFBFBD><D0B5><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ե<EFBFBD><D4B5><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>գ<EFBFBD><D5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˮƽ
//<2F><>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><E6B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
SSG_planeCalibPara wd_horizonCamera_getGroundCalibPara(
std::vector< std::vector<SVzNL3DPosition>>& scanLines)
{
return sg_HCameraVScan_getGroundCalibPara(scanLines);
}
//<2F><><EFBFBD><EFBFBD>ˮƽʱ<C6BD><CAB1>̬<EFBFBD><CCAC>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void wd_horizonCamera_lineDataR(
std::vector< SVzNL3DPosition>& a_line,
const double* camPoseR,
double groundH)
{
HCamera_lineDataRT_vector(a_line, camPoseR, groundH);
}
SVzNL3DPoint _ptRotate(SVzNL3DPoint pt3D, const double matrix3d[9])
{
SVzNL3DPoint _r_pt;
_r_pt.x = pt3D.x * matrix3d[0] + pt3D.y * matrix3d[1] + pt3D.z * matrix3d[2];
_r_pt.y = pt3D.x * matrix3d[3] + pt3D.y * matrix3d[4] + pt3D.z * matrix3d[5];
_r_pt.z = pt3D.x * matrix3d[6] + pt3D.y * matrix3d[7] + pt3D.z * matrix3d[8];
return _r_pt;
}
bool compareByPtSize(const SWD_clustersInfo& a, const SWD_clustersInfo& b) {
return a.ptSize > b.ptSize;
}
//<2F><>ȡ<EFBFBD><C8A1>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¶˵<C2B6>
void _getArcEndings(std::vector< std::vector<SVzNL3DPosition>>& scanLines, const int cluster_arc_id, std::vector<SVzNL2DPoint>& contourPts)
{
int lineNum = (int)scanLines.size();
for (int i = 0; i < lineNum; i++)
{
int ptNum = (int)scanLines[i].size();
int lastIdx = -1;
for (int j = 0; j < ptNum; j++)
{
if ((i == 380) && (j > 288))
int kkk = 1;
if ( (scanLines[i][j].nPointIdx == cluster_arc_id) && (scanLines[i][j].pt3D.z >1e-4))
lastIdx = j;
}
if (lastIdx >= 0)
{
SVzNL2DPoint a_pt = { i, lastIdx};
contourPts.push_back(a_pt);
}
}
}
//<2F><>ȡ<EFBFBD><C8A1>ü<EFBFBD><C3BC><EFBFBD>ӵ㣬<D3B5><E3A3AC><EFBFBD><EFBFBD>Ϊy<CEAA><79>С<EFBFBD>Ķ˵<C4B6>
int _getArcEndingsCenterPos(std::vector< std::vector<SVzNL3DPosition>>& scanLines, std::vector<SVzNL2DPoint>& contourPts)
{
double minY = DBL_MAX;
int seedPosIdx = 0;
for (int i = 0, i_max = (int)contourPts.size(); i < i_max; i++)
{
SVzNL2DPoint& a_pos = contourPts[i];
double y = scanLines[a_pos.x][a_pos.y].pt3D.y;
if ((minY > y) && (scanLines[a_pos.x][a_pos.y].pt3D.z > 1e-4))
{
seedPosIdx = i;
minY = y;
}
}
return seedPosIdx;
}
//ʹ<>ö˵<C3B6>ֱ<EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵽ֱ<E3B5BD>ߵľ<DFB5><C4BE><EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޵ķָ<C4B7>
int computeMaxDistPos(
int ptStartIdx, int ptEndIdx,
std::vector< SVzNL3DPosition>& lineData)
{
SVzNL3DPoint pt1 = lineData[ptStartIdx].pt3D;
SVzNL3DPoint pt2 = lineData[ptEndIdx].pt3D;
if ((pt1.z < 1e-4) || (pt2.z < 1e-4))
return -1;
double _a, _b, _c;
compute2ptLine_2(
pt1.y, pt1.z,
pt2.y, pt2.z,
&_a, &_b, &_c);
//compute2ptLine(pt1, pt2, &_a, &_b, &_c);
double denominator = sqrt(_a * _a + _b * _b);
//<2F><>һ<EFBFBD><D2BB>
_a = _a / denominator;
_b = _b / denominator;
_c = _c / denominator;
double maxDist = 0;
int maxPos = 0;
for (int i = ptStartIdx; i <= ptEndIdx; i++)
{
SVzNL3DPoint a_pt = lineData[i].pt3D;
if (a_pt.z > 1e-4)
{
double dist = abs(a_pt.y * _a + a_pt.z * _b + _c);
if (maxDist < dist)
{
maxDist = dist;
maxPos = i;
}
}
}
return maxPos;
}
void _extractArcFittingPts(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SVzNL2DPoint>& contourPts,
double chkWin,
int seedPosIdx,
std::vector< SVzNL2DPoint>& arcFittingPos)
{
int size = (int)contourPts.size();
arcFittingPos.push_back(contourPts[seedPosIdx]);
SVzNL3DPoint seedPt = scanLines[contourPts[seedPosIdx].x][contourPts[seedPosIdx].y].pt3D;
for (int i = seedPosIdx - 1; i >= 0; i--)
{
SVzNL2DPoint chkPos = contourPts[i];
SVzNL3DPoint chkPt = scanLines[chkPos.x][chkPos.y].pt3D;
double len = sqrt(pow(chkPt.x - seedPt.x, 2) + pow(chkPt.y - seedPt.y, 2));
if (len > chkWin)
break;
arcFittingPos.insert(arcFittingPos.begin(), chkPos);
}
for (int i = seedPosIdx + 1; i < size; i++)
{
SVzNL2DPoint chkPos = contourPts[i];
SVzNL3DPoint chkPt = scanLines[chkPos.x][chkPos.y].pt3D;
double len = sqrt(pow(chkPt.x - seedPt.x, 2) + pow(chkPt.y - seedPt.y, 2));
if (len > chkWin)
break;
arcFittingPos.push_back(chkPos);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>Ķ˵㣬<CBB5><E3A3AC><EFBFBD><EFBFBD>20mm
double chkLen = 20;
for (int i = 0, i_max = (int)arcFittingPos.size(); i < i_max; i++)
{
SVzNL2DPoint chkPos = arcFittingPos[i];
SVzNL3DPoint chkPt = scanLines[chkPos.x][chkPos.y].pt3D;
int endIdx = chkPos.y;
int startIdx = endIdx;
for (int m = endIdx - 1; m >= 0; m--)
{
SVzNL3DPoint a_pt = scanLines[chkPos.x][m].pt3D;
if (a_pt.z > 1e-4)
{
double len = sqrt(pow(a_pt.y - chkPt.y, 2) + pow(a_pt.z - chkPt.z, 2));
if (len > chkLen)
break;
startIdx = m;
}
}
if (startIdx != endIdx)
{
int maxPos = computeMaxDistPos(startIdx, endIdx, scanLines[chkPos.x]);
SVzNL3DPoint max_pt = scanLines[chkPos.x][maxPos].pt3D;
double len1 = sqrt(pow(max_pt.y - chkPt.y, 2) + pow(max_pt.z - chkPt.z, 2));
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD>ҵ㵽<D2B5>ױߵľ<DFB5><C4BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>
for (int m = maxPos - 1; m >= 0; m--)
{
SVzNL3DPoint a_pt = scanLines[chkPos.x][m].pt3D;
if (a_pt.z > 1e-4)
{
double len = sqrt(pow(a_pt.y - max_pt.y, 2) + pow(a_pt.z - max_pt.z, 2));
if (len > len1)
break;
startIdx = m;
}
}
maxPos = computeMaxDistPos(startIdx, endIdx, scanLines[chkPos.x]);
arcFittingPos[i].y = maxPos;
}
}
}
SVzNL3DPoint _getWheelArcFittingPoint(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
const int maskID,
std::vector< SVzNL2DPoint>& fittingPos,
SVzNL2DPoint& fittingPosition)
{
//upWheel, <20><>XYƽ<59><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>
std::vector<cv::Point2d> fittingPoints;
for (int i = 0, i_max = (int)fittingPos.size(); i < i_max; i++)
{
int lineIdx = fittingPos[i].x;
int ptIdx = fittingPos[i].y;
cv::Point2d a_pt = { scanLines[lineIdx][ptIdx].pt3D.x,scanLines[lineIdx][ptIdx].pt3D.y };
scanLines[lineIdx][ptIdx].nPointIdx = maskID;
fittingPoints.push_back(a_pt);
}
double a, b, c, mse, max_err;
bool fitResult = leastSquareParabolaFitEigen(
fittingPoints, a, b, c, mse, max_err);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6><EFBFBD>
SVzNL3DPoint fitPt;
fitPt.x = -b / (2 * a);
fitPt.y = (4 * a * c - b * b) / (4 * a);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD><D1B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
SVzNL2DPoint subOptiPtPos = { 0,0 };
double minLen = DBL_MAX;
for (int i = 0, i_max = (int)fittingPos.size(); i < i_max; i++)
{
int lineIdx = fittingPos[i].x;
int ptIdx = fittingPos[i].y;
cv::Point2d a_pt = { scanLines[lineIdx][ptIdx].pt3D.x,scanLines[lineIdx][ptIdx].pt3D.y };
double len = sqrt(pow(fitPt.x - a_pt.x, 2) + pow(fitPt.y - a_pt.y, 2));
if (minLen > len)
{
subOptiPtPos = fittingPos[i];
minLen = len;
}
}
fittingPosition = subOptiPtPos;
fitPt.z = scanLines[subOptiPtPos.x][subOptiPtPos.y].pt3D.z;
return fitPt;
}
//<2F><>ü<EFBFBD>߶Ȳ<DFB6><C8B2><EFBFBD>
WD_wheelArchInfo wd_wheelArchHeigthMeasure(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
const SSG_cornerParam cornerPara,
const SSG_lineSegParam lineSegPara,
const SSG_outlierFilterParam filterParam,
const SSG_treeGrowParam growParam,
const SSG_planeCalibPara groundCalibPara,
int* errCode)
{
*errCode = 0;
WD_wheelArchInfo result;
memset(&result, 0, sizeof(WD_wheelArchInfo));
int lineNum = (int)scanLines.size();
int linePtNum = (int)scanLines[0].size();
bool isGridData = true;
for (int line = 0; line < lineNum; line++)
{
std::vector<SVzNL3DPosition>& lineData = scanLines[line];
if (linePtNum != (int)lineData.size())
isGridData = false;
//<2F>˲<EFBFBD><CBB2><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><ECB3A3>
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], linePtNum, filterParam);
}
//<2F><><EFBFBD><EFBFBD>ˮƽɨ<C6BD><C9A8>
std::vector<std::vector<SVzNL3DPosition>> 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; //<2F><>ԭʼ<D4AD><CABC><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ʹ<EFBFBD>ã<EFBFBD>
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<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ
for (int line = 0; line < linePtNum; line++)
{
if (line == 974)
int kkk = 1;
std::vector<SVzNL3DPosition>& lineData = hLines_raw[line];
//<2F>˲<EFBFBD><CBB2><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><ECB3A3>
int ptNum = (int)lineData.size();
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], ptNum, filterParam);
}
//<2F><><EFBFBD><EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>̥
std::vector<std::vector<SSG_featureClusteringInfo>> featureInfoMask;
std::vector<std::vector<SVzNL3DPoint>> feature3DInfo;
featureInfoMask.resize(lineNum);
feature3DInfo.resize(lineNum);
for (int i = 0; i < lineNum; i++)
{
featureInfoMask[i].resize(linePtNum);
feature3DInfo[i].resize(linePtNum);
}
//<2F><><EFBFBD><EFBFBD>Mask
for (int line = 0; line < lineNum; line++)
{
std::vector<SVzNL3DPosition>& lineData = scanLines[line];
for (int ptIdx = 0; ptIdx < linePtNum; ptIdx++)
{
if (scanLines[line][ptIdx].pt3D.z > 1e-4)
{
SSG_featureClusteringInfo a_mask;
memset(&a_mask, 0, sizeof(SSG_featureClusteringInfo));
a_mask.featurType = 1;
a_mask.lineIdx = line;
a_mask.ptIdx = ptIdx;
featureInfoMask[line][ptIdx] = a_mask;
feature3DInfo[line][ptIdx] = scanLines[line][ptIdx].pt3D;
}
}
}
//<2F><><EFBFBD><EFBFBD>
//<2F><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>˼<EFBFBD><EFBFBD>ع<EFBFBD>˼·<CBBC><C2B7><EFBFBD>и<EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
std::vector<std::vector< SVzNL2DPoint>> clusters; //ֻ<><D6BB>¼λ<C2BC><CEBB>
std::vector<SWD_clustersInfo> clustersInfo;
int clusterID = 1;
int clusterCheckWin = 5;
for (int y = 0; y < linePtNum; y++)
{
for (int x = 0; x < lineNum; x++)
{
SSG_featureClusteringInfo& a_featureInfo = featureInfoMask[x][y];
if ((0 == a_featureInfo.featurType) || (a_featureInfo.clusterID > 0)) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>
continue;
SVzNL3DPoint& a_feature3DValue = feature3DInfo[x][y];
SVzNL3DRangeD a_clusterRoi;
a_clusterRoi.xRange.min = a_feature3DValue.x;
a_clusterRoi.xRange.max = a_feature3DValue.x;
a_clusterRoi.yRange.min = a_feature3DValue.y;
a_clusterRoi.yRange.max = a_feature3DValue.y;
a_clusterRoi.zRange.min = a_feature3DValue.z;
a_clusterRoi.zRange.max = a_feature3DValue.z;
SVzNL2DPoint a_seedPos = { x, y };
std::vector< SVzNL2DPoint> a_cluster;
a_cluster.push_back(a_seedPos);
wd_gridPointClustering(
featureInfoMask,//int<6E><74><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD>clusterID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>flag
feature3DInfo,//double,<2C><>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
clusterCheckWin, //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
growParam,//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
clusterID, //<2F><>ǰCluster<65><72>ID
a_cluster, //result
a_clusterRoi
);
clusters.push_back(a_cluster);
SWD_clustersInfo a_info;
a_info.clusterIdx = clusterID;
a_info.ptSize = (int)a_cluster.size();
a_info.roi3D = a_clusterRoi;
clustersInfo.push_back(a_info);
clusterID++;
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0A1A3><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ǰ壬<C7B0><E5A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><C7B3><EFBFBD>
std::sort(clustersInfo.begin(), clustersInfo.end(), compareByPtSize);
int cluseter_wheel_id, cluster_arc_id;
if (clustersInfo[0].roi3D.yRange.max > clustersInfo[1].roi3D.yRange.max)
{
cluseter_wheel_id = clustersInfo[0].clusterIdx;
cluster_arc_id = clustersInfo[1].clusterIdx;
}
else
{
cluseter_wheel_id = clustersInfo[1].clusterIdx;
cluster_arc_id = clustersInfo[0].clusterIdx;
}
std::vector< SVzNL2DPoint>& cluster_wheel = clusters[cluseter_wheel_id - 1];
std::vector< SVzNL2DPoint>& cluster_arc = clusters[cluster_arc_id - 1];
for (int i = 0, i_max = (int)cluster_wheel.size(); i < i_max; i++)
{
int lineIdx = cluster_wheel[i].x;
int ptIdx = cluster_wheel[i].y;
scanLines[lineIdx][ptIdx].nPointIdx = 1;
}
for (int i = 0, i_max = (int)cluster_arc.size(); i < i_max; i++)
{
int lineIdx = cluster_arc[i].x;
int ptIdx = cluster_arc[i].y;
scanLines[lineIdx][ptIdx].nPointIdx = 2;
}
//Ѱ<><D1B0><EFBFBD><EFBFBD>ü<EFBFBD><C3BC>
//(1)<29><><EFBFBD><EFBFBD>Ѱ<EFBFBD><D1B0><EFBFBD>¶˵㣨2<E3A3A8><32>ȡ<EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD>򣬾<EFBFBD>ȷȷ<C8B7><C8B7><EFBFBD>˵㣨3<E3A3A8><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><E3A3A8><EFBFBD>ߵ
std::vector<SVzNL2DPoint> arcEndings;
_getArcEndings(scanLines, 2, arcEndings); //<2F><>ü<EFBFBD><C3BC>ID<49><44>2
if (arcEndings.size() == 0)
{
*errCode = SX_ERR_INVALID_ARC;
return result;
}
int arcMidPos = _getArcEndingsCenterPos(scanLines, arcEndings);
//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD><EFBFBD>ȣ<EFBFBD>100mm<6D>ڵĵ㣬<C4B5><E3A3AC><EFBFBD>о<EFBFBD>ȷ<EFBFBD>߽<EFBFBD><DFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>
double chkWin = 100.0;
std::vector< SVzNL2DPoint> arcFittingPos;
_extractArcFittingPts(
scanLines,
arcEndings,
chkWin,
arcMidPos,
arcFittingPos);
//<2F><>XYƽ<59><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>
double outLineLen = 200;
SVzNL2DPoint arcPtPos;
SVzNL3DPoint arcPt = _getWheelArcFittingPoint(scanLines, 3, arcFittingPos, arcPtPos);
result.wheelArchPos = arcPt;
result.arcLine[0] = { arcPt.x - outLineLen, arcPt.y, arcPt.z };
result.arcLine[1] = { arcPt.x + outLineLen, arcPt.y, arcPt.z };
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>V<EFBFBD>Ͳۡ<CDB2><DBA1><EFBFBD><EFBFBD><EFBFBD>6mm<6D><6D><EFBFBD>Ƕ<EFBFBD><C7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>V<EFBFBD>Ͳ<EFBFBD>
std::vector< SVzNL2DPoint> upWheelPos;
std::vector< SVzNL2DPoint> downWheelPos;
int startLine = arcFittingPos[0].x;
int endLine = arcFittingPos.back().x;
SSG_cornerParam wheelCornerPara;
memset(&wheelCornerPara, 0, sizeof(SSG_cornerParam));
wheelCornerPara.scale = 6.0;
wheelCornerPara.cornerTh = 75.0;
for (int line = startLine; line <= endLine; line++)
{
std::vector<SSG_basicFeature1D> cornerFeatures;
sg_maskData_getLineCornerFeature(
scanLines[line],
line,
1, //<2F><><EFBFBD>ֵ<EFBFBD>IDΪ1
wheelCornerPara, //scaleͨ<65><CDA8>ȡbagH<67><48>1/4
cornerFeatures);
//ȡ<><C8A1>һ<EFBFBD><D2BB>Ϊup
if (cornerFeatures.size() >= 2)
{
upWheelPos.push_back(cornerFeatures[0].jumpPos2D);
downWheelPos.push_back(cornerFeatures.back().jumpPos2D);
}
}
SVzNL2DPoint upPos;
SVzNL3DPoint upWheelPt = _getWheelArcFittingPoint(scanLines, 4, upWheelPos, upPos);
result.wheelUpPos = upWheelPt;
result.upLine[0] = { upWheelPt.x - outLineLen, upWheelPt.y, upWheelPt.z };
result.upLine[1] = { upWheelPt.x + outLineLen, upWheelPt.y, upWheelPt.z };
SVzNL2DPoint downPos;
SVzNL3DPoint downWheelPt = _getWheelArcFittingPoint(scanLines, 5, downWheelPos, downPos);
result.wheelDownPos = downWheelPt;
result.downLine[0] = { downWheelPt.x - outLineLen, downWheelPt.y, downWheelPt.z };
result.downLine[1] = { downWheelPt.x + outLineLen, downWheelPt.y, downWheelPt.z };
double centerY = (upWheelPt.y + downWheelPt.y) / 2;
int searchLine = (upPos.x + downPos.x) / 2;
double minDist = DBL_MAX;
int minPtIdx = 0;
for (int i = 0; i < (int)scanLines[searchLine].size(); i++)
{
if (scanLines[searchLine][i].pt3D.z > 1e-4)
{
double dist = abs(scanLines[searchLine][i].pt3D.y - centerY);
if (minDist > dist)
{
minDist = dist;
minPtIdx = i;
}
}
}
result.centerLine[0] = { downWheelPt.x - outLineLen, centerY, scanLines[searchLine][minPtIdx].pt3D.z };
result.centerLine[1] = { downWheelPt.x + outLineLen, centerY, scanLines[searchLine][minPtIdx].pt3D.z };
result.archToCenterHeigth = centerY - arcPt.y;
result.archToGroundHeigth = groundCalibPara.planeHeight - arcPt.y;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۱<DBB1><EAB6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ
for (int i = 0; i < lineNum; i++)
lineDataRT_vector(scanLines[i], groundCalibPara.invRMatrix, -1);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ
result.wheelArchPos = _ptRotate(result.wheelArchPos, groundCalibPara.invRMatrix);
result.wheelUpPos = _ptRotate(result.wheelUpPos, groundCalibPara.invRMatrix);
result.wheelDownPos = _ptRotate(result.wheelDownPos, groundCalibPara.invRMatrix);
for (int i = 0; i < 2; i++)
{
result.arcLine[i] = _ptRotate(result.arcLine[i], groundCalibPara.invRMatrix);
result.centerLine[i] = _ptRotate(result.centerLine[i], groundCalibPara.invRMatrix);
result.downLine[i] = _ptRotate(result.downLine[i], groundCalibPara.invRMatrix);
result.upLine[i] = _ptRotate(result.upLine[i], groundCalibPara.invRMatrix);
}
return result;
}