轮毂检测算法更新

This commit is contained in:
yiyi 2026-04-02 00:38:50 +08:00
parent 839862ea26
commit 512c72b895
23 changed files with 124 additions and 36 deletions

View File

@ -164,28 +164,17 @@ int DetectPresenter::DetectRod(
objOps.push_back(rodCenters); objOps.push_back(rodCenters);
} }
// 从点云数据生成投影图像10cm边界 // 从点云数据生成投影图像10cm边界同时获取点云原始范围
detectionResult.image = PointCloudImageUtils::GeneratePointCloudRetPointImage(xyzData, objOps, 100.0); double margin = 100.0; // 10cm = 100mm
double xMin, xMax, yMin, yMax;
detectionResult.image = PointCloudImageUtils::GeneratePointCloudRetPointImage(xyzData, objOps, margin, &xMin, &xMax, &yMin, &yMax);
// 在图像上绘制棒材的轴向方向线 // 在图像上绘制棒材的轴向方向线
if (!detectionResult.image.isNull() && !rodInfo.empty()) { if (!detectionResult.image.isNull() && !rodInfo.empty()) {
QPainter painter(&detectionResult.image); QPainter painter(&detectionResult.image);
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
// 计算点云范围与PointCloudImageUtils相同的方式
double xMin = 1e10, xMax = -1e10, yMin = 1e10, yMax = -1e10;
for (const auto& line : xyzData) {
for (const auto& pt : line) {
if (pt.pt3D.z < 1e-4) continue;
xMin = std::min(xMin, (double)pt.pt3D.x);
xMax = std::max(xMax, (double)pt.pt3D.x);
yMin = std::min(yMin, (double)pt.pt3D.y);
yMax = std::max(yMax, (double)pt.pt3D.y);
}
}
// 扩展边界与GeneratePointCloudRetPointImage相同 // 扩展边界与GeneratePointCloudRetPointImage相同
double margin = 100.0; // 10cm = 100mm
xMin -= margin; xMin -= margin;
xMax += margin; xMax += margin;
yMin -= margin; yMin -= margin;

View File

@ -121,6 +121,11 @@ public:
*/ */
QStringList getCameraNames() const; QStringList getCameraNames() const;
/**
* @brief
*/
QString GetAlgoVersion() const;
/** /**
* @brief * @brief
*/ */

View File

@ -256,6 +256,12 @@ QStringList WheelMeasurePresenter::getCameraNames() const
return names; return names;
} }
QString WheelMeasurePresenter::GetAlgoVersion() const
{
const char* version = wd_wheelArchHeigthMeasureVersion();
return version ? QString::fromUtf8(version) : QString();
}
void WheelMeasurePresenter::ResetDetect(int cameraIndex) void WheelMeasurePresenter::ResetDetect(int cameraIndex)
{ {
StopDetection(); StopDetection();

View File

@ -2,8 +2,9 @@
#define VERSION_H #define VERSION_H
#define WHEELMEASURE_VERSION_STRING "1.0.1" #define WHEELMEASURE_APP_NAME "轮眉高度测量"
#define WHEELMEASURE_BUILD_STRING "6" #define WHEELMEASURE_VERSION_STRING "1.0.2"
#define WHEELMEASURE_BUILD_STRING "1"
#define WHEELMEASURE_FULL_VERSION_STRING "V" WHEELMEASURE_VERSION_STRING "_" WHEELMEASURE_BUILD_STRING #define WHEELMEASURE_FULL_VERSION_STRING "V" WHEELMEASURE_VERSION_STRING "_" WHEELMEASURE_BUILD_STRING
// 获取版本信息的便捷函数 // 获取版本信息的便捷函数

View File

@ -1,3 +1,7 @@
# 1.0.2
## build_1 2026-04-01
1. 更新算法 1.3.2
# 1.0.1 # 1.0.1
## build_5 2026-01-17 ## build_5 2026-01-17
1. 更新算法 1.3.0 1. 更新算法 1.3.0

View File

@ -7,6 +7,7 @@
#include "dialogcameralevel.h" #include "dialogcameralevel.h"
#include "dialogalgoarg.h" #include "dialogalgoarg.h"
#include "dialogcamera.h" #include "dialogcamera.h"
#include "AboutDialog.h"
#include <QImage> #include <QImage>
#include <QStringList> #include <QStringList>
@ -148,6 +149,18 @@ void MainWindow::resizeEvent(QResizeEvent* event)
QMainWindow::resizeEvent(event); QMainWindow::resizeEvent(event);
} }
bool MainWindow::eventFilter(QObject* watched, QEvent* event)
{
if (watched == m_versionLabel && event->type() == QEvent::MouseButtonPress) {
const QString algoVersion = m_presenter ? m_presenter->GetAlgoVersion() : QString();
AboutDialog dlg(WHEELMEASURE_APP_NAME, m_versionLabel->text(), algoVersion, this);
dlg.exec();
return true;
}
return QMainWindow::eventFilter(watched, event);
}
void MainWindow::on_btn_hide_clicked() void MainWindow::on_btn_hide_clicked()
{ {
this->showMinimized(); this->showMinimized();
@ -554,6 +567,8 @@ void MainWindow::setupVersionDisplay()
m_versionLabel->setText(versionText); m_versionLabel->setText(versionText);
m_versionLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); m_versionLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
m_versionLabel->setCursor(Qt::PointingHandCursor);
m_versionLabel->installEventFilter(this);
m_versionLabel->setStyleSheet("QLabel { color: rgb(239, 241, 245); font-size: 24px; margin-right: 10px; }"); m_versionLabel->setStyleSheet("QLabel { color: rgb(239, 241, 245); font-size: 24px; margin-right: 10px; }");

View File

@ -5,6 +5,7 @@
#include <QStringList> #include <QStringList>
#include <QSplitter> #include <QSplitter>
#include <QResizeEvent> #include <QResizeEvent>
#include <QEvent>
#include <QMessageBox> #include <QMessageBox>
#include <QPushButton> #include <QPushButton>
#include <QStringListModel> #include <QStringListModel>
@ -48,6 +49,7 @@ public:
protected: protected:
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
bool eventFilter(QObject* watched, QEvent* event) override;
private slots: private slots:
void on_btn_hide_clicked(); void on_btn_hide_clicked();

View File

@ -109,10 +109,10 @@ struct WheelOutlierFilterParam
*/ */
struct WheelTreeGrowParam struct WheelTreeGrowParam
{ {
double yDeviation_max = 5.0; // 生长时允许的最大Y偏差 double yDeviation_max = 10.0; // 生长时允许的最大Y偏差
double zDeviation_max = 2.0; // 生长时允许的最大Z偏差 double zDeviation_max = 10.0; // 生长时允许的最大Z偏差
int maxLineSkipNum = 10; // 生长时允许的最大跳线数 int maxLineSkipNum = 10; // 生长时允许的最大跳线数
double maxSkipDistance = 5.0; // 当maxLineSkipNum为-1时使用 double maxSkipDistance = 10.0; // 当maxLineSkipNum为-1时使用
double minLTypeTreeLen = 100.0; // 最少的L型节点数目 double minLTypeTreeLen = 100.0; // 最少的L型节点数目
double minVTypeTreeLen = 100.0; // 最少的V型节点数目 double minVTypeTreeLen = 100.0; // 最少的V型节点数目
}; };

View File

@ -39,6 +39,13 @@ typedef struct
SWD3DPoint point; SWD3DPoint point;
}SWDIndexing3DPoint; }SWDIndexing3DPoint;
typedef struct
{
int lineIdx;
int ptIdx;
SVzNL3DPoint point;
}SWDIndexingVzPoint;
typedef struct typedef struct
{ {
int start; int start;
@ -124,6 +131,16 @@ struct RGB {
int b; int b;
}; };
struct Plane {
double A, B, C, D; // Æ½Ãæ Ax+By+Cz+D=0
Plane() : A(0), B(0), C(0), D(0) {}
Plane(double a, double b, double c, double d) : A(a), B(b), C(c), D(d) {}
};
enum RobustType {
HUBER,
TUKEY
};
#define LINE_FEATURE_NUM 16 #define LINE_FEATURE_NUM 16
#define LINE_FEATURE_UNDEF 0 #define LINE_FEATURE_UNDEF 0
#define LINE_FEATURE_L_JUMP_H2L 1 #define LINE_FEATURE_L_JUMP_H2L 1
@ -257,6 +274,18 @@ typedef struct
double featureValue; double featureValue;
}SWD_segFeature; }SWD_segFeature;
typedef struct
{
int lineIdx;
int startPtIdx;
int endPtIdx;
int peakPtIdx;
SVzNL3DPoint startPt;
SVzNL3DPoint endPt;
SVzNL3DPoint peakPt;
double featureValue;
}SWD_rodArcFeature;
typedef struct typedef struct
{ {
double sameGapTh; double sameGapTh;
@ -330,6 +359,18 @@ typedef struct
int angleChkScalePos; //仅用于加速angleCheck的速度 int angleChkScalePos; //仅用于加速angleCheck的速度
}SSG_gapFeatureTree; }SSG_gapFeatureTree;
typedef struct
{
int treeState;
int treeType;
int sLineIdx;
int eLineIdx;
double tree_value;
SSG_ROIRectD roi;
std::vector< SWD_segFeature> treeNodes;
int angleChkScalePos; //½öÓÃÓÚ¼ÓËÙangleCheckµÄËÙ¶È
}SSG_segFeatureTree;
typedef struct typedef struct
{ {
int treeState; int treeState;
@ -352,6 +393,15 @@ typedef struct
std::vector< SWD_segFeature> treeNodes; std::vector< SWD_segFeature> treeNodes;
}SWD_segFeatureTree; }SWD_segFeatureTree;
typedef struct
{
int treeState;
int sLineIdx;
int eLineIdx;
double tree_value;
std::vector< SWD_rodArcFeature> treeNodes;
}SWD_rodArcFeatureTree;
typedef struct typedef struct
{ {
int vTreeFlag; int vTreeFlag;
@ -359,7 +409,9 @@ typedef struct
int treeType; int treeType;
int sLineIdx; int sLineIdx;
int eLineIdx; int eLineIdx;
int data;
SSG_ROIRectD roi; SSG_ROIRectD roi;
SVzNLRange ptIdxRange;
}SSG_treeInfo; }SSG_treeInfo;
typedef struct typedef struct
@ -549,6 +601,8 @@ typedef struct
typedef struct typedef struct
{ {
int pntIdx; int pntIdx;
int forwardPntIdx;
int backwardPntIdx;
int type; int type;
double forwardAngle; //前向角 double forwardAngle; //前向角
double backwardAngle; //后向角 double backwardAngle; //后向角
@ -557,6 +611,7 @@ typedef struct
double backwardDiffZ; double backwardDiffZ;
double pre_stepDist; double pre_stepDist;
double post_stepDist; double post_stepDist;
double curr_z;
double forward_z; double forward_z;
double backward_z; double backward_z;
}SSG_pntDirAngle; }SSG_pntDirAngle;

