feat:更新了算法,增加了边距系数

This commit is contained in:
YangSn 2026-08-28 09:27:51 +08:00
parent 77ec219b5d
commit ed91554bdb
28 changed files with 116 additions and 45 deletions

View File

@ -81,6 +81,7 @@ struct VrRotorCoreParam
double radius = 45.0;
double height = 20.0;
double layerRatio = 0.5; // 分层系数
double distToSideRatio = 1.1; // 边距系数
double groundRemoveOffset = 200.0; // 地面去除Z偏置
};

View File

@ -171,6 +171,8 @@ int CVrConfig::LoadConfig(const std::string& filePath, ConfigResult& configResul
rotorParam.height = rotorCoreParamElement->DoubleAttribute("height");
if (rotorCoreParamElement->Attribute("layerRatio"))
rotorParam.layerRatio = rotorCoreParamElement->DoubleAttribute("layerRatio");
if (rotorCoreParamElement->Attribute("distToSideRatio"))
rotorParam.distToSideRatio = rotorCoreParamElement->DoubleAttribute("distToSideRatio");
if (rotorCoreParamElement->Attribute("groundRemoveOffset"))
rotorParam.groundRemoveOffset = rotorCoreParamElement->DoubleAttribute("groundRemoveOffset");
}
@ -436,6 +438,7 @@ bool CVrConfig::SaveConfig(const std::string& filePath, ConfigResult& configResu
rotorCoreParamElement->SetAttribute("radius", configResult.algorithmParams.rotorCoreParam.radius);
rotorCoreParamElement->SetAttribute("height", configResult.algorithmParams.rotorCoreParam.height);
rotorCoreParamElement->SetAttribute("layerRatio", configResult.algorithmParams.rotorCoreParam.layerRatio);
rotorCoreParamElement->SetAttribute("distToSideRatio", configResult.algorithmParams.rotorCoreParam.distToSideRatio);
rotorCoreParamElement->SetAttribute("groundRemoveOffset", configResult.algorithmParams.rotorCoreParam.groundRemoveOffset);
algoParamsElement->InsertEndChild(rotorCoreParamElement);

View File

@ -28,7 +28,7 @@
minRectVertex1_0="5000.0" minRectVertex1_1="-5000.0" minRectVertex1_2="0.0"
minRectVertex2_0="5000.0" minRectVertex2_1="5000.0" minRectVertex2_2="0.0"
minRectVertex3_0="-5000.0" minRectVertex3_1="5000.0" minRectVertex3_2="0.0"/>
<RotorCoreParam radius="45.0" height="20.0" layerRatio="0.5" groundRemoveOffset="200.0"/>
<RotorCoreParam radius="45.0" height="20.0" layerRatio="0.5" distToSideRatio="1.1" groundRemoveOffset="200.0"/>
<PlaneCalibParams>
<CameraCalibParam cameraIndex="1" cameraName="Camera1" isCalibrated="false" planeHeight="-1.0"
planeCalib_00="1.0" planeCalib_01="0.0" planeCalib_02="0.0"

View File

@ -524,6 +524,7 @@ int DetectPresenter::DetectStatorWorkpiecePosition(
groundCalibPara,
workpieceParam,
algorithmParams.rotorCoreParam.layerRatio,
algorithmParams.rotorCoreParam.distToSideRatio,
algorithmParams.rotorCoreParam.groundRemoveOffset,
workpiecePositions,
algorithmBinInfo,
@ -550,9 +551,34 @@ int DetectPresenter::DetectStatorWorkpiecePosition(
detectionResult.errorCode = algorithmResult;
return algorithmResult;
}
if (algorithmBinInfo.length > 0.0 && algorithmBinInfo.width > 0.0) {
detectionResult.binInfo = algorithmBinInfo;
detectionResult.hasBinInfo = true;
// Some versions of the rotor algorithm return the detected bin size and
// center but leave minRectVertex untouched. Projecting those four zero
// points produces a degenerate polygon, so complete the geometry before
// handing it to the presenter. Do not manufacture a bin when the
// algorithm returned no bin information at all.
const bool hasBinOutput = algorithmBinInfo.length > 0.0 || algorithmBinInfo.width > 0.0;
if (hasBinOutput) {
EnsureUsableBinInfo(algorithmBinInfo);
if (algorithmBinInfo.length > 0.0 && algorithmBinInfo.width > 0.0) {
detectionResult.binInfo = algorithmBinInfo;
detectionResult.hasBinInfo = true;
LOG_INFO("[Rotor] bin output: length=%.3f width=%.3f topZ=%.3f "
"center=(%.3f,%.3f,%.3f) "
"vertices=(%.3f,%.3f,%.3f),(%.3f,%.3f,%.3f),"
"(%.3f,%.3f,%.3f),(%.3f,%.3f,%.3f)\n",
algorithmBinInfo.length, algorithmBinInfo.width,
algorithmBinInfo.binTopZ,
algorithmBinInfo.center.x, algorithmBinInfo.center.y,
algorithmBinInfo.center.z,
algorithmBinInfo.minRectVertex[0].x, algorithmBinInfo.minRectVertex[0].y,
algorithmBinInfo.minRectVertex[0].z,
algorithmBinInfo.minRectVertex[1].x, algorithmBinInfo.minRectVertex[1].y,
algorithmBinInfo.minRectVertex[1].z,
algorithmBinInfo.minRectVertex[2].x, algorithmBinInfo.minRectVertex[2].y,
algorithmBinInfo.minRectVertex[2].z,
algorithmBinInfo.minRectVertex[3].x, algorithmBinInfo.minRectVertex[3].y,
algorithmBinInfo.minRectVertex[3].z);
}
}
if (workpiecePositions.empty()) {
detectionResult.errorCode = ERR_CODE(SX_ERR_ZERO_OBJECTS);

View File

@ -1327,19 +1327,32 @@ int StatorWorkpiecePositionPresenter::ProcessAlgoDetection(std::vector<std::pair
algorithmParams, debugParam, m_dataLoader,
currentClibMatrix.clibMatrix, eulerOrder, dirVectorInvert,
detectionResult);
if (nRet == SUCCESS && !modelInputImage.isNull()) {
const std::vector<int> displayIndices = Build2DDisplayIndicesFromResult(
detections, detectionResult.positions);
const int highlightedDetectionIndex = detectionResult.positions.empty()
? -1
: detectionResult.positions.front().sourceDetectionIndex;
detectionResult.image = Draw2DDetectionsOnImage(
modelInputImage, detections, modelInputOriginX, modelInputOriginY,
&displayIndices, highlightedDetectionIndex);
SaveDebug2DDataIfNeeded(
detectionCameraIndex, debugParam, QImage(), detectionResult.image,
detections, QStringLiteral("final"));
}
// Keep the 2D result image even when the subsequent 3D positioning step
// fails. DetectPresenter can still return valid bin geometry before a
// later 3D error (for example, no workpiece found), and that geometry is
// useful to diagnose the scan and must be visible in the UI.
if (!modelInputImage.isNull()) {
const std::vector<int> displayIndices = Build2DDisplayIndicesFromResult(
detections, detectionResult.positions);
const int highlightedDetectionIndex = detectionResult.positions.empty()
? -1 : detectionResult.positions.front().sourceDetectionIndex;
detectionResult.image = Draw2DDetectionsOnImage(
modelInputImage, detections, modelInputOriginX, modelInputOriginY,
&displayIndices, highlightedDetectionIndex);
if (detectionResult.hasBinInfo) {
DrawProjectedBin(detectionResult.image,
detectionCameraIndex,
detectionResult.binInfo.minRectVertex,
modelInputOriginX,
modelInputOriginY);
} else {
LOG_WARNING("[2D] skip bin drawing: hasBinInfo=0 cameraIndex=%d imageNull=%d\n",
detectionCameraIndex, detectionResult.image.isNull() ? 1 : 0);
}
SaveDebug2DDataIfNeeded(detectionCameraIndex, debugParam, QImage(), detectionResult.image,
detections, QStringLiteral("final"));
}
// 根据项目类型选择处理方式
if (GetStatusCallback<IYStatorWorkpiecePositionStatus>()) {
@ -1899,4 +1912,3 @@ void StatorWorkpiecePositionPresenter::floatToRegisters(float value, uint16_t& h
low = static_cast<uint16_t>(bits & 0xFFFF);
}
}

View File

@ -5,7 +5,7 @@
#define STATORWORKPIECEPOSITION_APP_NAME "转子钢芯定位"
#define STATORWORKPIECEPOSITION_APP_KEY "WorkpieceRotorApp"
#define STATORWORKPIECEPOSITION_VERSION_STRING "1.0.2"
#define STATORWORKPIECEPOSITION_BUILD_STRING "2"
#define STATORWORKPIECEPOSITION_BUILD_STRING "3"
#define STATORWORKPIECEPOSITION_FULL_VERSION_STRING "V" STATORWORKPIECEPOSITION_VERSION_STRING "_" STATORWORKPIECEPOSITION_BUILD_STRING
// 构建日期

View File

@ -1,4 +1,10 @@
# 1.0.2
## build_3
1. 更新了算法,增加了边距系数
## build_2
1. 更新算法, 增加了分层系数
## build_1
1. 更新算法,已经去掉了料框的检测,直接检测工件位置,输出了料框的位置

View File

@ -30,6 +30,7 @@ DialogAlgoarg::DialogAlgoarg(ConfigManager* configManager, QWidget *parent)
if (ui->lineEdit_rotorRadius) ui->lineEdit_rotorRadius->setValidator(new QDoubleValidator(0.0, 1e6, 6, ui->lineEdit_rotorRadius));
if (ui->lineEdit_rotorHeight) ui->lineEdit_rotorHeight->setValidator(new QDoubleValidator(0.0, 1e6, 6, ui->lineEdit_rotorHeight));
if (ui->lineEdit_layerRatio) ui->lineEdit_layerRatio->setValidator(new QDoubleValidator(0.0, 10.0, 6, ui->lineEdit_layerRatio));
if (ui->lineEdit_distToSideRatio) ui->lineEdit_distToSideRatio->setValidator(new QDoubleValidator(0.0, 10.0, 6, ui->lineEdit_distToSideRatio));
if (ui->lineEdit_groundRemoveOffset) ui->lineEdit_groundRemoveOffset->setValidator(new QDoubleValidator(-1e6, 1e6, 6, ui->lineEdit_groundRemoveOffset));
ui->tabWidget->setCurrentIndex(0);
@ -254,18 +255,19 @@ bool DialogAlgoarg::SaveBinDetectionParamsFromUI(VrBinParam& binParam)
void DialogAlgoarg::LoadRotorCoreParamsToUI(const VrRotorCoreParam& rotorParam)
{
if (!ui || !ui->lineEdit_rotorRadius || !ui->lineEdit_rotorHeight || !ui->lineEdit_layerRatio || !ui->lineEdit_groundRemoveOffset) {
if (!ui || !ui->lineEdit_rotorRadius || !ui->lineEdit_rotorHeight || !ui->lineEdit_layerRatio || !ui->lineEdit_distToSideRatio || !ui->lineEdit_groundRemoveOffset) {
return;
}
ui->lineEdit_rotorRadius->setText(QString::number(rotorParam.radius, 'f', 6));
ui->lineEdit_rotorHeight->setText(QString::number(rotorParam.height, 'f', 6));
ui->lineEdit_layerRatio->setText(QString::number(rotorParam.layerRatio, 'f', 6));
ui->lineEdit_distToSideRatio->setText(QString::number(rotorParam.distToSideRatio, 'f', 6));
ui->lineEdit_groundRemoveOffset->setText(QString::number(rotorParam.groundRemoveOffset, 'f', 6));
}
bool DialogAlgoarg::SaveRotorCoreParamsFromUI(VrRotorCoreParam& rotorParam)
{
if (!ui || !ui->lineEdit_rotorRadius || !ui->lineEdit_rotorHeight || !ui->lineEdit_layerRatio || !ui->lineEdit_groundRemoveOffset) {
if (!ui || !ui->lineEdit_rotorRadius || !ui->lineEdit_rotorHeight || !ui->lineEdit_layerRatio || !ui->lineEdit_distToSideRatio || !ui->lineEdit_groundRemoveOffset) {
return false;
}
@ -276,6 +278,8 @@ bool DialogAlgoarg::SaveRotorCoreParamsFromUI(VrRotorCoreParam& rotorParam)
if (!ok || rotorParam.height <= 0.0) return false;
rotorParam.layerRatio = ui->lineEdit_layerRatio->text().toDouble(&ok);
if (!ok || rotorParam.layerRatio <= 0.0) return false;
rotorParam.distToSideRatio = ui->lineEdit_distToSideRatio->text().toDouble(&ok);
if (!ok || rotorParam.distToSideRatio <= 0.0) return false;
rotorParam.groundRemoveOffset = ui->lineEdit_groundRemoveOffset->text().toDouble(&ok);
if (!ok) return false;
return true;

View File

@ -74,7 +74,7 @@ QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;
<x>20</x>
<y>20</y>
<width>651</width>
<height>181</height>
<height>251</height>
</rect>
</property>
<property name="font">
@ -134,7 +134,7 @@ QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;
</property>
</widget>
</item>
<item row="2" column="0">
<item row="4" column="0">
<widget class="QLabel" name="label_groundRemoveOffset">
<property name="font">
<font>
@ -146,7 +146,7 @@ QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;
</property>
</widget>
</item>
<item row="2" column="1">
<item row="4" column="1">
<widget class="QLineEdit" name="lineEdit_groundRemoveOffset">
<property name="font">
<font>
@ -155,17 +155,28 @@ QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;
</property>
</widget>
</item>
<item row="3" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_layerRatio">
<property name="font"><font><pointsize>16</pointsize></font></property>
<property name="text"><string>分层系数</string></property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<widget class="QLineEdit" name="lineEdit_layerRatio">
<property name="font"><font><pointsize>16</pointsize></font></property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_distToSideRatio">
<property name="font"><font><pointsize>16</pointsize></font></property>
<property name="text"><string>边距系数</string></property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_distToSideRatio">
<property name="font"><font><pointsize>16</pointsize></font></property>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@ -3,7 +3,7 @@
#define WELDSEAM_APP_NAME "焊缝定位"
#define WELDSEAM_VERSION_STRING "1.0.1"
#define WELDSEAM_BUILD_STRING "1"
#define WELDSEAM_BUILD_STRING "3"
#define WELDSEAM_FULL_VERSION_STRING "V" WELDSEAM_VERSION_STRING "_" WELDSEAM_BUILD_STRING
// 获取版本信息的便捷函数

View File

@ -1,4 +1,10 @@
# 1.0.1
## build_3
1. 结果二维图像增加缩放功能
## build_2
1. 修复相机停留调用C模式失败
## build_1
1. 更新算法版本,增加了焊缝类型

View File

@ -29,6 +29,7 @@ unix:!macx {
}
INCLUDEPATH += $$PWD/Presenter/Inc
INCLUDEPATH += $$PWD/../../../Utils/ImageView/Inc
INCLUDEPATH += $$PWD/../../../Utils/VrCommon/Inc
INCLUDEPATH += $$PWD/../../../Utils/VrUtils/Inc
@ -85,6 +86,7 @@ win32 {
}
win32:CONFIG(debug, debug|release) {
LIBS += -L../../../Utils/ImageView/debug -lImageView
LIBS += -L../../../Utils/VrUtils/debug -lVrUtils
LIBS += -L../../../AppUtils/UICommon/debug -lUICommon
LIBS += -L../../../AppUtils/AppCommon/debug -lAppCommon
@ -100,6 +102,7 @@ win32:CONFIG(debug, debug|release) {
LIBS += -L../../../Nets/debug -lVrTcpServer
}else:win32:CONFIG(release, debug|release){
LIBS += -L../../../Utils/ImageView/release -lImageView
LIBS += -L../../../Utils/VrUtils/release -lVrUtils
LIBS += -L../../../AppUtils/UICommon/release -lUICommon
LIBS += -L../../../AppUtils/AppCommon/release -lAppCommon
@ -114,6 +117,7 @@ win32:CONFIG(debug, debug|release) {
LIBS += -L../../../Nets/release -lVrModbus
LIBS += -L../../../Nets/release -lVrTcpServer
}else:unix:!macx {
LIBS += -L../../../Utils/ImageView -lImageView
LIBS += -L../WeldSeamConfig -lWeldSeamConfig
LIBS += -L../../../AppUtils/UICommon -lUICommon
LIBS += -L../../../AppUtils/AppCommon -lAppCommon

View File

@ -1,6 +1,5 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsScene>
#include <QStandardItemModel>
#include <QDebug>
#include <QBrush>
@ -83,10 +82,6 @@ MainWindow::MainWindow(QWidget *parent)
ui->label_work->setVisible(false);
// 初始化GraphicsScene
QGraphicsScene* scene = new QGraphicsScene(this);
ui->detect_image->setScene(scene);
QGraphicsScene* scene2 = new QGraphicsScene(this);
ui->detect_image_2->setScene(scene2);
// 初始化日志辅助类
m_logHelper = new DetectLogHelper(ui->detect_log, this);
@ -201,12 +196,7 @@ void MainWindow::displayImage(const QImage& image)
return;
}
QGraphicsScene* scene = ui->detect_image->scene();
scene->clear();
QPixmap pixmap = QPixmap::fromImage(image);
scene->addPixmap(pixmap);
ui->detect_image->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
ui->detect_image->setImage(image);
}
void MainWindow::displayImageInSecondView(const QImage& image)
@ -216,10 +206,7 @@ void MainWindow::displayImageInSecondView(const QImage& image)
return;
}
QGraphicsScene* scene = ui->detect_image_2->scene();
scene->clear();
scene->addPixmap(QPixmap::fromImage(image));
ui->detect_image_2->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
ui->detect_image_2->setImage(image);
}
// 添加扩展版本的检测结果函数

View File

@ -11,6 +11,7 @@
#include <QStandardItem>
#include <QStringListModel>
#include <QGraphicsView>
#include "ImageView.h"
#include <QMenu>
#include <QAction>
#include "AboutDialog.h"

View File

@ -20,7 +20,7 @@
<string notr="true">background-color:rgb(25, 26, 28)</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QGraphicsView" name="detect_image">
<widget class="ImageView" name="detect_image">
<property name="geometry">
<rect>
<x>20</x>
@ -33,7 +33,7 @@
<string notr="true">background-color: rgb(37, 38, 42);</string>
</property>
</widget>
<widget class="QGraphicsView" name="detect_image_2">
<widget class="ImageView" name="detect_image_2">
<property name="geometry">
<rect>
<x>970</x>
@ -367,5 +367,12 @@ background-color: rgba(255, 255, 255, 0);</string>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<customwidgets>
<customwidget>
<class>ImageView</class>
<extends>QGraphicsView</extends>
<header>ImageView.h</header>
</customwidget>
</customwidgets>
<connections/>
</ui>

View File

@ -63,7 +63,8 @@ SG_APISHARED_EXPORT void wd_HRM_RotorCorePositioning(
std::vector<WD_objArea2D>& objROIs,
const SSG_planeCalibPara groundCalibPara,
const SWD_Cylinder workpieceParam, //圆柱形工件的标称半径和高度
const double layerRatio, //分层系数,分层门限=分层系数*工作高度;当两个工作的高度差大于分层门限时,判断为在不同层
const double layerRatio, //分层系数,分层门限=分层系数*工件高度;当两个工件的高度差大于分层门限时,判断为在不同层
const double distToSideRatio, //边距系数,边距门限=边距系数*工件直径;当工件距边的距离大于边距门限时,判断为边上的工件
const double groundRemoveOffset, //料筐地面去除的Z偏置实际地面去除高度为 groundCalibPara.planeHeight - groundRemoveOffset
std::vector< WD_workpieceInfo>& workpiecePositions,
WD_HRM_BinInfo& binInfo, //输出Bin信息用于debug确认料筐信息检测正确

View File

@ -2340,7 +2340,8 @@ void HaiRuiMa_rotorCorePositioning_test(void)
workpieceParam.radius = 45.0;
workpieceParam.height = 20.0;
double layerRatio = 0.5; //分层系数,分层门限=分层系数*工作高度;当两个工作的高度差大于分层门限时,判断为在不同层
double layerRatio = 0.5; //分层系数,分层门限=分层系数*工件高度;当两个工件的高度差大于分层门限时,判断为在不同层
const double distToSideRatio = 1.1; //边距系数,边距门限=边距系数*工件直径;当工件距边的距离大于边距门限时,判断为边上的工件
double groundRemoveOffset = 200; //料筐地面去除的Z偏置实际地面去除高度为 groundCalibPara.planeHeight - groundRemoveOffset
long t1 = (long)GetTickCount64();//统计时间
@ -2353,6 +2354,7 @@ void HaiRuiMa_rotorCorePositioning_test(void)
groundCalibPara,
workpieceParam,
layerRatio,
distToSideRatio,
groundRemoveOffset,
workpiecePositions,
binInfo,