Compare commits

...

2 Commits

16 changed files with 30 additions and 115 deletions

View File

@ -51,15 +51,8 @@ int DetectPresenter::DetectHoles(
return ERR_CODE(DEV_DATA_INVALID); return ERR_CODE(DEV_DATA_INVALID);
} }
// 保存debug数据 // debug保存点云已由 BasePresenter::DetectTask() 统一处理,此处不再重复保存
// 调试模式下先保存原始激光线数据,便于后续离线复现问题。
std::string timeStamp = CVrDateUtils::GetNowTime(); std::string timeStamp = CVrDateUtils::GetNowTime();
if (debugParam.enableDebug && debugParam.savePointCloud) {
LOG_INFO("[Algo Thread] Debug mode is enabled, saving point cloud data\n");
std::string fileName = debugParam.debugOutputPath + "/Laserline_" + std::to_string(cameraIndex) + "_" + timeStamp + ".txt";
dataLoader.SaveLaserScanData(fileName, laserLines, laserLines.size(), 0.0, 0, 0);
}
int nRet = SUCCESS; int nRet = SUCCESS;

View File

@ -3,11 +3,7 @@
#include "AlgoParamConverter.h" #include "AlgoParamConverter.h"
#include "IHandEyeCalib.h" #include "IHandEyeCalib.h"
#include <fstream> #include <fstream>
#define _USE_MATH_DEFINES
#include <cmath>
#include <memory> #include <memory>
#include <QPainter>
#include <QPen>
#include <QColor> #include <QColor>
namespace namespace
@ -68,17 +64,8 @@ int DetectPresenter::DetectRod(
cameraCalibParam = &cameraCalibParamValue; cameraCalibParam = &cameraCalibParamValue;
} }
// 保存debug数据 // debug保存点云已由 BasePresenter::DetectTask() 统一处理,此处不再重复保存
std::string timeStamp = CVrDateUtils::GetNowTime(); std::string timeStamp = CVrDateUtils::GetNowTime();
if(debugParam.enableDebug && debugParam.savePointCloud){
LOG_INFO("[Algo Thread] Debug mode is enabled, saving point cloud data\n");
// 获取当前时间戳格式为YYYYMMDDHHMMSS
std::string fileName = debugParam.debugOutputPath + "/Laserline_" + std::to_string(cameraIndex) + "_" + timeStamp + ".txt";
// 直接使用统一格式保存数据
dataLoader.SaveLaserScanData(fileName, laserLines, laserLines.size(), 0.0, 0, 0);
}
int nRet = SUCCESS; int nRet = SUCCESS;
@ -136,96 +123,32 @@ int DetectPresenter::DetectRod(
const HECCalibResult calibResult = HECCalibResult::fromHomogeneousArray(clibMatrix); const HECCalibResult calibResult = HECCalibResult::fromHomogeneousArray(clibMatrix);
const HECEulerOrder hecEulerOrder = ToHandEyeEulerOrder(eulerOrder); const HECEulerOrder hecEulerOrder = ToHandEyeEulerOrder(eulerOrder);
// 构建检测结果:生成点云图像 // 使用 PointCloudCanvas 生成点云图像(灰色底图 + 棒材中心/方向线标记)
// 1. 获取所有棒材的中心点用于可视化 {
std::vector<std::vector<SVzNL3DPoint>> objOps; PointCloudCanvas canvas = PointCloudCanvas::Create(xyzData);
std::vector<SVzNL3DPoint> rodCenters;
for (const auto& rod : rodInfo) { for (size_t i = 0; i < rodInfo.size(); i++) {
SVzNL3DPoint pt; const auto& rod = rodInfo[i];
pt.x = rod.center.x;
pt.y = rod.center.y;
pt.z = rod.center.z;
rodCenters.push_back(pt);
}
if (!rodCenters.empty()) {
objOps.push_back(rodCenters);
}
// 从点云数据生成投影图像10cm边界同时获取点云原始范围 // 绘制棒材中心点(红色)
double margin = 100.0; // 10cm = 100mm canvas.drawPoint(rod.center.x, rod.center.y, QColor(255, 0, 0), 6);
double xMin, xMax, yMin, yMax;
detectionResult.image = PointCloudImageUtils::GeneratePointCloudRetPointImage(xyzData, objOps, margin, &xMin, &xMax, &yMin, &yMax);
// 在图像上绘制棒材的轴向方向线
if (!detectionResult.image.isNull() && !rodInfo.empty()) {
QPainter painter(&detectionResult.image);
painter.setRenderHint(QPainter::Antialiasing);
// 扩展边界与GeneratePointCloudRetPointImage相同
xMin -= margin;
xMax += margin;
yMin -= margin;
yMax += margin;
// 使用与GeneratePointCloudRetPointImage相同的参数
int imgRows = detectionResult.image.height();
int imgCols = detectionResult.image.width();
int x_skip = 50;
int y_skip = 50;
// 计算投影比例与PointCloudImageUtils相同的方式
double y_rows = (double)(imgRows - y_skip * 2);
double x_cols = (double)(imgCols - x_skip * 2);
double x_scale = (xMax - xMin) / x_cols;
double y_scale = (yMax - yMin) / y_rows;
// 使用统一的比例尺
double scale = std::max(x_scale, y_scale);
x_scale = scale;
y_scale = scale;
// 计算点云在图像中居中的偏移量与PointCloudImageUtils一致
double cloudWidth = (xMax - xMin) / scale;
double cloudHeight = (yMax - yMin) / scale;
int x_offset = x_skip + (int)((x_cols - cloudWidth) / 2);
int y_offset = y_skip + (int)((y_rows - cloudHeight) / 2);
// 转换3D坐标到图像坐标的lambda函数使用居中偏移
auto toImageCoord = [&](const SVzNL3DPoint& pt) -> QPointF {
int px = (int)((pt.x - xMin) / x_scale + x_offset);
int py = (int)((pt.y - yMin) / y_scale + y_offset);
return QPointF(px, py);
};
// 绘制棒材的轴向方向线
for (const auto& rod : rodInfo) {
// 绘制轴向方向线(红色) // 绘制轴向方向线(红色)
double len = 60; double len = 60;
QPen axisPen(QColor(255, 0, 0), 2); double ax0 = rod.center.x - len * rod.axialDir.x;
painter.setPen(axisPen); double ay0 = rod.center.y - len * rod.axialDir.y;
double ax1 = rod.center.x + len * rod.axialDir.x;
SVzNL3DPoint pt0 = { rod.center.x - len * rod.axialDir.x, double ay1 = rod.center.y + len * rod.axialDir.y;
rod.center.y - len * rod.axialDir.y, canvas.drawLine(ax0, ay0, ax1, ay1, QColor(255, 0, 0), 2);
rod.center.z - len * rod.axialDir.z };
SVzNL3DPoint pt1 = { rod.center.x + len * rod.axialDir.x,
rod.center.y + len * rod.axialDir.y,
rod.center.z + len * rod.axialDir.z };
QPointF imgPt0 = toImageCoord(pt0);
QPointF imgPt1 = toImageCoord(pt1);
painter.drawLine(imgPt0, imgPt1);
// 绘制起点到终点线段(绿色) // 绘制起点到终点线段(绿色)
QPen segPen(QColor(0, 255, 0), 2); canvas.drawLine(rod.startPt.x, rod.startPt.y, rod.endPt.x, rod.endPt.y, QColor(0, 255, 0), 2);
painter.setPen(segPen);
SVzNL3DPoint startPt = { rod.startPt.x, rod.startPt.y, rod.startPt.z }; // 中心点白色编号
SVzNL3DPoint endPt = { rod.endPt.x, rod.endPt.y, rod.endPt.z }; canvas.drawText(rod.center.x, rod.center.y, QString("%1").arg(i + 1), Qt::white, 14);
QPointF imgStart = toImageCoord(startPt);
QPointF imgEnd = toImageCoord(endPt);
painter.drawLine(imgStart, imgEnd);
} }
detectionResult.image = canvas.image();
} }
// 转换检测结果为UI显示格式使用机械臂坐标系数据 // 转换检测结果为UI显示格式使用机械臂坐标系数据

