178 lines
7.7 KiB
C++
178 lines
7.7 KiB
C++
#include "DetectPresenter.h"
|
|
#include "WD_particleSizeMeasure_Export.h"
|
|
#include <fstream>
|
|
|
|
DetectPresenter::DetectPresenter(/* args */)
|
|
{
|
|
LOG_DEBUG("DetectPresenter Init algo ver: %s\n", wd_particleSegVersion());
|
|
}
|
|
|
|
DetectPresenter::~DetectPresenter()
|
|
{
|
|
}
|
|
|
|
int DetectPresenter::DetectWorkpiece(
|
|
int cameraIndex,
|
|
std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& laserLines,
|
|
const VrAlgorithmParams& algorithmParams,
|
|
const VrDebugParam& debugParam,
|
|
LaserDataLoader& dataLoader,
|
|
const double clibMatrix[16],
|
|
DetectionResult& detectionResult)
|
|
{
|
|
if (laserLines.empty()) {
|
|
LOG_WARNING("No laser lines data available\n");
|
|
return ERR_CODE(DEV_DATA_INVALID);
|
|
}
|
|
|
|
// 获取当前相机的校准参数
|
|
VrCameraPlaneCalibParam cameraCalibParamValue;
|
|
const VrCameraPlaneCalibParam* cameraCalibParam = nullptr;
|
|
if (algorithmParams.planeCalibParam.GetCameraCalibParam(cameraIndex, cameraCalibParamValue)) {
|
|
cameraCalibParam = &cameraCalibParamValue;
|
|
}
|
|
|
|
// 保存debug数据
|
|
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;
|
|
|
|
// 转换为算法需要的XYZ格式
|
|
std::vector<std::vector<SVzNL3DPosition>> xyzData;
|
|
int convertResult = dataLoader.ConvertToSVzNL3DPosition(laserLines, xyzData);
|
|
if (convertResult != SUCCESS || xyzData.empty()) {
|
|
LOG_WARNING("Failed to convert data to XYZ format or no XYZ data available\n");
|
|
return ERR_CODE(DEV_DATA_INVALID);
|
|
}
|
|
|
|
// 准备粒度检测参数
|
|
SWD_paricleSizeParam particleSizeParam;
|
|
// 直接赋值,因为现在结构匹配
|
|
particleSizeParam.minSize.length = algorithmParams.particleSizeParam.minSize.length;
|
|
particleSizeParam.minSize.width = algorithmParams.particleSizeParam.minSize.width;
|
|
particleSizeParam.minSize.height = algorithmParams.particleSizeParam.minSize.height;
|
|
particleSizeParam.alarmSize.length = algorithmParams.particleSizeParam.alarmSize.length;
|
|
particleSizeParam.alarmSize.width = algorithmParams.particleSizeParam.alarmSize.width;
|
|
particleSizeParam.alarmSize.height = algorithmParams.particleSizeParam.alarmSize.height;
|
|
|
|
// 准备算法参数
|
|
SWD_PSM_algoParam algoParam;
|
|
algoParam.cornerParam.minEndingGap = algorithmParams.cornerParam.minEndingGap;
|
|
algoParam.cornerParam.minEndingGap_z = algorithmParams.cornerParam.minEndingGap_z;
|
|
algoParam.cornerParam.scale = algorithmParams.cornerParam.scale;
|
|
algoParam.cornerParam.cornerTh = algorithmParams.cornerParam.cornerTh;
|
|
algoParam.cornerParam.jumpCornerTh_1 = algorithmParams.cornerParam.jumpCornerTh_1;
|
|
algoParam.cornerParam.jumpCornerTh_2 = algorithmParams.cornerParam.jumpCornerTh_2;
|
|
|
|
algoParam.growParam.yDeviation_max = algorithmParams.growParam.yDeviation_max;
|
|
algoParam.growParam.zDeviation_max = algorithmParams.growParam.zDeviation_max;
|
|
algoParam.growParam.maxLineSkipNum = algorithmParams.growParam.maxLineSkipNum;
|
|
algoParam.growParam.maxSkipDistance = algorithmParams.growParam.maxSkipDistance;
|
|
algoParam.growParam.minLTypeTreeLen = algorithmParams.growParam.minLTypeTreeLen;
|
|
algoParam.growParam.minVTypeTreeLen = algorithmParams.growParam.minVTypeTreeLen;
|
|
|
|
algoParam.filterParam.continuityTh = algorithmParams.filterParam.continuityTh;
|
|
algoParam.filterParam.outlierTh = algorithmParams.filterParam.outlierTh;
|
|
|
|
// 准备平面校准参数
|
|
SSG_planeCalibPara groundCalibPara;
|
|
if(cameraCalibParam){
|
|
memcpy(groundCalibPara.planeCalib, cameraCalibParam->planeCalib, sizeof(double) * 9);
|
|
memcpy(groundCalibPara.invRMatrix, cameraCalibParam->invRMatrix, sizeof(double) * 9);
|
|
groundCalibPara.planeHeight = cameraCalibParam->planeHeight;
|
|
} else {
|
|
// 使用默认单位矩阵
|
|
double identity[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
|
|
memcpy(groundCalibPara.planeCalib, identity, sizeof(double) * 9);
|
|
memcpy(groundCalibPara.invRMatrix, identity, sizeof(double) * 9);
|
|
groundCalibPara.planeHeight = -1.0;
|
|
}
|
|
|
|
if(debugParam.enableDebug && debugParam.printDetailLog)
|
|
{
|
|
LOG_INFO("[Algo Thread] minSize l:%.1f, w:%.1f, h:%.1f\n", particleSizeParam.minSize.length, particleSizeParam.minSize.width, particleSizeParam.minSize.height);
|
|
LOG_INFO(" alarmSize l:%.1f, w:%.1f, h:%.1f\n",particleSizeParam.alarmSize.length, particleSizeParam.alarmSize.width, particleSizeParam.alarmSize.height);
|
|
LOG_INFO("[Algo Thread] Corner: cornerTh=%.1f, scale=%.1f\n", algoParam.cornerParam.cornerTh, algoParam.cornerParam.scale);
|
|
LOG_INFO("[Algo Thread] Filter: continuityTh=%.1f, outlierTh=%.1f\n", algoParam.filterParam.continuityTh, algoParam.filterParam.outlierTh);
|
|
LOG_INFO("Plane height: %.3f\n", groundCalibPara.planeHeight);
|
|
}
|
|
|
|
// 数据预处理:调平和去除地面
|
|
if(cameraCalibParam){
|
|
LOG_DEBUG("Processing data with plane calibration\n");
|
|
for(size_t i = 0; i < xyzData.size(); i++){
|
|
wd_lineDataR(xyzData[i], cameraCalibParam->planeCalib, groundCalibPara.planeHeight);
|
|
}
|
|
}
|
|
|
|
int errCode = 0;
|
|
CVrTimeUtils oTimeUtils;
|
|
std::vector<SWD_ParticlePosInfo> particles;
|
|
|
|
LOG_DEBUG("before wd_particleSizeMeasure \n");
|
|
|
|
// 调用粒度检测算法
|
|
wd_particleSizeMeasure(
|
|
xyzData,
|
|
particleSizeParam,
|
|
groundCalibPara,
|
|
algoParam,
|
|
particles,
|
|
&errCode
|
|
);
|
|
|
|
LOG_DEBUG("after wd_particleSizeMeasure \n");
|
|
|
|
LOG_INFO("wd_particleSizeMeasure: detected %d particles, err=%d runtime=%.3fms\n", (int)particles.size(), errCode, oTimeUtils.GetElapsedTimeInMilliSec());
|
|
|
|
ERR_CODE_RETURN(errCode);
|
|
|
|
// 保存检测到的颗粒信息到结果
|
|
detectionResult.positions.clear();
|
|
for(size_t i = 0; i < particles.size(); i++) {
|
|
ParticleSizePosition pos;
|
|
|
|
pos.index = i + 1;
|
|
pos.length = particles[i].size.length;
|
|
pos.width = particles[i].size.width;
|
|
pos.height = particles[i].size.height;
|
|
|
|
// 保存颗粒尺寸
|
|
pos.width = particles[i].size.width;
|
|
pos.height = particles[i].size.height;
|
|
|
|
// 检查是否超过告警阈值
|
|
pos.isAlarm = (pos.length > particleSizeParam.alarmSize.length || pos.width > particleSizeParam.alarmSize.width || pos.height > particleSizeParam.alarmSize.height);
|
|
|
|
detectionResult.positions.push_back(pos);
|
|
|
|
if(debugParam.enableDebug && debugParam.printDetailLog) {
|
|
LOG_INFO("Particle %d: size=(%.2f, %.2f, %.2f), alarm=%d\n", pos.index, pos.length, pos.width, pos.height, pos.isAlarm);
|
|
}
|
|
}
|
|
|
|
// 生成可视化图像
|
|
if (!xyzData.empty()) {
|
|
// 转换颗粒信息格式
|
|
std::vector<SimpleParticleInfo> simpleParticles;
|
|
for (const auto& p : particles) {
|
|
SimpleParticleInfo sp;
|
|
for (int i = 0; i < 8; i++) {
|
|
sp.vertix[i] = p.vertix[i];
|
|
}
|
|
sp.size.width = p.size.width;
|
|
sp.size.height = p.size.height;
|
|
simpleParticles.push_back(sp);
|
|
}
|
|
|
|
detectionResult.image = PointCloudImageUtils::GeneratePointCloudImageWithParticles(xyzData, simpleParticles, cameraIndex);
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|