feat: v0.1.0更新

This commit is contained in:
2026-01-14 18:07:26 +08:00
commit efd8a7cc20
55 changed files with 6200 additions and 0 deletions

View File

@@ -0,0 +1,277 @@
#include "core/PointCloudProcessor.h"
#include <QDebug>
#include <vector>
PointCloudProcessor::PointCloudProcessor(QObject *parent)
: QObject(parent)
, m_fx(1432.8957f)
, m_fy(1432.6590f)
, m_cx(637.5117f)
, m_cy(521.8720f)
, m_zScale(0.2f)
, m_imageWidth(1224)
, m_imageHeight(1024)
, m_totalPoints(1224 * 1024)
, m_platform(nullptr)
, m_device(nullptr)
, m_context(nullptr)
, m_queue(nullptr)
, m_program(nullptr)
, m_kernel(nullptr)
, m_depthBuffer(nullptr)
, m_xyzBuffer(nullptr)
, m_clInitialized(false)
{
}
PointCloudProcessor::~PointCloudProcessor()
{
cleanupOpenCL();
}
void PointCloudProcessor::setCameraIntrinsics(float fx, float fy, float cx, float cy)
{
m_fx = fx;
m_fy = fy;
m_cx = cx;
m_cy = cy;
}
void PointCloudProcessor::setZScaleFactor(float scale)
{
m_zScale = scale;
}
bool PointCloudProcessor::initializeOpenCL()
{
if (m_clInitialized) {
return true;
}
cl_int err;
qDebug() << "[OpenCL] Starting initialization...";
// 1. 获取平台
err = clGetPlatformIDs(1, &m_platform, nullptr);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to get OpenCL platform");
return false;
}
// 2. 获取设备优先GPU
err = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_GPU, 1, &m_device, nullptr);
if (err != CL_SUCCESS) {
qDebug() << "[OpenCL] GPU not available, using CPU";
err = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_CPU, 1, &m_device, nullptr);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to get OpenCL device");
return false;
}
}
// 3. 创建上下文
m_context = clCreateContext(nullptr, 1, &m_device, nullptr, nullptr, &err);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to create OpenCL context");
return false;
}
// 4. 创建命令队列
#if CL_TARGET_OPENCL_VERSION >= 200
cl_queue_properties props[] = { CL_QUEUE_ON_DEVICE_DEFAULT, 0 };
m_queue = clCreateCommandQueueWithProperties(m_context, m_device, props, &err);
#else
m_queue = clCreateCommandQueue(m_context, m_device, 0, &err);
#endif
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to create command queue");
cleanupOpenCL();
return false;
}
qDebug() << "[OpenCL] Platform, device, context, and queue created successfully";
// 5. 创建并编译OpenCL程序
const char* kernelSource =
"__kernel void compute_xyz(__global const float* depth, "
"__global float* xyz, int width, int height, "
"float inv_fx, float inv_fy, float cx, float cy, float z_scale) { "
"int idx = get_global_id(0); "
"if (idx >= width * height) return; "
"int y = idx / width; "
"int x = idx % width; "
"float z = depth[idx] * z_scale; "
// 完全平面的圆柱投影X和Y直接使用像素坐标缩放到合适的范围
"xyz[idx*3] = (x - cx) * 2.0f; " // X坐标缩放系数2.0
"xyz[idx*3+1] = (y - cy) * 2.0f; " // Y坐标缩放系数2.0
"xyz[idx*3+2] = z; "
"}";
m_program = clCreateProgramWithSource(m_context, 1, &kernelSource, nullptr, &err);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to create OpenCL program");
cleanupOpenCL();
return false;
}
err = clBuildProgram(m_program, 1, &m_device, nullptr, nullptr, nullptr);
if (err != CL_SUCCESS) {
char buildLog[4096];
clGetProgramBuildInfo(m_program, m_device, CL_PROGRAM_BUILD_LOG, sizeof(buildLog), buildLog, nullptr);
emit errorOccurred(QString("Failed to build OpenCL program: %1").arg(buildLog));
cleanupOpenCL();
return false;
}
qDebug() << "[OpenCL] Program compiled successfully";
// 6. 创建kernel
m_kernel = clCreateKernel(m_program, "compute_xyz", &err);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to create OpenCL kernel");
cleanupOpenCL();
return false;
}
// 7. 创建缓冲区
m_depthBuffer = clCreateBuffer(m_context, CL_MEM_READ_ONLY,
sizeof(float) * m_totalPoints, nullptr, &err);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to create depth buffer");
cleanupOpenCL();
return false;
}
m_xyzBuffer = clCreateBuffer(m_context, CL_MEM_WRITE_ONLY,
sizeof(float) * m_totalPoints * 3, nullptr, &err);
if (err != CL_SUCCESS) {
emit errorOccurred("Failed to create XYZ buffer");
cleanupOpenCL();
return false;
}
m_clInitialized = true;
qDebug() << "[OpenCL] Initialization complete";
return true;
}
void PointCloudProcessor::processDepthData(const QByteArray &depthData, uint32_t blockId)
{
if (!m_clInitialized) {
if (!initializeOpenCL()) {
return;
}
}
// 验证数据大小
if (depthData.size() != m_totalPoints * sizeof(int16_t)) {
qDebug() << "[PointCloud] Invalid depth data size:" << depthData.size()
<< "expected:" << (m_totalPoints * sizeof(int16_t));
return;
}
// 转换int16_t到float
const int16_t* depthShort = reinterpret_cast<const int16_t*>(depthData.constData());
std::vector<float> depthFloat(m_totalPoints);
for (size_t i = 0; i < m_totalPoints; i++) {
depthFloat[i] = static_cast<float>(depthShort[i]);
}
// 注释掉频繁的日志输出
// qDebug() << "[PointCloud] Processing block" << blockId << "with" << m_totalPoints << "points";
// 上传深度数据到GPU
cl_int err = clEnqueueWriteBuffer(m_queue, m_depthBuffer, CL_TRUE, 0,
sizeof(float) * m_totalPoints, depthFloat.data(),
0, nullptr, nullptr);
if (err != CL_SUCCESS) {
emit errorOccurred(QString("Failed to upload depth data: %1").arg(err));
return;
}
// 设置kernel参数
float inv_fx = 1.0f / m_fx;
float inv_fy = 1.0f / m_fy;
int width = m_imageWidth;
int height = m_imageHeight;
clSetKernelArg(m_kernel, 0, sizeof(cl_mem), &m_depthBuffer);
clSetKernelArg(m_kernel, 1, sizeof(cl_mem), &m_xyzBuffer);
clSetKernelArg(m_kernel, 2, sizeof(int), &width);
clSetKernelArg(m_kernel, 3, sizeof(int), &height);
clSetKernelArg(m_kernel, 4, sizeof(float), &inv_fx);
clSetKernelArg(m_kernel, 5, sizeof(float), &inv_fy);
clSetKernelArg(m_kernel, 6, sizeof(float), &m_cx);
clSetKernelArg(m_kernel, 7, sizeof(float), &m_cy);
clSetKernelArg(m_kernel, 8, sizeof(float), &m_zScale);
// 执行kernel
size_t local = 256;
size_t global = ((m_totalPoints + local - 1) / local) * local;
err = clEnqueueNDRangeKernel(m_queue, m_kernel, 1, nullptr,
&global, &local, 0, nullptr, nullptr);
if (err != CL_SUCCESS) {
emit errorOccurred(QString("Failed to execute kernel: %1").arg(err));
return;
}
clFinish(m_queue);
// 读取结果
std::vector<float> xyz(m_totalPoints * 3);
err = clEnqueueReadBuffer(m_queue, m_xyzBuffer, CL_TRUE, 0,
sizeof(float) * m_totalPoints * 3, xyz.data(),
0, nullptr, nullptr);
if (err != CL_SUCCESS) {
emit errorOccurred(QString("Failed to read XYZ data: %1").arg(err));
return;
}
// 创建PCL点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->width = m_imageWidth;
cloud->height = m_imageHeight;
cloud->is_dense = false;
cloud->points.resize(m_totalPoints);
// 填充点云数据(过滤全零点)
for (size_t i = 0; i < m_totalPoints; i++) {
cloud->points[i].x = xyz[i * 3];
cloud->points[i].y = xyz[i * 3 + 1];
cloud->points[i].z = xyz[i * 3 + 2];
}
// 注释掉频繁的日志输出
// qDebug() << "[PointCloud] Block" << blockId << "processed successfully";
emit pointCloudReady(cloud, blockId);
}
void PointCloudProcessor::cleanupOpenCL()
{
if (m_depthBuffer) {
clReleaseMemObject(m_depthBuffer);
m_depthBuffer = nullptr;
}
if (m_xyzBuffer) {
clReleaseMemObject(m_xyzBuffer);
m_xyzBuffer = nullptr;
}
if (m_kernel) {
clReleaseKernel(m_kernel);
m_kernel = nullptr;
}
if (m_program) {
clReleaseProgram(m_program);
m_program = nullptr;
}
if (m_queue) {
clReleaseCommandQueue(m_queue);
m_queue = nullptr;
}
if (m_context) {
clReleaseContext(m_context);
m_context = nullptr;
}
m_clInitialized = false;
qDebug() << "[OpenCL] Cleanup complete";
}