Utils/CloudUtils/Inc/PointCloudImageUtils.h

202 lines
8.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef POINTCLOUDIMAGEUTILS_H
#define POINTCLOUDIMAGEUTILS_H
#include <QImage>
#include <QColor>
#include <vector>
#include <utility> // for std::pair
#include "VZNL_Types.h"
// 简单的颗粒信息结构 - 避免依赖OpenCV
struct SimpleParticleInfo {
SVzNL3DPoint vertix[8]; // 8个顶点
struct {
double width;
double height;
} size;
};
// 通用检测目标结构体 - 替代算法SDK的 SSG_peakRgnInfo
struct DetectionTargetInfo {
struct {
double x;
double y;
double z_yaw; // 偏航角(度)
} centerPos;
struct {
double dWidth;
double dHeight;
} objSize;
int orienFlag = 0; // 朝向标记: 0=无, 1=正面, 2=反面
};
// 孔洞标记信息结构体 - 用于孔洞检测结果可视化
struct HoleMarkerInfo {
SVzNL3DPoint center; // 孔洞中心 (double x,y,z)
double radius; // 孔洞半径 (mm)
};
class PointCloudImageUtils
{
public:
// 点云转图像 - 使用通用检测目标结构体
static QImage GeneratePointCloudImage(SVzNL3DLaserLine* scanData,
int lineNum,
const std::vector<DetectionTargetInfo>& objOps);
static QImage GeneratePointCloudImage(SVzNLXYZRGBDLaserLine* scanData,
int lineNum,
const std::vector<DetectionTargetInfo>& objOps);
// 新的点云图像生成函数 - 基于X、Y范围创建图像
static QImage GeneratePointCloudImage(SVzNLXYZRGBDLaserLine* scanData,
int lineNum);
// LapWeld点云和检测结果转图像 - 基于scan lines格式
static QImage GeneratePointCloudImage(const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
const std::vector<std::vector<SVzNL3DPoint>>& weldResults,
int imageWidth = 800, int imageHeight = 600);
// Workpiece点云和角点检测结果转图像 - 将角点画成圆点
static QImage GeneratePointCloudRetPointImage(const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
const std::vector<std::vector<SVzNL3DPoint>>& cornerPoints,
double margin = 0.0,
double* outXMin = nullptr,
double* outXMax = nullptr,
double* outYMin = nullptr,
double* outYMax = nullptr);
// ParticleSize点云和颗粒检测结果转图像 - 生成带颗粒标记的点云图像 (直接返回QImage)
static QImage GeneratePointCloudImageWithParticles(
const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
const std::vector<SimpleParticleInfo>& particles,
int cameraIndex);
// WheelMeasure点云和轮眉检测结果转图像 - 生成带轮眉标记的点云图像
static QImage GenerateWheelArchImage(
const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
const SVzNL3DPoint& wheelArchPos,
const SVzNL3DPoint& wheelUpPos,
const SVzNL3DPoint& wheelDownPos,
double archToCenterHeight,
bool hasResult = true);
// 从检测数据缓存生成深度图像
static int GenerateDepthImage(
const std::vector<std::pair<EVzResultDataType, SVzLaserLineData>>& detectionDataCache,
QImage& outImage);
// 通道间距测量图像生成 - 根据算法标记的nPointIdx着色
// 参考 HC_chanelSpaceMeasure_test.cpp 的 _outputRGBDScan_RGBD 函数
// nPointIdx > 0: 使用预定义的8种颜色, 否则使用灰色
static QImage GenerateChannelSpaceImage(
const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
int imageWidth = 1056, int imageHeight = 992);
// 点云灰度图生成 - 灰色着色 + 自适应点大小填充扫描线间隙(通用接口)
static QImage GenerateHeatmapImage(
const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
double rotateX_deg = 0.0,
double rotateY_deg = 0.0);
// 孔洞检测图像生成 - 热力图底图 + 孔洞标记
// useZGradient: 为true时根据点云Z值范围生成灰度渐变底图否则使用统一灰色底图
static QImage GenerateHoleDetectionImage(
const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
const std::vector<HoleMarkerInfo>& holes,
double rotateX_deg = 0.0,
double rotateY_deg = 0.0,
bool useZGradient = false);
// 计算scan lines格式点云的范围
static void CalculateScanLinesRange(const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
double& xMin, double& xMax,
double& yMin, double& yMax);
private:
// 定义线特征颜色和大小获取函数
static void GetLineFeatureStyle(int vType, int hType, int objId,
QColor& pointColor, int& pointSize);
// 获取对象颜色
static QColor GetObjectColor(int index);
// 计算点云范围
static void CalculatePointCloudRange(SVzNL3DLaserLine* scanData, int lineNum,
double& xMin, double& xMax,
double& yMin, double& yMax);
// 绘制LapWeld检测结果
static void DrawLapWeldResults(QPainter& painter,
const std::vector<std::vector<SVzNL3DPoint>>& weldResults,
double xMin, double xMax, double yMin, double yMax,
int imageWidth, int imageHeight);
// 绘制scan lines点云数据
static void DrawScanLinesPointCloud(QPainter& painter,
const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
double xMin, double xMax, double yMin, double yMax,
int imageWidth, int imageHeight);
// 绘制检测目标(使用通用结构体)
static void DrawDetectionTargets(QPainter& painter,
const std::vector<DetectionTargetInfo>& objOps,
double xMin, double xScale, int xSkip,
double yMin, double yScale, int ySkip,
int imgCols, int imgRows);
};
/**
* @brief 通用点云画布类
* 封装点云底图生成 + 3D→2D投影 + 通用绘图原语
* 调用方可自由组合绘制点、文字、线段、圆等标记
*/
class PointCloudCanvas
{
public:
/**
* @brief 从 scan lines 创建画布,生成灰色点云底图
* @param scanLines 扫描线数据
* @param imageWidth 图像宽度(像素)
* @param imageHeight 图像高度(像素)
* @param margin 边距(像素)
*/
static PointCloudCanvas Create(const std::vector<std::vector<SVzNL3DPosition>>& scanLines,
int imageWidth = 1056, int imageHeight = 992, int margin = 50);
bool isValid() const;
QImage& image();
const QImage& image() const;
/// 3D坐标→图像像素坐标
QPoint project(double x, double y) const;
/// 绘制实心圆点
void drawPoint(double x, double y, const QColor& color, int size = 4);
/// 绘制圆radius3D为3D空间半径自动投影为像素半径
void drawCircle(double x, double y, double radius3D, const QColor& color, int penWidth = 2, bool fill = false);
/// 绘制文字offsetX/offsetY 为像素偏移)
void drawText(double x, double y, const QString& text, const QColor& color, int fontSize = 14, int offsetX = 8, int offsetY = 6);
/// 绘制线段
void drawLine(double x1, double y1, double x2, double y2, const QColor& color, int penWidth = 2);
private:
QImage m_image;
double m_xMin = 0.0;
double m_yMin = 0.0;
double m_scale = 1.0;
int m_offsetX = 0;
int m_offsetY = 0;
int m_imgWidth = 0;
int m_imgHeight = 0;
bool m_valid = false;
};
#endif // POINTCLOUDIMAGEUTILS_H