View File

@ -5,7 +5,7 @@
// 应用名称 // 应用名称
#define RODANDBARPOSITION_APP_NAME "棒材定位" #define RODANDBARPOSITION_APP_NAME "棒材定位"
#define RODANDBARPOSITION_VERSION_STRING "1.0.2" #define RODANDBARPOSITION_VERSION_STRING "1.1.0"
#define RODANDBARPOSITION_BUILD_STRING "1" #define RODANDBARPOSITION_BUILD_STRING "1"
#define RODANDBARPOSITION_FULL_VERSION_STRING "V" RODANDBARPOSITION_VERSION_STRING "_" RODANDBARPOSITION_BUILD_STRING #define RODANDBARPOSITION_FULL_VERSION_STRING "V" RODANDBARPOSITION_VERSION_STRING "_" RODANDBARPOSITION_BUILD_STRING

View File

@ -1,3 +1,7 @@
# 1.1.0 2026-04-13
## build_1
1. 更新内存泄露问题
# 1.0.1 2026-03-27 # 1.0.1 2026-03-27
## build_1 ## build_1
1. 修复协议,增加读取下一个目标的 1. 修复协议,增加读取下一个目标的

View File

@ -3,7 +3,7 @@
#define WHEELMEASURE_APP_NAME "轮眉高度测量" #define WHEELMEASURE_APP_NAME "轮眉高度测量"
#define WHEELMEASURE_VERSION_STRING "1.1.1" #define WHEELMEASURE_VERSION_STRING "1.1.2"
#define WHEELMEASURE_BUILD_STRING "1" #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.1.2
## build_1 2026-04-09
1. 更新算法1.3.4
# 1.1.1 # 1.1.1
## build_1 2026-04-09 ## build_1 2026-04-09
1. 更新算法1.3.3 1. 更新算法1.3.3

View File

@ -45,17 +45,8 @@ int DetectPresenter::DetectWorkpieceHole(
cameraCalibParam = &cameraCalibParamValue; cameraCalibParam = &cameraCalibParamValue;
} }
// 保存debug数据 // debug保存点云已由 BasePresenter::DetectTask() 统一处理,此处不再重复保存
std::string timeStamp = CVrDateUtils::GetNowTime(); std::string timeStamp = CVrDateUtils::GetNowTime();
if(debugParam.enableDebug && debugParam.savePointCloud){
LOG_INFO("[Algo Thread] Debug mode is enabled, saving point cloud data\n");
// 获取当前时间戳格式为YYYYMMDDHHMMSS
std::string fileName = debugParam.debugOutputPath + "/Laserline_" + std::to_string(cameraIndex) + "_" + timeStamp + ".txt";
// 直接使用统一格式保存数据
dataLoader.SaveLaserScanData(fileName, laserLines, laserLines.size(), 0.0, 0, 0);
}
int nRet = SUCCESS; int nRet = SUCCESS;