View File

@ -32,6 +32,10 @@
//汽车轮眉高度测量 //汽车轮眉高度测量
#define SX_ERR_INVALID_ARC -2301 #define SX_ERR_INVALID_ARC -2301
#define SX_ERR_INVALID_WHEEL_EDGE -2302
#define SX_ERR_NO_WHEEL_COMMON_EDGE -2303
#define SX_ERR_NO_WHEEL_ARC -2304
//糖袋子拆线 //糖袋子拆线
#define SX_ERR_NO_MARK -2401 #define SX_ERR_NO_MARK -2401

View File

@ -2637,9 +2637,9 @@ void _outputScanDataFile_removeZeros(char* fileName, SVzNL3DLaserLine * scanData
#define TEST_CONVERT_TO_GRID 0 #define TEST_CONVERT_TO_GRID 0
#define TEST_COMPUTE_WHEEL_ARCH 1 #define TEST_COMPUTE_WHEEL_ARCH 1
#define TEST_COMPUTE_CALIB_PARA 1 #define TEST_COMPUTE_CALIB_PARA 0
#define TEST_GROUP 1 #define TEST_GROUP 2
int main() int main()
{ {
#if TEST_CONVERT_TO_GRID #if TEST_CONVERT_TO_GRID
@ -2717,10 +2717,11 @@ int main()
#if TEST_COMPUTE_WHEEL_ARCH #if TEST_COMPUTE_WHEEL_ARCH
const char* dataPath[TEST_GROUP] = { const char* dataPath[TEST_GROUP] = {
"F:/ShangGu/项目/冠钦_轮眉高度测量/测试数据/现场数据/", //0 "F:/ShangGu/项目/冠钦_轮眉高度测量/测试数据/现场数据/", //0
"F:/ShangGu/项目/冠钦_轮眉高度测量/测试数据/部署现场数据/", //1
}; };
SVzNLRange fileIdx[TEST_GROUP] = { SVzNLRange fileIdx[TEST_GROUP] = {
{1,2}, {1,2}, {1,4}
}; };
SSG_planeCalibPara poseCalibPara; SSG_planeCalibPara poseCalibPara;
@ -2744,14 +2745,14 @@ int main()
char _scan_file[256]; char _scan_file[256];
int endGroup = TEST_GROUP - 1; int endGroup = TEST_GROUP - 1;
for (int grp = 0; grp <= endGroup; grp++) for (int grp = 1; grp <= endGroup; grp++)
{ {
char calibFile[250]; char calibFile[250];
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]); sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
poseCalibPara = _readCalibPara(calibFile); poseCalibPara = _readCalibPara(calibFile);
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++) for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{ {
//fidx = 193; //fidx = 4;
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx); sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanData; std::vector<std::vector< SVzNL3DPosition>> scanData;
vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanData); vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanData);
@ -2783,17 +2784,17 @@ int main()
SSG_treeGrowParam growParam; SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 10; growParam.maxLineSkipNum = 10;
growParam.yDeviation_max = 5.0; growParam.yDeviation_max = 10.0;
growParam.maxSkipDistance = 5.0; growParam.maxSkipDistance = 10.0;
growParam.zDeviation_max = 2.0;// growParam.zDeviation_max = 10.0;//
growParam.minLTypeTreeLen = 100; //mm growParam.minLTypeTreeLen = 100; //mm
growParam.minVTypeTreeLen = 100; //mm growParam.minVTypeTreeLen = 100; //mm
WD_wheelArchInfo wheelArcHeight; WD_wheelArchInfo wheelArcHeight;
memset(&wheelArcHeight, 0, sizeof(WD_wheelArchInfo)); memset(&wheelArcHeight, 0, sizeof(WD_wheelArchInfo));
bool wheePresense = wd_wheelPresenseDetection( scanData, wheelRoi3d); bool wheelPresense = wd_wheelPresenseDetection( scanData, wheelRoi3d);
if (true == wheePresense) if (true == wheelPresense)
{ {
int lineNum = (int)scanData.size(); int lineNum = (int)scanData.size();
for (int i = 0; i < lineNum; i++) for (int i = 0; i < lineNum; i++)
@ -2802,7 +2803,7 @@ int main()
int kkk = 1; int kkk = 1;
//行处理 //行处理
//调平,去除地面 //调平,去除地面
wd_horizonCamera_lineDataR(scanData[i], poseCalibPara.planeCalib, poseCalibPara.planeHeight - 5); wd_horizonCamera_lineDataR(scanData[i], poseCalibPara.planeCalib, -1); // poseCalibPara.planeHeight - 5);
} }
#if 0 //数据转存 #if 0 //数据转存
sprintf_s(_scan_file, "%sLaserLine%d_grid_RTadjust.txt", dataPath[grp], fidx); sprintf_s(_scan_file, "%sLaserLine%d_grid_RTadjust.txt", dataPath[grp], fidx);
@ -2819,7 +2820,7 @@ int main()
growParam, growParam,
poseCalibPara, poseCalibPara,
&errCode); &errCode);
}
long t2 = GetTickCount64(); long t2 = GetTickCount64();
@ -2831,6 +2832,12 @@ int main()
#endif #endif
printf("%s: height=%f, arcToGrund=%f, time=%d(ms)!\n", _scan_file, wheelArcHeight.archToCenterHeigth, wheelArcHeight.archToGroundHeigth, (int)(t2 - t1)); printf("%s: height=%f, arcToGrund=%f, time=%d(ms)!\n", _scan_file, wheelArcHeight.archToCenterHeigth, wheelArcHeight.archToGroundHeigth, (int)(t2 - t1));
} }
else
{
printf("%s: no Wheel!", _scan_file);
}
}
} }
#endif #endif
printf("all done!\n"); printf("all done!\n");