wheelArchHeigthMeasure ver 1.0.0
-汽车轮眉高度测量初始版本
This commit is contained in:
parent
007ce93dbf
commit
7e51432bd2
@ -157,6 +157,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BQ_assemblyPosition", "BQ_a
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BQ_assemblyPosition_test", "BQ_assemblyPosition_test\BQ_assemblyPosition_test.vcxproj", "{BC38D1E5-10CB-438B-AC72-6012303CE139}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wheelArchHeigthMeaure", "wheelArchHeigthMeaure\wheelArchHeigthMeaure.vcxproj", "{CFE11556-106A-4216-BF62-FDA980528F7A}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{95DC3F1A-902A-490E-BD3B-B10463CF0EBD} = {95DC3F1A-902A-490E-BD3B-B10463CF0EBD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wheelArchHeigthMeasure_test", "wheelArchHeigthMeasure_test\wheelArchHeigthMeasure_test.vcxproj", "{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{95DC3F1A-902A-490E-BD3B-B10463CF0EBD} = {95DC3F1A-902A-490E-BD3B-B10463CF0EBD}
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A} = {CFE11556-106A-4216-BF62-FDA980528F7A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -413,6 +424,22 @@ Global
|
||||
{BC38D1E5-10CB-438B-AC72-6012303CE139}.Release|x64.Build.0 = Release|x64
|
||||
{BC38D1E5-10CB-438B-AC72-6012303CE139}.Release|x86.ActiveCfg = Release|Win32
|
||||
{BC38D1E5-10CB-438B-AC72-6012303CE139}.Release|x86.Build.0 = Release|Win32
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Debug|x64.Build.0 = Debug|x64
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Release|x64.ActiveCfg = Release|x64
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Release|x64.Build.0 = Release|x64
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CFE11556-106A-4216-BF62-FDA980528F7A}.Release|x86.Build.0 = Release|Win32
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Debug|x64.Build.0 = Debug|x64
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Debug|x86.Build.0 = Debug|Win32
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Release|x64.ActiveCfg = Release|x64
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Release|x64.Build.0 = Release|x64
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Release|x86.ActiveCfg = Release|Win32
|
||||
{BBF5341E-8447-45E9-ADA3-3E8A9B52F5EF}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@ -59,6 +59,14 @@ SG_APISHARED_EXPORT void sg_getLineCornerFeature(
|
||||
const SSG_cornerParam cornerPara, //scale通常取bagH的1/4
|
||||
SSG_lineFeature* line_features);
|
||||
|
||||
// 对激光线上由Mask(nPointIdx转义定义)指定的点提取激光线上的拐点特征
|
||||
SG_APISHARED_EXPORT void sg_maskData_getLineCornerFeature(
|
||||
std::vector< SVzNL3DPosition>& lineData,
|
||||
int lineIdx,
|
||||
int maskID,
|
||||
const SSG_cornerParam cornerPara, //scale通常取bagH的1/4
|
||||
std::vector<SSG_basicFeature1D>& features);
|
||||
|
||||
SG_APISHARED_EXPORT void sg_getLineCornerFeature_BQ(
|
||||
SVzNL3DPosition* lineData,
|
||||
int dataSize,
|
||||
@ -67,6 +75,20 @@ SG_APISHARED_EXPORT void sg_getLineCornerFeature_BQ(
|
||||
const SSG_cornerParam cornerPara,
|
||||
std::vector<SSG_basicFeature1D>& line_features);
|
||||
|
||||
SG_APISHARED_EXPORT void wd_getLineDataIntervals(
|
||||
std::vector<SVzNL3DPosition>& lineData,
|
||||
const SSG_lineSegParam lineSegPara,
|
||||
std::vector<SSG_RUN>& segs);
|
||||
|
||||
// 最小点集数量(小于此数无法拟合直线)
|
||||
const int MIN_POINT_COUNT = 3;
|
||||
//使用端点直线,检查点到直线的距离,大于门限的分割
|
||||
SG_APISHARED_EXPORT void split(
|
||||
SSG_RUN a_run,
|
||||
std::vector< SVzNL3DPosition>& lineData,
|
||||
const double maxError,
|
||||
std::vector< SSG_RUN>& lineSegs);
|
||||
|
||||
/// <summary>
|
||||
/// 提取激光线上的特征:跳变、低于z阈值、V及L型,用于粒径检测(PSM)
|
||||
/// seg端点:z距离大于门限
|
||||
@ -360,6 +382,12 @@ SG_APISHARED_EXPORT double fitCircleByLeastSquare(
|
||||
SVzNL3DPoint& center,
|
||||
double& radius);
|
||||
|
||||
//抛物线最小二乘拟合 y=ax^2 + bx + c
|
||||
SG_APISHARED_EXPORT bool leastSquareParabolaFitEigen(
|
||||
const std::vector<cv::Point2d>& points,
|
||||
double& a, double& b, double& c,
|
||||
double& mse, double& max_err);
|
||||
|
||||
//计算Z均值
|
||||
SG_APISHARED_EXPORT double computeMeanZ(std::vector< SVzNL3DPoint>& pts);
|
||||
|
||||
@ -446,6 +474,9 @@ SG_APISHARED_EXPORT SSG_planeCalibPara sg_getPlaneCalibPara(
|
||||
SVzNL3DLaserLine* laser3DPoints,
|
||||
int lineNum);
|
||||
|
||||
SG_APISHARED_EXPORT SSG_planeCalibPara sg_HCameraVScan_getGroundCalibPara(
|
||||
std::vector< std::vector<SVzNL3DPosition>>& scanLines);
|
||||
|
||||
//将一个平面调整为水平平面(z为固定值),
|
||||
SG_APISHARED_EXPORT SSG_planeCalibPara adjustPlaneToXYPlane(
|
||||
double plane_A, double plane_B, double plane_C //平面法向量
|
||||
@ -487,6 +518,10 @@ SG_APISHARED_EXPORT void lineDataRT_vector(
|
||||
std::vector< SVzNL3DPosition>& a_line,
|
||||
const double* camPoseR,
|
||||
double groundH);
|
||||
SG_APISHARED_EXPORT void HCamera_lineDataRT_vector(
|
||||
std::vector< SVzNL3DPosition>& a_line,
|
||||
const double* camPoseR,
|
||||
double groundH);
|
||||
SG_APISHARED_EXPORT void lineDataRT_RGBD(
|
||||
SVzNLXYZRGBDLaserLine* a_line,
|
||||
const double* camPoseR,
|
||||
|
||||
@ -525,3 +525,10 @@ typedef struct
|
||||
double cornerAngle;
|
||||
int cornerDir;
|
||||
}SWD_polarPeakInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int clusterIdx;
|
||||
int ptSize;
|
||||
SVzNL3DRangeD roi3D;
|
||||
}SWD_clustersInfo;
|
||||
|
||||
@ -346,6 +346,148 @@ double fitCircleByLeastSquare(
|
||||
return err;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool leastSquareParabolaFit(const std::vector<cv::Point2d>& points,
|
||||
double& a, double& b, double& c,
|
||||
double& mse, double& max_err)
|
||||
{
|
||||
// 校验点集数量(至少3个点才能拟合抛物线)
|
||||
int n = points.size();
|
||||
if (n < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 初始化各项求和参数
|
||||
double sum_x = 0.0, sum_x2 = 0.0, sum_x3 = 0.0, sum_x4 = 0.0;
|
||||
double sum_y = 0.0, sum_xy = 0.0, sum_x2y = 0.0;
|
||||
|
||||
// 计算各项求和
|
||||
for (const auto& p : points) {
|
||||
double x = p.x;
|
||||
double y = p.y;
|
||||
double x2 = x * x;
|
||||
double x3 = x2 * x;
|
||||
double x4 = x3 * x;
|
||||
|
||||
sum_x += x;
|
||||
sum_x2 += x2;
|
||||
sum_x3 += x3;
|
||||
sum_x4 += x4;
|
||||
sum_y += y;
|
||||
sum_xy += x * y;
|
||||
sum_x2y += x2 * y;
|
||||
}
|
||||
|
||||
// 构建线性方程组 M * [a,b,c]^T = N
|
||||
// M矩阵:3x3
|
||||
double M[3][3] = {
|
||||
{sum_x4, sum_x3, sum_x2},
|
||||
{sum_x3, sum_x2, sum_x},
|
||||
{sum_x2, sum_x, (double)n}
|
||||
};
|
||||
|
||||
// N向量:3x1
|
||||
double N[3] = { sum_x2y, sum_xy, sum_y };
|
||||
|
||||
// 高斯消元法求解线性方程组(3元一次方程组)
|
||||
// 步骤1:将M转化为上三角矩阵
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// 选主元(避免除数为0)
|
||||
int pivot = i;
|
||||
for (int j = i; j < 3; j++) {
|
||||
if (fabs(M[j][i]) > fabs(M[pivot][i])) {
|
||||
pivot = j;
|
||||
}
|
||||
}
|
||||
// 交换行
|
||||
std::swap(M[i], M[pivot]);
|
||||
std::swap(N[i], N[pivot]);
|
||||
|
||||
// 归一化主元行
|
||||
double div = M[i][i];
|
||||
if (fabs(div) < 1e-10) {
|
||||
return false;
|
||||
}
|
||||
for (int j = i; j < 3; j++) {
|
||||
M[i][j] /= div;
|
||||
}
|
||||
N[i] /= div;
|
||||
|
||||
// 消去下方行
|
||||
for (int j = i + 1; j < 3; j++) {
|
||||
double factor = M[j][i];
|
||||
for (int k = i; k < 3; k++) {
|
||||
M[j][k] -= factor * M[i][k];
|
||||
}
|
||||
N[j] -= factor * N[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 步骤2:回代求解
|
||||
c = N[2];
|
||||
b = N[1] - M[1][2] * c;
|
||||
a = N[0] - M[0][1] * b - M[0][2] * c;
|
||||
|
||||
// 计算拟合误差
|
||||
mse = 0.0;
|
||||
max_err = 0.0;
|
||||
for (const auto& p : points) {
|
||||
double y_fit = a * p.x * p.x + b * p.x + c;
|
||||
double err = y_fit - p.y;
|
||||
double err_abs = fabs(err);
|
||||
mse += err * err;
|
||||
if (err_abs > max_err) {
|
||||
max_err = err_abs;
|
||||
}
|
||||
}
|
||||
mse /= n; // 均方误差
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
bool leastSquareParabolaFitEigen(
|
||||
const std::vector<cv::Point2d>& points,
|
||||
double& a, double& b, double& c,
|
||||
double& mse, double& max_err)
|
||||
{
|
||||
int n = points.size();
|
||||
if (n < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 构建系数矩阵A和目标向量B
|
||||
Eigen::MatrixXd A(n, 3);
|
||||
Eigen::VectorXd B(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
double x = points[i].x;
|
||||
A(i, 0) = x * x;
|
||||
A(i, 1) = x;
|
||||
A(i, 2) = 1.0;
|
||||
B(i) = points[i].y;
|
||||
}
|
||||
|
||||
// 最小二乘求解:Ax = B,直接调用Eigen的求解器
|
||||
Eigen::Vector3d coeffs = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(B);
|
||||
a = coeffs(0);
|
||||
b = coeffs(1);
|
||||
c = coeffs(2);
|
||||
|
||||
// 计算误差
|
||||
mse = 0.0;
|
||||
max_err = 0.0;
|
||||
for (const auto& p : points) {
|
||||
double y_fit = a * p.x * p.x + b * p.x + c;
|
||||
double err = y_fit - p.y;
|
||||
double err_abs = fabs(err);
|
||||
mse += err * err;
|
||||
if (err_abs > max_err) {
|
||||
max_err = err_abs;
|
||||
}
|
||||
}
|
||||
mse /= n;
|
||||
return true;
|
||||
}
|
||||
|
||||
//¼ÆËãZ¾ùÖµ
|
||||
double computeMeanZ(std::vector< SVzNL3DPoint>& pts)
|
||||
{
|
||||
@ -1915,6 +2057,162 @@ SSG_planeCalibPara sg_getPlaneCalibPara2(
|
||||
return planePara;
|
||||
}
|
||||
|
||||
//水平安装相机垂直扫描模式地面调平
|
||||
SSG_planeCalibPara sg_HCameraVScan_getGroundCalibPara(
|
||||
std::vector< std::vector<SVzNL3DPosition>>& scanLines)
|
||||
{
|
||||
//设置初始结果
|
||||
double initCalib[9] = {
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0 };
|
||||
SSG_planeCalibPara planePara;
|
||||
for (int i = 0; i < 9; i++)
|
||||
planePara.planeCalib[i] = initCalib[i];
|
||||
planePara.planeHeight = -1.0;
|
||||
|
||||
//提取地面直线段
|
||||
SSG_lineSegParam lineSegPara;
|
||||
lineSegPara.maxDist = 2.0;
|
||||
lineSegPara.segGapTh_y = 5.0; //y方向间隔大于5mm认为是分段
|
||||
lineSegPara.segGapTh_z = 10.0; //z方向间隔大于10mm认为是分段
|
||||
|
||||
std::vector<cv::Point3f> groundPts;
|
||||
int lineNum = (int)scanLines.size();
|
||||
for (int line = 0; line < lineNum; line++)
|
||||
{
|
||||
std::vector<SVzNL3DPosition>& lineData = scanLines[line];
|
||||
int dataSize = (int)lineData.size();
|
||||
//去除零点
|
||||
std::vector<SSG_RUN> segs;
|
||||
wd_getLineDataIntervals(lineData, lineSegPara, segs);
|
||||
if (segs.size() == 0)
|
||||
continue;
|
||||
|
||||
//对最后一段进行处理
|
||||
SSG_RUN lastSeg = segs.back();
|
||||
//直线分割
|
||||
std::vector< SSG_RUN> segmentationLines;
|
||||
split(lastSeg, lineData, lineSegPara.maxDist, segmentationLines);
|
||||
//检查最后一段的直线段的斜率
|
||||
SSG_RUN lastLine = segmentationLines.back();
|
||||
//计算斜率
|
||||
int startIdx = lastLine.start;
|
||||
int endIdx = lastLine.start + lastLine.len - 1;
|
||||
double dy = abs(lineData[endIdx].pt3D.y - lineData[startIdx].pt3D.y) + 1e-8; //加扰,防止dy为0
|
||||
double dz = lineData[startIdx].pt3D.z - lineData[endIdx].pt3D.z;
|
||||
if (dz > 0)
|
||||
{
|
||||
double tan_k = dz / dy;
|
||||
if (tan_k > tan(PI / 3)) //大于60度,合格
|
||||
{
|
||||
for (int i = startIdx; i <= endIdx; i++)
|
||||
{
|
||||
if (lineData[i].pt3D.z > 1e-4)
|
||||
{
|
||||
lineData[i].nPointIdx = 1;
|
||||
cv::Point3f a_pt = cv::Point3f(lineData[i].pt3D.x, lineData[i].pt3D.y, lineData[i].pt3D.z);
|
||||
groundPts.push_back(a_pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//平面拟合
|
||||
std::vector<double> planceFunc;
|
||||
vzCaculateLaserPlane(groundPts, planceFunc);
|
||||
|
||||
#if 1 //两个向量的旋转旋转,使用四元数法,
|
||||
Vector3 a = Vector3(planceFunc[0], planceFunc[1], planceFunc[2]);
|
||||
Vector3 b = Vector3(0, 1.0, 0);
|
||||
Quaternion quanPara = rotationBetweenVectors(a, b);
|
||||
|
||||
RotationMatrix rMatrix;
|
||||
quaternionToMatrix(quanPara, rMatrix.data);
|
||||
//计算反向旋转矩阵
|
||||
Quaternion invQuanPara = rotationBetweenVectors(b, a);
|
||||
RotationMatrix invMatrix;
|
||||
quaternionToMatrix(invQuanPara, invMatrix.data);
|
||||
#else //根据平面的法向量计算欧拉角,进而计算旋转矩阵
|
||||
//参数计算
|
||||
SSG_EulerAngles eulerPra = planeNormalToEuler(planceFunc[0], planceFunc[1], planceFunc[2]);
|
||||
//反射进行校正
|
||||
eulerPra.roll = eulerPra.roll;
|
||||
eulerPra.pitch = eulerPra.pitch;
|
||||
eulerPra.yaw = eulerPra.yaw;
|
||||
RotationMatrix rMatrix = eulerToRotationMatrix(eulerPra.yaw, eulerPra.pitch, eulerPra.roll);
|
||||
#endif
|
||||
|
||||
planePara.planeCalib[0] = rMatrix.data[0][0];
|
||||
planePara.planeCalib[1] = rMatrix.data[0][1];
|
||||
planePara.planeCalib[2] = rMatrix.data[0][2];
|
||||
planePara.planeCalib[3] = rMatrix.data[1][0];
|
||||
planePara.planeCalib[4] = rMatrix.data[1][1];
|
||||
planePara.planeCalib[5] = rMatrix.data[1][2];
|
||||
planePara.planeCalib[6] = rMatrix.data[2][0];
|
||||
planePara.planeCalib[7] = rMatrix.data[2][1];
|
||||
planePara.planeCalib[8] = rMatrix.data[2][2];
|
||||
|
||||
planePara.invRMatrix[0] = invMatrix.data[0][0];
|
||||
planePara.invRMatrix[1] = invMatrix.data[0][1];
|
||||
planePara.invRMatrix[2] = invMatrix.data[0][2];
|
||||
planePara.invRMatrix[3] = invMatrix.data[1][0];
|
||||
planePara.invRMatrix[4] = invMatrix.data[1][1];
|
||||
planePara.invRMatrix[5] = invMatrix.data[1][2];
|
||||
planePara.invRMatrix[6] = invMatrix.data[2][0];
|
||||
planePara.invRMatrix[7] = invMatrix.data[2][1];
|
||||
planePara.invRMatrix[8] = invMatrix.data[2][2];
|
||||
|
||||
#if 0 //test: 两个矩阵的乘积必须是单位阵
|
||||
double testMatrix[3][3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
testMatrix[i][j] = 0;
|
||||
for (int m = 0; m < 3; m++)
|
||||
testMatrix[i][j] += invMatrix.data[i][m] * rMatrix.data[m][j];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//数据进行转换
|
||||
SVzNLRangeD calibYRange = { 0, -1 };
|
||||
SVzNLRangeD topYRange = { 0, -1 };
|
||||
double sumMeanY = 0;
|
||||
int sumSize = 0;
|
||||
for (int i = 0, i_max = (int)groundPts.size(); i < i_max; i++)
|
||||
{
|
||||
|
||||
cv::Point3f a_calibPt;
|
||||
a_calibPt.x = (float)(groundPts[i].x * planePara.planeCalib[0] + groundPts[i].y * planePara.planeCalib[1] + groundPts[i].z * planePara.planeCalib[2]);
|
||||
a_calibPt.y = (float)(groundPts[i].x * planePara.planeCalib[3] + groundPts[i].y * planePara.planeCalib[4] + groundPts[i].z * planePara.planeCalib[5]);
|
||||
a_calibPt.z = (float)(groundPts[i].x * planePara.planeCalib[6] + groundPts[i].y * planePara.planeCalib[7] + groundPts[i].z * planePara.planeCalib[8]);
|
||||
//z
|
||||
if (calibYRange.max < calibYRange.min)
|
||||
{
|
||||
calibYRange.min = a_calibPt.y;
|
||||
calibYRange.max = a_calibPt.y;
|
||||
sumMeanY += a_calibPt.y;
|
||||
sumSize++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (calibYRange.min > a_calibPt.y)
|
||||
calibYRange.min = a_calibPt.y;
|
||||
if (calibYRange.max < a_calibPt.y)
|
||||
calibYRange.max = a_calibPt.y;
|
||||
sumMeanY += a_calibPt.y;
|
||||
sumSize++;
|
||||
}
|
||||
}
|
||||
if (sumSize > 0)
|
||||
sumMeanY = sumMeanY / (double)sumSize;
|
||||
planePara.planeHeight = sumMeanY; // calibZRange.min;
|
||||
|
||||
return planePara;
|
||||
}
|
||||
|
||||
SSG_planeCalibPara sg_getPlaneCalibPara2_ROI(
|
||||
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
|
||||
SVzNL3DRangeD roi)
|
||||
@ -2311,6 +2609,28 @@ void lineDataRT_vector(std::vector< SVzNL3DPosition>& a_line, const double* camP
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void HCamera_lineDataRT_vector(std::vector< SVzNL3DPosition>& a_line, const double* camPoseR, double groundH)
|
||||
{
|
||||
for (int i = 0; i < a_line.size(); i++)
|
||||
{
|
||||
SVzNL3DPoint a_pt = a_line[i].pt3D;
|
||||
if (a_pt.z < 1e-4)
|
||||
continue;
|
||||
double x = a_pt.x * camPoseR[0] + a_pt.y * camPoseR[1] + a_pt.z * camPoseR[2];
|
||||
double y = a_pt.x * camPoseR[3] + a_pt.y * camPoseR[4] + a_pt.z * camPoseR[5];
|
||||
double z = a_pt.x * camPoseR[6] + a_pt.y * camPoseR[7] + a_pt.z * camPoseR[8];
|
||||
if ((groundH > 0) && (y >= groundH)) //去除地面
|
||||
z = 0;
|
||||
a_pt.x = x;
|
||||
a_pt.y = y;
|
||||
a_pt.z = z;
|
||||
a_line[i].pt3D = a_pt;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void lineDataRT_RGBD(SVzNLXYZRGBDLaserLine* a_line, const double* camPoseR, double groundH)
|
||||
{
|
||||
for (int i = 0; i < a_line->nPointCnt; i++)
|
||||
|
||||
@ -25,3 +25,6 @@
|
||||
//뀔관
|
||||
#define SX_BAG_TRAY_EMPTY -2201
|
||||
|
||||
//汽车轮眉高度测量
|
||||
#define SX_ERR_INVALID_ARC -2301
|
||||
|
||||
|
||||
@ -205,6 +205,55 @@ if (i == 370)
|
||||
return;
|
||||
}
|
||||
|
||||
void wd_getLineDataIntervals(
|
||||
std::vector<SVzNL3DPosition>& lineData,
|
||||
const SSG_lineSegParam lineSegPara,
|
||||
std::vector<SSG_RUN>& segs)
|
||||
{
|
||||
int runIdx = 1;
|
||||
SSG_RUN a_run = { 0, -1, 0 }; //startIdx, len, lastIdx
|
||||
double pre_z = 0;
|
||||
double pre_y = 0;
|
||||
int dataSize = (int)lineData.size();
|
||||
for (int i = 0; i < dataSize; i++)
|
||||
{
|
||||
lineData[i].nPointIdx = 0; //转义使用
|
||||
if (lineData[i].pt3D.z > 1e-4)
|
||||
{
|
||||
if (a_run.len < 0)
|
||||
{
|
||||
a_run.start = i;
|
||||
a_run.len = 1;
|
||||
a_run.value = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
double z_diff = abs(lineData[i].pt3D.z - pre_z);
|
||||
double y_diff = abs(lineData[i].pt3D.y - pre_y);
|
||||
if ((z_diff < lineSegPara.segGapTh_z) && (y_diff < lineSegPara.segGapTh_y))
|
||||
{
|
||||
a_run.len = i - a_run.start + 1;
|
||||
a_run.value = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
a_run.value = runIdx;
|
||||
segs.push_back(a_run);
|
||||
runIdx++;
|
||||
|
||||
a_run.start = i;
|
||||
a_run.len = 1;
|
||||
a_run.value = i;
|
||||
}
|
||||
}
|
||||
pre_z = lineData[i].pt3D.z;
|
||||
pre_y = lineData[i].pt3D.y;
|
||||
}
|
||||
}
|
||||
if (a_run.len > 0)
|
||||
segs.push_back(a_run);
|
||||
}
|
||||
|
||||
//滤除离群点:z跳变门限方法
|
||||
void sg_lineDataRemoveOutlier_changeOriginData(
|
||||
SVzNL3DPosition* lineData,
|
||||
@ -1500,6 +1549,233 @@ void sg_getLineCornerFeature(
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对激光线上由Mask(nPointIdx转义定义)指定的点提取激光线上的拐点特征
|
||||
/// 算法流程:
|
||||
/// (1)逐点计算前向角和后向角
|
||||
/// (2)逐点计算拐角,顺时针为负,逆时针为正
|
||||
/// (3)搜索正拐角的极大值。
|
||||
/// (4)判断拐角是否为跳变
|
||||
/// </summary>
|
||||
void sg_maskData_getLineCornerFeature(
|
||||
std::vector< SVzNL3DPosition>& lineData,
|
||||
int lineIdx,
|
||||
int maskID,
|
||||
const SSG_cornerParam cornerPara, //scale通常取bagH的1/4
|
||||
std::vector<SSG_basicFeature1D>& features)
|
||||
{
|
||||
//去除零点
|
||||
int dataSize = (int)lineData.size();
|
||||
std::vector< SVzNL3DPosition> vldPts;
|
||||
for (int i = 0; i < dataSize; i++)
|
||||
{
|
||||
SVzNL3DPosition a_pt = lineData[i];
|
||||
a_pt.nPointIdx = i;
|
||||
if ( (lineData[i].pt3D.z > 1e-4) &&(lineData[i].nPointIdx == maskID))
|
||||
vldPts.push_back(a_pt);
|
||||
}
|
||||
//计算前向角和后向角
|
||||
std::vector< SSG_pntDirAngle> corners;
|
||||
corners.resize(vldPts.size());
|
||||
for (int i = 0, i_max = (int)vldPts.size(); i < i_max; i++)
|
||||
{
|
||||
if (vldPts[i].nPointIdx == 521)
|
||||
int kkk = 1;
|
||||
//前向寻找
|
||||
int pre_i = -1;
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
double dist = sqrt(pow(vldPts[i].pt3D.y - vldPts[j].pt3D.y, 2) +
|
||||
pow(vldPts[i].pt3D.z - vldPts[j].pt3D.z, 2));
|
||||
if (dist >= cornerPara.scale * 4)
|
||||
{
|
||||
pre_i = -1;
|
||||
break;
|
||||
}
|
||||
else if (dist >= cornerPara.scale)
|
||||
{
|
||||
pre_i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//后向寻找
|
||||
int post_i = -1;
|
||||
for (int j = i + 1; j < i_max; j++)
|
||||
{
|
||||
double dist = sqrt(pow(vldPts[i].pt3D.y - vldPts[j].pt3D.y, 2) +
|
||||
pow(vldPts[i].pt3D.z - vldPts[j].pt3D.z, 2));
|
||||
if (dist >= cornerPara.scale * 4)
|
||||
{
|
||||
post_i = -1;
|
||||
break;
|
||||
}
|
||||
else if (dist >= cornerPara.scale)
|
||||
{
|
||||
post_i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//计算拐角
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
double tanValue_pre = (vldPts[i].pt3D.z - vldPts[pre_i].pt3D.z) / abs(vldPts[i].pt3D.y - vldPts[pre_i].pt3D.y);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//搜索拐角极值
|
||||
int _state = 0;
|
||||
int pre_i = -1;
|
||||
int sEdgePtIdx = -1;
|
||||
int eEdgePtIdx = -1;
|
||||
SSG_pntDirAngle* pre_data = NULL;
|
||||
std::vector< SSG_pntDirAngle> cornerPeakP;
|
||||
std::vector< SSG_pntDirAngle> cornerPeakM;
|
||||
for (int i = 0, i_max = (int)vldPts.size(); i < i_max; i++)
|
||||
{
|
||||
if (i == 275)
|
||||
int kkk = 1;
|
||||
SSG_pntDirAngle* curr_data = &corners[i];
|
||||
if (curr_data->pntIdx < 0)
|
||||
{
|
||||
if (i == i_max - 1) //最后一个
|
||||
{
|
||||
if (1 == _state) //上升
|
||||
{
|
||||
cornerPeakP.push_back(corners[eEdgePtIdx]);
|
||||
}
|
||||
else if (2 == _state) //下降
|
||||
{
|
||||
cornerPeakM.push_back(corners[eEdgePtIdx]);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
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) //下降
|
||||
{
|
||||
cornerPeakP.push_back(*pre_data);
|
||||
_state = 2;
|
||||
}
|
||||
break;
|
||||
case 2: //下降
|
||||
if (cornerDiff > 0) // 上升
|
||||
{
|
||||
cornerPeakM.push_back(*pre_data);
|
||||
_state = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_state = 0;
|
||||
break;
|
||||
}
|
||||
pre_data = curr_data;
|
||||
pre_i = i;
|
||||
}
|
||||
//注意:最后一个不处理,为基座位置
|
||||
|
||||
//极小值点(峰顶)
|
||||
//极值比较,在尺度窗口下寻找局部极值点
|
||||
double square_distTh = 4 * cornerPara.scale * cornerPara.scale; //2倍的cornerScale。
|
||||
for (int i = 0, i_max = (int)cornerPeakP.size(); i < i_max; i++)
|
||||
{
|
||||
if (cornerPeakP[i].corner < cornerPara.cornerTh)
|
||||
continue;
|
||||
|
||||
bool isPeak = true;
|
||||
//向前搜索
|
||||
int cornerPtIdx = cornerPeakP[i].pntIdx;
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
int prePtIdx = cornerPeakP[j].pntIdx;
|
||||
double dist = pow(vldPts[cornerPtIdx].pt3D.y - vldPts[prePtIdx].pt3D.y, 2); // + pow(pkTop[i].pt3D.x - pkTop[j].pt3D.x, 2) ;
|
||||
if (dist > square_distTh) //超出尺度窗口
|
||||
break;
|
||||
|
||||
if (cornerPeakP[i].corner < cornerPeakP[j].corner)
|
||||
{
|
||||
isPeak = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//向后搜索
|
||||
if (true == isPeak)
|
||||
{
|
||||
cornerPtIdx = cornerPeakP[i].pntIdx;
|
||||
for (int j = i + 1; j < i_max; j++)
|
||||
{
|
||||
int postPtIdx = cornerPeakP[j].pntIdx;
|
||||
double dist = pow(vldPts[cornerPtIdx].pt3D.y - vldPts[postPtIdx].pt3D.y, 2); // +pow(pkTop[i].pt3D.x - pkTop[j].pt3D.x, 2);
|
||||
if (dist > square_distTh) //超出尺度窗口
|
||||
break;
|
||||
|
||||
if (cornerPeakP[i].corner < cornerPeakP[j].corner)
|
||||
{
|
||||
isPeak = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (true == isPeak)
|
||||
{
|
||||
SSG_basicFeature1D a_feature;
|
||||
if ((cornerPeakP[i].backwardAngle > cornerPara.jumpCornerTh_1) && (cornerPeakP[i].forwardAngle > -cornerPara.jumpCornerTh_2))
|
||||
a_feature.featureType = LINE_FEATURE_L_JUMP_H2L;
|
||||
else if ((cornerPeakP[i].forwardAngle < -cornerPara.jumpCornerTh_1) && (cornerPeakP[i].backwardAngle < cornerPara.jumpCornerTh_2))
|
||||
a_feature.featureType = LINE_FEATURE_L_JUMP_L2H;
|
||||
else
|
||||
a_feature.featureType = LINE_FEATURE_CORNER_V;
|
||||
a_feature.featureValue = cornerPeakP[i].corner;
|
||||
|
||||
a_feature.jumpPos = vldPts[cornerPtIdx].pt3D;
|
||||
a_feature.jumpPos2D = { lineIdx, vldPts[cornerPtIdx].nPointIdx };
|
||||
features.push_back(a_feature);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提取激光线上的拐点特征,水平端点视为Corner
|
||||
/// seg端点:z距离或y距离大于门限
|
||||
@ -2558,8 +2834,6 @@ void wd_getRingArcFeature(
|
||||
return;
|
||||
}
|
||||
|
||||
// 最小点集数量(小于此数无法拟合直线)
|
||||
const int MIN_POINT_COUNT = 3;
|
||||
//使用端点直线,检查点到直线的距离,大于门限的分割
|
||||
void split(
|
||||
SSG_RUN a_run,
|
||||
@ -2628,46 +2902,7 @@ void wd_surfaceLineSegment(
|
||||
int dataSize = (int)lineData.size();
|
||||
//去除零点
|
||||
std::vector<SSG_RUN> segs;
|
||||
int runIdx = 1;
|
||||
SSG_RUN a_run = { 0, -1, 0 }; //startIdx, len, lastIdx
|
||||
double pre_z = 0;
|
||||
double pre_y = 0;
|
||||
for (int i = 0; i < dataSize; i++)
|
||||
{
|
||||
if (lineData[i].pt3D.z > 1e-4)
|
||||
{
|
||||
if (a_run.len < 0)
|
||||
{
|
||||
a_run.start = i;
|
||||
a_run.len = 1;
|
||||
a_run.value = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
double z_diff = abs(lineData[i].pt3D.z - pre_z);
|
||||
double y_diff = abs(lineData[i].pt3D.y - pre_y);
|
||||
if ((z_diff < lineSegPara.segGapTh_z) && (y_diff < lineSegPara.segGapTh_y))
|
||||
{
|
||||
a_run.len = i - a_run.start + 1;
|
||||
a_run.value = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
a_run.value = runIdx;
|
||||
segs.push_back(a_run);
|
||||
runIdx++;
|
||||
|
||||
a_run.start = i;
|
||||
a_run.len = 1;
|
||||
a_run.value = i;
|
||||
}
|
||||
}
|
||||
pre_z = lineData[i].pt3D.z;
|
||||
pre_y = lineData[i].pt3D.y;
|
||||
}
|
||||
}
|
||||
if (a_run.len > 0)
|
||||
segs.push_back(a_run);
|
||||
wd_getLineDataIntervals(lineData, lineSegPara, segs);
|
||||
|
||||
//逐段处理
|
||||
int segSize = (int)segs.size();
|
||||
|
||||
492
sourceCode/wheelArchHeigthMeasure.cpp
Normal file
492
sourceCode/wheelArchHeigthMeasure.cpp
Normal file
@ -0,0 +1,492 @@
|
||||
#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
|
||||
std::string m_strVersion = "1.0.0";
|
||||
const char* wd_wheelArchHeigthMeasureVersion(void)
|
||||
{
|
||||
return m_strVersion.c_str();
|
||||
}
|
||||
|
||||
//相机水平安装计算地面调平参数。
|
||||
//相机Z轴基本平行地面时,需要以地面为参照,将相机调水平
|
||||
//旋转矩阵为调平参数,即将平面法向调整为垂直向量的参数
|
||||
SSG_planeCalibPara wd_horizonCamera_getGroundCalibPara(
|
||||
std::vector< std::vector<SVzNL3DPosition>>& scanLines)
|
||||
{
|
||||
return sg_HCameraVScan_getGroundCalibPara(scanLines);
|
||||
}
|
||||
|
||||
//相机水平时姿态调平,并去除地面
|
||||
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;
|
||||
}
|
||||
|
||||
//提取轮眉区域的下端点
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//提取轮眉种子点,定义为y最小的端点
|
||||
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;
|
||||
}
|
||||
|
||||
//使用端点直线,检查点到直线的距离,大于门限的分割
|
||||
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);
|
||||
//归一化
|
||||
_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);
|
||||
}
|
||||
|
||||
//检查正确的端点,检查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));
|
||||
//构建等腰三角形,重新寻找点到底边的距离最高点
|
||||
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, 在XY平面生成拟合点
|
||||
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);
|
||||
//计算轮毂上顶点
|
||||
SVzNL3DPoint fitPt;
|
||||
fitPt.x = -b / (2 * a);
|
||||
fitPt.y = (4 * a * c - b * b) / (4 * a);
|
||||
//在轮廓点中寻找最近的点
|
||||
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;
|
||||
}
|
||||
|
||||
//轮眉高度测量
|
||||
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;
|
||||
//滤波,滤除异常点
|
||||
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], linePtNum, filterParam);
|
||||
}
|
||||
|
||||
//生成水平扫描
|
||||
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; //将原始数据的序列清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特征提取
|
||||
for (int line = 0; line < linePtNum; line++)
|
||||
{
|
||||
if (line == 974)
|
||||
int kkk = 1;
|
||||
std::vector<SVzNL3DPosition>& lineData = hLines_raw[line];
|
||||
//滤波,滤除异常点
|
||||
int ptNum = (int)lineData.size();
|
||||
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], ptNum, filterParam);
|
||||
}
|
||||
|
||||
//聚类,聚类出前盖板和轮胎
|
||||
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);
|
||||
}
|
||||
//生成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;
|
||||
}
|
||||
}
|
||||
}
|
||||
//聚类
|
||||
//采用迭代思想,回归思路进行高效聚类
|
||||
std::vector<std::vector< SVzNL2DPoint>> clusters; //只记录位置
|
||||
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)) //非特征或已经处理
|
||||
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_pointClustering2D(
|
||||
featureInfoMask,//int,记录特征标记和clusterID,附加一个flag
|
||||
feature3DInfo,//double,记录坐标信息
|
||||
clusterCheckWin, //搜索窗口
|
||||
growParam,//聚类条件
|
||||
clusterID, //当前Cluster的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++;
|
||||
}
|
||||
}
|
||||
//聚类结果分析
|
||||
//取最大的两个聚类。上面的聚类是前盖板,下面的是车轮
|
||||
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;
|
||||
}
|
||||
|
||||
//寻找轮眉点
|
||||
//(1)快速寻找下端点(2)取中间区域,精确确定端点(3)抛物线拟合(4)计算轮眉点(最高点)
|
||||
std::vector<SVzNL2DPoint> arcEndings;
|
||||
_getArcEndings(scanLines, 2, arcEndings); //轮眉的ID是2
|
||||
if (arcEndings.size() == 0)
|
||||
{
|
||||
*errCode = SX_ERR_INVALID_ARC;
|
||||
return result;
|
||||
}
|
||||
int arcMidPos = _getArcEndingsCenterPos(scanLines, arcEndings);
|
||||
//取两侧固定长度(100mm内的点,进行精确边界提取,拟合)
|
||||
double chkWin = 100.0;
|
||||
std::vector< SVzNL2DPoint> arcFittingPos;
|
||||
_extractArcFittingPts(
|
||||
scanLines,
|
||||
arcEndings,
|
||||
chkWin,
|
||||
arcMidPos,
|
||||
arcFittingPos);
|
||||
//在XY平面生成拟合点
|
||||
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 };
|
||||
|
||||
//提取轮毂特征:V型槽。连长6mm,角度最大的V型槽
|
||||
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, //车轮的ID为1
|
||||
wheelCornerPara, //scale通常取bagH的1/4
|
||||
cornerFeatures);
|
||||
//取第一个为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;
|
||||
//将数据重新投射回原来的坐标系,以保持手眼标定结果正确
|
||||
for (int i = 0; i < lineNum; i++)
|
||||
lineDataRT_vector(scanLines[i], groundCalibPara.invRMatrix, -1);
|
||||
//将检测结果重新投射回原来的坐标系
|
||||
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;
|
||||
}
|
||||
43
sourceCode/wheelArchHeigthMeasure_Export.h
Normal file
43
sourceCode/wheelArchHeigthMeasure_Export.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "SG_algo_Export.h"
|
||||
#include <vector>
|
||||
|
||||
#define _OUTPUT_DEBUG_DATA 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SVzNL3DPoint wheelArchPos;
|
||||
SVzNL3DPoint wheelUpPos;
|
||||
SVzNL3DPoint wheelDownPos;
|
||||
SVzNL3DPoint arcLine[2];
|
||||
SVzNL3DPoint upLine[2];
|
||||
SVzNL3DPoint downLine[2];
|
||||
SVzNL3DPoint centerLine[2];
|
||||
double archToCenterHeigth;
|
||||
}WD_wheelArchInfo;
|
||||
|
||||
//读版本号
|
||||
SG_APISHARED_EXPORT const char* wd_wheelArchHeigthMeasureVersion(void);
|
||||
|
||||
//相机水平安装计算地面调平参数。。
|
||||
//相机Z轴基本平行地面时,需要以地面为参照,将相机调水平
|
||||
//旋转矩阵为调平参数,即将平面法向调整为垂直向量的参数
|
||||
SG_APISHARED_EXPORT SSG_planeCalibPara wd_horizonCamera_getGroundCalibPara(
|
||||
std::vector< std::vector<SVzNL3DPosition>>& scanLines);
|
||||
|
||||
//相机水平时姿态调平,并去除地面
|
||||
SG_APISHARED_EXPORT void wd_horizonCamera_lineDataR(
|
||||
std::vector< SVzNL3DPosition>& a_line,
|
||||
const double* camPoseR,
|
||||
double groundH);
|
||||
|
||||
//提取工件角点及定位长度信息
|
||||
SG_APISHARED_EXPORT 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);
|
||||
2839
wheelArchHeigthMeasure_test/wheelArchHeigthMeasure_test.cpp
Normal file
2839
wheelArchHeigthMeasure_test/wheelArchHeigthMeasure_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
157
wheelArchHeigthMeasure_test/wheelArchHeigthMeasure_test.vcxproj
Normal file
157
wheelArchHeigthMeasure_test/wheelArchHeigthMeasure_test.vcxproj
Normal file
@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{bbf5341e-8447-45e9-ada3-3e8a9b52f5ef}</ProjectGuid>
|
||||
<RootNamespace>wheelArchHeigthMeasuretest</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IncludePath>..\..\thirdParty\VzNLSDK\Inc;..\sourceCode;..\sourceCode\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IncludePath>..\..\thirdParty\VzNLSDK\Inc;..\sourceCode;..\sourceCode\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\thirdParty\opencv320\build\include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\..\thirdParty\opencv320\build\x64\vc14\lib;..\build\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencv_world320d.lib;wheelArchHeigthMeasure.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\thirdParty\opencv320\build\include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\..\thirdParty\opencv320\build\x64\vc14\lib;..\build\x64\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencv_world320.lib;wheelArchHeigthMeasure.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="wheelArchHeigthMeasure_test.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
174
wheelArchHeigthMeaure/wheelArchHeigthMeaure.vcxproj
Normal file
174
wheelArchHeigthMeaure/wheelArchHeigthMeaure.vcxproj
Normal file
@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\sourceCode\wheelArchHeigthMeasure.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\sourceCode\wheelArchHeigthMeasure_Export.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{cfe11556-106a-4216-bf62-fda980528f7a}</ProjectGuid>
|
||||
<RootNamespace>wheelArchHeigthMeaure</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>wheelArchHeigthMeasure</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IncludePath>..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IncludePath>..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;WHEELARCHHEIGTHMEAURE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;WHEELARCHHEIGTHMEAURE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;WHEELARCHHEIGTHMEAURE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>..\..\thirdParty\opencv320\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>..\..\thirdParty\opencv320\build\x64\vc14\lib;..\build\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<PerUserRedirection>true</PerUserRedirection>
|
||||
<AdditionalDependencies>opencv_world320d.lib;baseAlgorithm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;WHEELARCHHEIGTHMEAURE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>..\..\thirdParty\opencv320\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>..\..\thirdParty\opencv320\build\x64\vc14\lib;..\build\x64\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencv_world320.lib;baseAlgorithm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user