diff --git a/Mali_OpenCL_results.txt b/Mali_OpenCL_results.txt deleted file mode 100644 index 4603a49e64ec4d1a48265b2bc0e49603b249721d..0000000000000000000000000000000000000000 --- a/Mali_OpenCL_results.txt +++ /dev/null @@ -1,527 +0,0 @@ -一、CPP代码: -#define CL_TARGET_OPENCL_VERSION 300 // 定义目标OpenCL版本(3.0) -#include -#include -#include -#include -#include -#include - -#define MAX_PLATFORMS 10 -#define MAX_DEVICES 10 -#define DATA_SIZE 1024 // 测试数据大小 - -// 打印设备信息 -void printDeviceInfo(cl_device_id device) { - char device_name[256]; - char device_vendor[256]; - char device_version[256]; - char driver_version[256]; - char device_extensions[4096]; - - clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name), device_name, NULL); - clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(device_vendor), device_vendor, NULL); - clGetDeviceInfo(device, CL_DEVICE_VERSION, sizeof(device_version), device_version, NULL); - clGetDeviceInfo(device, CL_DRIVER_VERSION, sizeof(driver_version), driver_version, NULL); - - cl_ulong global_mem_size; - cl_ulong local_mem_size; - cl_uint max_compute_units; - size_t max_work_group_size; - cl_uint max_work_item_dimensions; - size_t max_work_item_sizes[3]; - - clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(global_mem_size), &global_mem_size, NULL); - clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(local_mem_size), &local_mem_size, NULL); - clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(max_compute_units), &max_compute_units, NULL); - clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_work_group_size), &max_work_group_size, NULL); - clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(max_work_item_dimensions), &max_work_item_dimensions, NULL); - clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_work_item_sizes), max_work_item_sizes, NULL); - clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, sizeof(device_extensions), device_extensions, NULL); - - printf(" Device Name: %s\n", device_name); - printf(" Vendor: %s\n", device_vendor); - printf(" Device Version: %s\n", device_version); - printf(" Driver Version: %s\n", driver_version); - printf(" Global Memory Size: %lu MB\n", global_mem_size / (1024 * 1024)); - printf(" Local Memory Size: %lu KB\n", local_mem_size / 1024); - printf(" Max Compute Units: %u\n", max_compute_units); - printf(" Max Work Group Size: %zu\n", max_work_group_size); - printf(" Max Work Item Dimensions: %u\n", max_work_item_dimensions); - printf(" Max Work Item Sizes: [%zu, %zu, %zu]\n", - max_work_item_sizes[0], max_work_item_sizes[1], max_work_item_sizes[2]); - - // 检查重要扩展 - printf(" Important Extensions:\n"); - if (strstr(device_extensions, "cl_khr_fp64")) printf(" - Double precision support (cl_khr_fp64)\n"); - if (strstr(device_extensions, "cl_khr_fp16")) printf(" - Half precision support (cl_khr_fp16)\n"); - if (strstr(device_extensions, "cl_arm_integer_dot_product_int8")) printf(" - Integer dot product (cl_arm_integer_dot_product_int8)\n"); - if (strstr(device_extensions, "cl_arm_printf")) printf(" - Kernel printf support (cl_arm_printf)\n"); -} - -// 向量加法OpenCL内核 -const char* vector_add_kernel = -"__kernel void vector_add(__global const float* a, __global const float* b, __global float* result) {\n" -" int idx = get_global_id(0);\n" -" result[idx] = a[idx] + b[idx];\n" -"}\n"; - -// 矩阵乘法OpenCL内核 -const char* matrix_mul_kernel = -"__kernel void matrix_mul(__global const float* a, __global const float* b, __global float* c, \n" -" int width_a, int width_b) {\n" -" int row = get_global_id(0);\n" -" int col = get_global_id(1);\n" -" \n" -" float sum = 0.0f;\n" -" for (int k = 0; k < width_a; k++) {\n" -" sum += a[row * width_a + k] * b[k * width_b + col];\n" -" }\n" -" c[row * width_b + col] = sum;\n" -"}\n"; - -// 性能测试内核 -const char* performance_kernel = -"__kernel void performance_test(__global float* data) {\n" -" int idx = get_global_id(0);\n" -" float x = (float)idx;\n" -" \n" -" // 一些数学运算来测试性能\n" -" for (int i = 0; i < 100; i++) {\n" -" x = sin(x) * cos(x) + sqrt(fabs(x));\n" -" }\n" -" \n" -" data[idx] = x;\n" -"}\n"; - -int main() { - cl_platform_id platforms[MAX_PLATFORMS]; - cl_device_id devices[MAX_DEVICES]; - cl_uint num_platforms, num_devices; - cl_context context; - cl_command_queue command_queue; - cl_program program; - cl_kernel kernel; - cl_int ret; - - printf("=== Mali GPU OpenCL 完整测试 ===\n\n"); - - // 1. 获取平台数量 - ret = clGetPlatformIDs(MAX_PLATFORMS, platforms, &num_platforms); - if (ret != CL_SUCCESS || num_platforms == 0) { - printf("错误: 没有找到OpenCL平台\n"); - return -1; - } - - printf("找到 %u 个OpenCL平台:\n", num_platforms); - - // 2. 遍历打印平台信息 - for (cl_uint i = 0; i < num_platforms; i++) { - char platform_name[128]; - char platform_vendor[128]; - char platform_version[128]; - - clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, sizeof(platform_name), platform_name, NULL); - clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, sizeof(platform_vendor), platform_vendor, NULL); - clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, sizeof(platform_version), platform_version, NULL); - - printf("平台 %u:\n", i); - printf(" 名称: %s\n", platform_name); - printf(" 供应商: %s\n", platform_vendor); - printf(" 版本: %s\n", platform_version); - - // 3. 获取设备信息 - cl_uint device_count; - ret = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, MAX_DEVICES, devices, &device_count); - if (ret != CL_SUCCESS) { - printf(" 警告: 无法获取设备列表\n"); - continue; - } - - printf(" 找到 %u 个设备:\n", device_count); - - for (cl_uint j = 0; j < device_count; j++) { - printf(" 设备 %u:\n", j); - printDeviceInfo(devices[j]); - } - } - - // 4. 使用第一个平台的第一个GPU设备 - ret = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, MAX_DEVICES, devices, &num_devices); - if (ret != CL_SUCCESS || num_devices == 0) { - printf("错误: 没有找到GPU设备\n"); - return -1; - } - - printf("\n=== 使用设备: ===\n"); - printDeviceInfo(devices[0]); - - // 5. 创建OpenCL上下文 - context = clCreateContext(NULL, 1, &devices[0], NULL, NULL, &ret); - if (ret != CL_SUCCESS) { - printf("错误: 无法创建OpenCL上下文\n"); - return -1; - } - - // 6. 创建命令队列 - command_queue = clCreateCommandQueue(context, devices[0], CL_QUEUE_PROFILING_ENABLE, &ret); - if (ret != CL_SUCCESS) { - printf("错误: 无法创建命令队列\n"); - return -1; - } - - printf("\n=== 测试1: 向量加法 ===\n"); - - // 7. 创建向量加法程序 - program = clCreateProgramWithSource(context, 1, &vector_add_kernel, NULL, &ret); - if (ret != CL_SUCCESS) { - printf("错误: 无法创建程序\n"); - return -1; - } - - // 8. 构建程序 - ret = clBuildProgram(program, 1, &devices[0], NULL, NULL, NULL); - if (ret != CL_SUCCESS) { - printf("错误: 程序构建失败\n"); - // 获取构建日志 - size_t log_size; - clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); - char *log = (char *)malloc(log_size); - clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, log_size, log, NULL); - printf("构建日志:\n%s\n", log); - free(log); - return -1; - } - - // 9. 创建内核 - kernel = clCreateKernel(program, "vector_add", &ret); - if (ret != CL_SUCCESS) { - printf("错误: 无法创建内核\n"); - return -1; - } - - // 10. 准备测试数据 - size_t data_bytes = DATA_SIZE * sizeof(float); - float *a = (float*)malloc(data_bytes); - float *b = (float*)malloc(data_bytes); - float *results = (float*)malloc(data_bytes); - float *cpu_results = (float*)malloc(data_bytes); - - srand(time(NULL)); - for (size_t i = 0; i < DATA_SIZE; i++) { - a[i] = (float)rand() / RAND_MAX * 100.0f; - b[i] = (float)rand() / RAND_MAX * 100.0f; - cpu_results[i] = a[i] + b[i]; // CPU计算结果用于验证 - } - - // 11. 创建OpenCL缓冲区 - cl_mem a_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, - data_bytes, a, &ret); - cl_mem b_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, - data_bytes, b, &ret); - cl_mem results_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, - data_bytes, NULL, &ret); - - // 12. 设置内核参数 - ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), &a_buffer); - ret |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &b_buffer); - ret |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &results_buffer); - - if (ret != CL_SUCCESS) { - printf("错误: 无法设置内核参数\n"); - return -1; - } - - // 13. 执行内核(带性能测量) - cl_event event; - size_t global_work_size = DATA_SIZE; - size_t local_work_size = 64; // 典型的工作组大小 - - ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, - &global_work_size, &local_work_size, - 0, NULL, &event); - if (ret != CL_SUCCESS) { - printf("错误: 无法执行内核\n"); - return -1; - } - - clWaitForEvents(1, &event); - - // 14. 获取性能数据 - cl_ulong start_time, end_time; - clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, - sizeof(cl_ulong), &start_time, NULL); - clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, - sizeof(cl_ulong), &end_time, NULL); - - double gpu_time = (end_time - start_time) / 1e6; // 转换为毫秒 - - // 15. 读取结果 - ret = clEnqueueReadBuffer(command_queue, results_buffer, CL_TRUE, 0, - data_bytes, results, 0, NULL, NULL); - - // 16. 验证结果 - int errors = 0; - for (size_t i = 0; i < DATA_SIZE; i++) { - if (fabs(results[i] - cpu_results[i]) > 0.001f) { - errors++; - if (errors < 10) { - printf(" 错误: results[%zu] = %f, 期望 = %f\n", - i, results[i], cpu_results[i]); - } - } - } - - if (errors == 0) { - printf(" 测试通过: 向量加法正确\n"); - printf(" 执行时间: %.3f ms\n", gpu_time); - printf(" 吞吐量: %.2f MFLOPs\n", - (DATA_SIZE * 1.0) / (gpu_time / 1000.0) / 1e6); - } else { - printf(" 测试失败: 发现 %d 个错误\n", errors); - } - - // 清理测试1的资源 - clReleaseMemObject(a_buffer); - clReleaseMemObject(b_buffer); - clReleaseMemObject(results_buffer); - clReleaseKernel(kernel); - clReleaseProgram(program); - clReleaseEvent(event); - - printf("\n=== 测试2: 矩阵乘法 ===\n"); - - // 17. 测试矩阵乘法 - const int MATRIX_SIZE = 32; // 小矩阵,适合测试 - int matrix_bytes = MATRIX_SIZE * MATRIX_SIZE * sizeof(float); - - // 创建矩阵乘法程序 - program = clCreateProgramWithSource(context, 1, &matrix_mul_kernel, NULL, &ret); - ret = clBuildProgram(program, 1, &devices[0], NULL, NULL, NULL); - kernel = clCreateKernel(program, "matrix_mul", &ret); - - // 准备矩阵数据 - float *matrix_a = (float*)malloc(matrix_bytes); - float *matrix_b = (float*)malloc(matrix_bytes); - float *matrix_c = (float*)malloc(matrix_bytes); - float *matrix_c_cpu = (float*)malloc(matrix_bytes); - - for (int i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) { - matrix_a[i] = (float)rand() / RAND_MAX * 10.0f; - matrix_b[i] = (float)rand() / RAND_MAX * 10.0f; - matrix_c_cpu[i] = 0.0f; - } - - // CPU矩阵乘法 - clock_t cpu_start = clock(); - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - float sum = 0.0f; - for (int k = 0; k < MATRIX_SIZE; k++) { - sum += matrix_a[i * MATRIX_SIZE + k] * matrix_b[k * MATRIX_SIZE + j]; - } - matrix_c_cpu[i * MATRIX_SIZE + j] = sum; - } - } - clock_t cpu_end = clock(); - double cpu_time = (double)(cpu_end - cpu_start) / CLOCKS_PER_SEC * 1000.0; - - // GPU矩阵乘法 - cl_mem buffer_a = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, - matrix_bytes, matrix_a, &ret); - cl_mem buffer_b = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, - matrix_bytes, matrix_b, &ret); - cl_mem buffer_c = clCreateBuffer(context, CL_MEM_WRITE_ONLY, - matrix_bytes, NULL, &ret); - - int width_a = MATRIX_SIZE; - int width_b = MATRIX_SIZE; - clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer_a); - clSetKernelArg(kernel, 1, sizeof(cl_mem), &buffer_b); - clSetKernelArg(kernel, 2, sizeof(cl_mem), &buffer_c); - clSetKernelArg(kernel, 3, sizeof(int), &width_a); - clSetKernelArg(kernel, 4, sizeof(int), &width_b); - - size_t global_work_size2[2] = {MATRIX_SIZE, MATRIX_SIZE}; - size_t local_work_size2[2] = {8, 8}; // 适合Mali的局部工作组大小 - - cl_event event2; - ret = clEnqueueNDRangeKernel(command_queue, kernel, 2, NULL, - global_work_size2, local_work_size2, - 0, NULL, &event2); - - clWaitForEvents(1, &event2); - clEnqueueReadBuffer(command_queue, buffer_c, CL_TRUE, 0, - matrix_bytes, matrix_c, 0, NULL, NULL); - - // 获取GPU时间 - clGetEventProfilingInfo(event2, CL_PROFILING_COMMAND_START, - sizeof(cl_ulong), &start_time, NULL); - clGetEventProfilingInfo(event2, CL_PROFILING_COMMAND_END, - sizeof(cl_ulong), &end_time, NULL); - double gpu_time2 = (end_time - start_time) / 1e6; - - // 验证结果 - errors = 0; - for (int i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) { - if (fabs(matrix_c[i] - matrix_c_cpu[i]) > 0.01f) { - errors++; - } - } - - if (errors == 0) { - printf(" 测试通过: 矩阵乘法正确\n"); - printf(" CPU时间: %.3f ms\n", cpu_time); - printf(" GPU时间: %.3f ms\n", gpu_time2); - printf(" 加速比: %.2fx\n", cpu_time / gpu_time2); - } else { - printf(" 测试失败: 发现 %d 个错误\n", errors); - } - - // 清理测试2的资源 - clReleaseMemObject(buffer_a); - clReleaseMemObject(buffer_b); - clReleaseMemObject(buffer_c); - clReleaseKernel(kernel); - clReleaseProgram(program); - clReleaseEvent(event2); - - // 18. 测试性能(数学运算密集型) - printf("\n=== 测试3: 数学运算性能 ===\n"); - - program = clCreateProgramWithSource(context, 1, &performance_kernel, NULL, &ret); - ret = clBuildProgram(program, 1, &devices[0], NULL, NULL, NULL); - kernel = clCreateKernel(program, "performance_test", &ret); - - float *perf_data = (float*)malloc(data_bytes); - cl_mem perf_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, data_bytes, NULL, &ret); - clSetKernelArg(kernel, 0, sizeof(cl_mem), &perf_buffer); - - cl_event event3; - ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, - &global_work_size, &local_work_size, - 0, NULL, &event3); - clWaitForEvents(1, &event3); - clEnqueueReadBuffer(command_queue, perf_buffer, CL_TRUE, 0, - data_bytes, perf_data, 0, NULL, NULL); - - clGetEventProfilingInfo(event3, CL_PROFILING_COMMAND_START, - sizeof(cl_ulong), &start_time, NULL); - clGetEventProfilingInfo(event3, CL_PROFILING_COMMAND_END, - sizeof(cl_ulong), &end_time, NULL); - double gpu_time3 = (end_time - start_time) / 1e6; - - printf(" 数学运算时间: %.3f ms\n", gpu_time3); - printf(" 性能: %.2f GFLOPS\n", - (DATA_SIZE * 100.0 * 5.0) / (gpu_time3 / 1000.0) / 1e9); - - // 19. 内存带宽测试 - printf("\n=== 测试4: 内存带宽 ===\n"); - - // 简单内存拷贝测试 - cl_mem src_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY, data_bytes, NULL, &ret); - cl_mem dst_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, data_bytes, NULL, &ret); - - cl_event copy_event; - ret = clEnqueueCopyBuffer(command_queue, src_buffer, dst_buffer, 0, 0, - data_bytes, 0, NULL, ©_event); - clWaitForEvents(1, ©_event); - - clGetEventProfilingInfo(copy_event, CL_PROFILING_COMMAND_START, - sizeof(cl_ulong), &start_time, NULL); - clGetEventProfilingInfo(copy_event, CL_PROFILING_COMMAND_END, - sizeof(cl_ulong), &end_time, NULL); - double copy_time = (end_time - start_time) / 1e6; - double bandwidth = (data_bytes * 2.0) / (copy_time / 1000.0) / (1024*1024*1024); - - printf(" 内存拷贝时间: %.3f ms\n", copy_time); - printf(" 估计带宽: %.2f GB/s\n", bandwidth); - - // 20. 资源清理 - clReleaseMemObject(src_buffer); - clReleaseMemObject(dst_buffer); - clReleaseMemObject(perf_buffer); - clReleaseKernel(kernel); - clReleaseProgram(program); - clReleaseEvent(event3); - clReleaseEvent(copy_event); - clReleaseCommandQueue(command_queue); - clReleaseContext(context); - - // 释放主机内存 - free(a); - free(b); - free(results); - free(cpu_results); - free(matrix_a); - free(matrix_b); - free(matrix_c); - free(matrix_c_cpu); - free(perf_data); - - printf("\n=== 测试完成 ===\n"); - return 0; -} - -二、运行结果: -=== Mali GPU OpenCL 完整测试 === - -arm_release_ver: g13p0-01eac0, rk_so_ver: 10 -找到 1 个OpenCL平台: -平台 0: - 名称: ARM Platform - 供应商: ARM - 版本: OpenCL 3.0 v1.g13p0-01eac0.68603db295fbf2c59ac6b927fdfb1c32 - 找到 1 个设备: - 设备 0: - Device Name: Mali-G610 r0p0 - Vendor: ARM - Device Version: OpenCL 3.0 v1.g13p0-01eac0.68603db295fbf2c59ac6b927fdfb1c32 - Driver Version: 3.0 - Global Memory Size: 7927 MB - Local Memory Size: 32 KB - Max Compute Units: 4 - Max Work Group Size: 1024 - Max Work Item Dimensions: 3 - Max Work Item Sizes: [1024, 1024, 1024] - Important Extensions: - - Half precision support (cl_khr_fp16) - - Integer dot product (cl_arm_integer_dot_product_int8) - - Kernel printf support (cl_arm_printf) - -=== 使用设备: === - Device Name: Mali-G610 r0p0 - Vendor: ARM - Device Version: OpenCL 3.0 v1.g13p0-01eac0.68603db295fbf2c59ac6b927fdfb1c32 - Driver Version: 3.0 - Global Memory Size: 7927 MB - Local Memory Size: 32 KB - Max Compute Units: 4 - Max Work Group Size: 1024 - Max Work Item Dimensions: 3 - Max Work Item Sizes: [1024, 1024, 1024] - Important Extensions: - - Half precision support (cl_khr_fp16) - - Integer dot product (cl_arm_integer_dot_product_int8) - - Kernel printf support (cl_arm_printf) - -=== 测试1: 向量加法 === - 测试通过: 向量加法正确 - 执行时间: 0.013 ms - 吞吐量: 76.27 MFLOPs - -=== 测试2: 矩阵乘法 === - 测试通过: 矩阵乘法正确 - CPU时间: 0.134 ms - GPU时间: 0.083 ms - 加速比: 1.61x - -=== 测试3: 数学运算性能 === - 数学运算时间: 0.229 ms - 性能: 2.23 GFLOPS - -=== 测试4: 内存带宽 === - 内存拷贝时间: 0.004 ms - 估计带宽: 1.87 GB/s - -=== 测试完成 === \ No newline at end of file diff --git a/VisualRobot/VisualRobot.pro b/VisualRobot/VisualRobot.pro index 4978a3f318784ee51e49eb9e23f85453c7f1216c..418bc1ceace4b81aa976150da8497e4e87b66d9a 100644 --- a/VisualRobot/VisualRobot.pro +++ b/VisualRobot/VisualRobot.pro @@ -18,12 +18,22 @@ DEFINES += QT_DEPRECATED_WARNINGS # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 +# 硬件平台配置选项 +# 默认使用OrangePi 5 RK3588S配置 +# 可通过qmake命令行参数指定: qmake CONFIG+=orangepi5_rk3588s +# 或: qmake CONFIG+=raspberrypi4 +# 或: qmake CONFIG+=x86_64_pc + +# 默认配置 +CONFIG += orangepi5_rk3588s + SOURCES += \ DIP.cpp \ DLProcessor.cpp \ DataProcessor.cpp \ MvCamera.cpp \ SystemMonitor.cpp \ + configmanager.cpp \ main.cpp \ mainwindow.cpp \ mainwindow_systemstats.cpp \ @@ -42,6 +52,7 @@ HEADERS += \ YOLOProcessorORT.h \ MvCamera.h \ SystemMonitor.h \ + configmanager.h \ mainwindow.h \ DLExample.h \ Undistort.h \ @@ -51,49 +62,128 @@ HEADERS += \ FORMS += \ mainwindow.ui +# 公共包含路径 INCLUDEPATH += /opt/MVS/include - INCLUDEPATH += /usr/include/eigen3/Eigen -INCLUDEPATH += /usr/local/include \ - /usr/local/include/opencv4 \ - /usr/local/include/opencv4/opencv2 - -INCLUDEPATH += /home/orangepi/Desktop/VisualRobot_Local/onnxruntime-linux-aarch64-1.23.2/include - -LIBS += -L/home/orangepi/Desktop/VisualRobot_Local/onnxruntime-linux-aarch64-1.23.2/lib -lonnxruntime - -LIBS += -L/usr/local/lib/ -lopencv_calib3d -lopencv_core -lopencv_dnn -lopencv_features2d \ - -lopencv_flann -lopencv_gapi -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc \ - -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video \ - -lopencv_videoio +# OrangePi 5 RK3588S 配置 +orangepi5_rk3588s { + message("Configuring for OrangePi 5 RK3588S") + + INCLUDEPATH += /usr/local/include \ + /usr/local/include/opencv4 \ + /usr/local/include/opencv4/opencv2 + + INCLUDEPATH += /home/orangepi/Desktop/VisualRobot_Local/onnxruntime-linux-aarch64-1.23.2/include + + LIBS += -L/home/orangepi/Desktop/VisualRobot_Local/onnxruntime-linux-aarch64-1.23.2/lib -lonnxruntime + + LIBS += -L/usr/local/lib/ -lopencv_calib3d -lopencv_core -lopencv_dnn -lopencv_features2d \ + -lopencv_flann -lopencv_gapi -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc \ + -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video \ + -lopencv_videoio + + LIBS += -L/opt/MVS/lib/aarch64/ -lMvCameraControl -lMvCameraControlWrapper -lMVGigEVisionSDK -lMvUsb3vTL + + LIBS += -L/usr/lib/aarch64-linux-gnu -lmali -lOpenCL +} -LIBS += -L/opt/MVS/lib/aarch64/ -lMvCameraControl -lMvCameraControlWrapper -lMVGigEVisionSDK -lMvUsb3vTL +# Raspberry Pi 4 配置 +raspberrypi4 { + message("Configuring for Raspberry Pi 4") + + INCLUDEPATH += /usr/local/include \ + /usr/local/include/opencv4 \ + /usr/local/include/opencv4/opencv2 + + INCLUDEPATH += /home/pi/onnxruntime-linux-aarch64-1.23.2/include + + LIBS += -L/home/pi/onnxruntime-linux-aarch64-1.23.2/lib -lonnxruntime + + LIBS += -L/usr/local/lib/ -lopencv_calib3d -lopencv_core -lopencv_dnn -lopencv_features2d \ + -lopencv_flann -lopencv_gapi -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc \ + -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video \ + -lopencv_videoio + + LIBS += -L/opt/MVS/lib/aarch64/ -lMvCameraControl -lMvCameraControlWrapper -lMVGigEVisionSDK -lMvUsb3vTL +} -LIBS += -L/usr/lib/aarch64-linux-gnu -lmali -lOpenCL +# x86_64 PC 配置 +x86_64_pc { + message("Configuring for x86_64 PC") + + INCLUDEPATH += /usr/local/include \ + /usr/local/include/opencv4 \ + /usr/local/include/opencv4/opencv2 + + INCLUDEPATH += /usr/local/include/onnxruntime + + LIBS += -L/usr/local/lib -lonnxruntime + + LIBS += -L/usr/local/lib/ -lopencv_calib3d -lopencv_core -lopencv_dnn -lopencv_features2d \ + -lopencv_flann -lopencv_gapi -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc \ + -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video \ + -lopencv_videoio + + LIBS += -L/opt/MVS/lib/x86_64/ -lMvCameraControl -lMvCameraControlWrapper -lMVGigEVisionSDK -lMvUsb3vTL + + LIBS += -L/usr/lib/x86_64-linux-gnu -lOpenCL +} # 编译优化选项 unix { # 启用所有警告 QMAKE_CXXFLAGS += -Wall -Wextra - # 优化选项 + # 基础优化选项 QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CXXFLAGS_RELEASE += -O3 - - # 架构特定优化 - QMAKE_CXXFLAGS += -march=armv8.2-a -mtune=cortex-a76.cortex-a55 - - # SIMD和向量化优化 - QMAKE_CXXFLAGS += -ftree-vectorize -ftree-slp-vectorize - + # 链接时优化 QMAKE_CXXFLAGS += -flto QMAKE_LFLAGS += -flto - - # 缓存和内存优化 - QMAKE_CXXFLAGS += -fprefetch-loop-arrays - QMAKE_CXXFLAGS += -falign-functions=64 + + # OrangePi 5 RK3588S 特定优化 + orangepi5_rk3588s { + # 架构特定优化 + QMAKE_CXXFLAGS += -march=armv8.2-a -mtune=cortex-a76.cortex-a55 + + # SIMD和向量化优化 + QMAKE_CXXFLAGS += -ftree-vectorize -ftree-slp-vectorize + + # 缓存和内存优化 + QMAKE_CXXFLAGS += -fprefetch-loop-arrays + QMAKE_CXXFLAGS += -falign-functions=64 + } + + # Raspberry Pi 4 特定优化 + raspberrypi4 { + # 架构特定优化 + QMAKE_CXXFLAGS += -march=armv8-a -mtune=cortex-a72 + + # SIMD和向量化优化 + QMAKE_CXXFLAGS += -ftree-vectorize + + # 内存优化 + QMAKE_CXXFLAGS += -falign-functions=32 + } + + # x86_64 PC 特定优化 + x86_64_pc { + # 架构特定优化 + QMAKE_CXXFLAGS += -march=native -mtune=native + + # SIMD和向量化优化 + QMAKE_CXXFLAGS += -ftree-vectorize -ftree-slp-vectorize + + # 缓存和内存优化 + QMAKE_CXXFLAGS += -fprefetch-loop-arrays + QMAKE_CXXFLAGS += -falign-functions=64 + + # 并行优化 + QMAKE_CXXFLAGS += -fopenmp + QMAKE_LFLAGS += -fopenmp + } } # Default rules for deployment. @@ -102,4 +192,4 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target # Bundle the UI stylesheet into the application resources so it is available at runtime -RESOURCES += styles.qrc +RESOURCES += styles.qrc hardware_config.qrc diff --git a/VisualRobot/YOLOExample.cpp b/VisualRobot/YOLOExample.cpp index 361d9acf1e26787eb32c03f12efba95d9eb82b44..07cd94eae0e3db4f4e1753a99d24855085d02dda 100644 --- a/VisualRobot/YOLOExample.cpp +++ b/VisualRobot/YOLOExample.cpp @@ -31,10 +31,10 @@ YOLOExample::YOLOExample(QWidget *parent) SetupUI(); // 设置UI界面 ConnectSignals(); // 连接信号和槽 - // 固定模型路径 - QString modelPath = "../models/arcuchi2.onnx"; - // 固定标签路径 - QString labelPath = "../Data/Labels/class_labels.txt"; + // 从配置管理器获取路径 + ConfigManager* config = ConfigManager::instance(); + QString modelPath = config->getModelPath() + "/arcuchi2.onnx"; + QString labelPath = config->getLabelPath() + "/class_labels.txt"; // 加载模型 bool modelOk = yoloProcessor_->InitModel(modelPath.toStdString(), false); diff --git a/VisualRobot/YOLOProcessorORT.cpp b/VisualRobot/YOLOProcessorORT.cpp index abaadcf89a371b183eeaba57addb9b18d689b098..e792513668f90cd660d99e3236eeb8eb0324fc1a 100644 --- a/VisualRobot/YOLOProcessorORT.cpp +++ b/VisualRobot/YOLOProcessorORT.cpp @@ -12,6 +12,8 @@ using namespace std; +#include "configmanager.h" + /** * @brief YOLOProcessorORT构造函数 * @param parent 父对象指针 @@ -31,21 +33,62 @@ YOLOProcessorORT::YOLOProcessorORT(QObject* parent) , letterbox_dw_(0.0) // 宽度方向填充,初始化为0.0 , letterbox_dh_(0.0) // 高度方向填充,初始化为0.0 { - // 根据嵌入式设备特点调整的配置 - sessionOptions_.SetIntraOpNumThreads(4); - sessionOptions_.SetInterOpNumThreads(1); + // 从配置管理器获取优化参数 + ConfigManager* config = ConfigManager::instance(); + + // 设置线程数 + sessionOptions_.SetIntraOpNumThreads(config->getIntraOpNumThreads()); + sessionOptions_.SetInterOpNumThreads(config->getInterOpNumThreads()); - // 根据内存情况选择: - // 如果内存紧张,禁用Arena分配器 - // sessionOptions_.DisableCpuMemArena(); // 减少内存使用 - // 如果内存充足,启用Arena分配器以提升性能 - sessionOptions_.EnableCpuMemArena(); + // 设置内存管理 + if (config->getEnableCpuMemArena()) + { + sessionOptions_.EnableCpuMemArena(); + } + else + { + sessionOptions_.DisableCpuMemArena(); + } - sessionOptions_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED); - sessionOptions_.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL); + // 设置图优化级别 + QString graphOptLevel = config->getGraphOptimizationLevel(); + if (graphOptLevel == "ORT_ENABLE_ALL") + { + sessionOptions_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL); + } + else if (graphOptLevel == "ORT_ENABLE_EXTENDED") + { + sessionOptions_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED); + } + else if (graphOptLevel == "ORT_ENABLE_BASIC") + { + sessionOptions_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_BASIC); + } + else + { + sessionOptions_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_DISABLE_ALL); + } + + // 设置执行模式 + QString execMode = config->getExecutionMode(); + if (execMode == "ORT_PARALLEL") + { + sessionOptions_.SetExecutionMode(ExecutionMode::ORT_PARALLEL); + } + else + { + sessionOptions_.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL); + } - // 如果输入尺寸固定,启用内存模式优化 - sessionOptions_.EnableMemPattern(); + // 设置内存模式优化 + if (config->getEnableMemPattern()) + { + sessionOptions_.EnableMemPattern(); + } + else + { + sessionOptions_.DisableMemPattern(); + } // 可选:启用profiling(仅用于调试) // sessionOptions_.EnableProfiling("profile.json"); @@ -80,10 +123,15 @@ bool YOLOProcessorORT::InitModel(const string& modelPath, bool useCUDA) { try { - // 配置OpenCL参数 - sessionOptions_.AddConfigEntry("session.enable_opencl","1"); - sessionOptions_.AddConfigEntry("opencl_device_id", "0"); // 使用第一个OpenCL设备 - sessionOptions_.AddConfigEntry("opencl_mem_limit", "4096"); // 4GB内存限制 + // 从配置管理器获取加速选项 + ConfigManager* config = ConfigManager::instance(); + if (config->isAcceleratorEnabled("opencl")) { + sessionOptions_.AddConfigEntry("session.enable_opencl","1"); + sessionOptions_.AddConfigEntry("opencl_device_id", "0"); // 使用第一个OpenCL设备 + sessionOptions_.AddConfigEntry("opencl_mem_limit", "4096"); // 4GB内存限制 + } else { + sessionOptions_.AddConfigEntry("session.enable_opencl","0"); + } session_ = std::make_unique(env_, modelPath.c_str(), sessionOptions_); return true; diff --git a/VisualRobot/configmanager.cpp b/VisualRobot/configmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b25f2e7d84593c851962cb389aa4427592fa7cf --- /dev/null +++ b/VisualRobot/configmanager.cpp @@ -0,0 +1,223 @@ +#include "configmanager.h" + +// 初始化单例实例 +ConfigManager* ConfigManager::instance_ = nullptr; + +ConfigManager::ConfigManager(QObject *parent) + : QObject(parent) + , currentConfigName_("") +{ +} + +ConfigManager::~ConfigManager() +{ +} + +ConfigManager* ConfigManager::instance() +{ + if (!instance_) + { + instance_ = new ConfigManager(); + } + return instance_; +} + +bool ConfigManager::init(const QString& configFilePath) +{ + QString filePath = configFilePath; + + // 如果没有提供文件路径,使用默认路径 + if (filePath.isEmpty()) + { + // 尝试从应用程序目录获取配置文件 + filePath = QDir::currentPath() + "/hardware_config.json"; + + // 如果不存在,尝试从资源文件获取 + if (!QFile::exists(filePath)) + { + filePath = ":/hardware_config.json"; + } + } + + qDebug() << "Loading config file:" << filePath; + + // 解析配置文件 + if (!parseConfigFile(filePath)) + { + qWarning() << "Failed to parse config file:" << filePath; + return false; + } + + // 加载默认配置 + QString defaultConfig = allConfigs_.value("default_config").toString(); + if (defaultConfig.isEmpty()) + { + qWarning() << "No default config specified in config file"; + return false; + } + + return loadHardwareConfig(defaultConfig); +} + +bool ConfigManager::parseConfigFile(const QString& filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + qWarning() << "Failed to open config file:" << filePath; + return false; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + if (doc.isNull() || !doc.isObject()) + { + qWarning() << "Invalid JSON format in config file:" << filePath; + return false; + } + + allConfigs_ = doc.object(); + return true; +} + +bool ConfigManager::loadHardwareConfig(const QString& configName) +{ + QJsonObject hardwareConfigs = allConfigs_.value("hardware_configs").toObject(); + if (hardwareConfigs.isEmpty()) + { + qWarning() << "No hardware configs found in config file"; + return false; + } + + QJsonObject config = hardwareConfigs.value(configName).toObject(); + if (config.isEmpty()) + { + qWarning() << "Hardware config not found:" << configName; + return false; + } + + currentConfigName_ = configName; + currentConfig_ = config; + + qDebug() << "Loaded hardware config:" << configName; + return true; +} + +QString ConfigManager::getCurrentConfigName() const +{ + return currentConfigName_; +} + +QStringList ConfigManager::getAvailableConfigs() const +{ + QJsonObject hardwareConfigs = allConfigs_.value("hardware_configs").toObject(); + return hardwareConfigs.keys(); +} + +QString ConfigManager::getDependencyIncludePath(const QString& depName) const +{ + QJsonObject deps = currentConfig_.value("dependencies").toObject(); + QJsonObject dep = deps.value(depName).toObject(); + return dep.value("include_path").toString(); +} + +QString ConfigManager::getDependencyLibPath(const QString& depName) const +{ + QJsonObject deps = currentConfig_.value("dependencies").toObject(); + QJsonObject dep = deps.value(depName).toObject(); + return dep.value("lib_path").toString(); +} + +QStringList ConfigManager::getDependencyLibs(const QString& depName) const +{ + QStringList libs; + QJsonObject deps = currentConfig_.value("dependencies").toObject(); + QJsonObject dep = deps.value(depName).toObject(); + QJsonArray libArray = dep.value("libs").toArray(); + + for (const QJsonValue& lib : libArray) + { + libs << lib.toString(); + } + + return libs; +} + +bool ConfigManager::isAcceleratorEnabled(const QString& accName) const +{ + QJsonObject accs = currentConfig_.value("accelerators").toObject(); + return accs.value(accName).toBool(false); +} + +QString ConfigManager::getModelPath() const +{ + QJsonObject paths = currentConfig_.value("paths").toObject(); + return paths.value("models").toString("../models"); +} + +QString ConfigManager::getLabelPath() const +{ + QJsonObject paths = currentConfig_.value("paths").toObject(); + return paths.value("labels").toString("../Data/Labels"); +} + +QString ConfigManager::getImagePath() const +{ + QJsonObject paths = currentConfig_.value("paths").toObject(); + return paths.value("images").toString("../Img"); +} + +int ConfigManager::getIntraOpNumThreads() const +{ + QJsonObject opt = currentConfig_.value("optimization").toObject(); + return opt.value("intra_op_num_threads").toInt(4); +} + +int ConfigManager::getInterOpNumThreads() const +{ + QJsonObject opt = currentConfig_.value("optimization").toObject(); + return opt.value("inter_op_num_threads").toInt(1); +} + +QString ConfigManager::getGraphOptimizationLevel() const +{ + QJsonObject opt = currentConfig_.value("optimization").toObject(); + return opt.value("graph_optimization_level").toString("ORT_ENABLE_EXTENDED"); +} + +QString ConfigManager::getExecutionMode() const +{ + QJsonObject opt = currentConfig_.value("optimization").toObject(); + return opt.value("execution_mode").toString("ORT_SEQUENTIAL"); +} + +bool ConfigManager::getEnableCpuMemArena() const +{ + QJsonObject opt = currentConfig_.value("optimization").toObject(); + return opt.value("enable_cpu_mem_arena").toBool(true); +} + +bool ConfigManager::getEnableMemPattern() const +{ + QJsonObject opt = currentConfig_.value("optimization").toObject(); + return opt.value("enable_mem_pattern").toBool(true); +} + +QString ConfigManager::getHardwareName() const +{ + return currentConfig_.value("name").toString(); +} + +QString ConfigManager::getHardwareModel() const +{ + return currentConfig_.value("model").toString(); +} + +QString ConfigManager::getHardwareSystem() const +{ + return currentConfig_.value("system").toString(); +} + +QString ConfigManager::getHardwareArchitecture() const +{ + return currentConfig_.value("architecture").toString(); +} \ No newline at end of file diff --git a/VisualRobot/configmanager.h b/VisualRobot/configmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..21bcc38ce517b7cb3b801d8d80851113a5e1b400 --- /dev/null +++ b/VisualRobot/configmanager.h @@ -0,0 +1,75 @@ +#ifndef CONFIGMANAGER_H +#define CONFIGMANAGER_H + +#include +#include +#include +#include +#include +#include + +class ConfigManager : public QObject +{ + Q_OBJECT +public: + explicit ConfigManager(QObject *parent = nullptr); + ~ConfigManager(); + + // 初始化配置管理器 + bool init(const QString& configFilePath = ""); + + // 加载指定硬件配置 + bool loadHardwareConfig(const QString& configName); + + // 获取当前硬件配置名称 + QString getCurrentConfigName() const; + + // 获取所有可用的硬件配置名称 + QStringList getAvailableConfigs() const; + + // 获取依赖库信息 + QString getDependencyIncludePath(const QString& depName) const; + QString getDependencyLibPath(const QString& depName) const; + QStringList getDependencyLibs(const QString& depName) const; + + // 获取加速选项 + bool isAcceleratorEnabled(const QString& accName) const; + + // 获取路径配置 + QString getModelPath() const; + QString getLabelPath() const; + QString getImagePath() const; + + // 获取优化参数 + int getIntraOpNumThreads() const; + int getInterOpNumThreads() const; + QString getGraphOptimizationLevel() const; + QString getExecutionMode() const; + bool getEnableCpuMemArena() const; + bool getEnableMemPattern() const; + + // 获取硬件信息 + QString getHardwareName() const; + QString getHardwareModel() const; + QString getHardwareSystem() const; + QString getHardwareArchitecture() const; + + // 静态方法:获取单例实例 + static ConfigManager* instance(); + +private: + // 解析配置文件 + bool parseConfigFile(const QString& filePath); + + // 当前配置 + QString currentConfigName_; + QJsonObject currentConfig_; + + // 所有配置 + QJsonObject allConfigs_; + + // 单例实例 + static ConfigManager* instance_; +}; + +#endif // CONFIGMANAGER_H \ No newline at end of file diff --git a/VisualRobot/hardware_config.json b/VisualRobot/hardware_config.json new file mode 100644 index 0000000000000000000000000000000000000000..fdfac9cfe980ff68d7c1a06baa52d565ce1aafe5 --- /dev/null +++ b/VisualRobot/hardware_config.json @@ -0,0 +1,138 @@ +{ + "hardware_configs": { + "orangepi5_rk3588s": { + "name": "OrangePi 5", + "model": "RK3588S", + "system": "Linux", + "architecture": "aarch64", + "dependencies": { + "onnxruntime": { + "include_path": "/home/orangepi/Desktop/VisualRobot_Local/onnxruntime-linux-aarch64-1.23.2/include", + "lib_path": "/home/orangepi/Desktop/VisualRobot_Local/onnxruntime-linux-aarch64-1.23.2/lib", + "libs": ["onnxruntime"] + }, + "opencv": { + "include_path": "/usr/local/include/opencv4", + "lib_path": "/usr/local/lib", + "libs": ["opencv_calib3d", "opencv_core", "opencv_dnn", "opencv_features2d", "opencv_flann", "opencv_gapi", "opencv_highgui", "opencv_imgcodecs", "opencv_imgproc", "opencv_ml", "opencv_objdetect", "opencv_photo", "opencv_stitching", "opencv_video", "opencv_videoio"] + }, + "mvs": { + "include_path": "/opt/MVS/include", + "lib_path": "/opt/MVS/lib/aarch64", + "libs": ["MvCameraControl", "MvCameraControlWrapper", "MVGigEVisionSDK", "MvUsb3vTL"] + }, + "opencl": { + "include_path": "/usr/include", + "lib_path": "/usr/lib/aarch64-linux-gnu", + "libs": ["mali", "OpenCL"] + } + }, + "accelerators": { + "opencl": true, + "cuda": false, + "tensorrt": false + }, + "paths": { + "models": "../models", + "labels": "../Data/Labels", + "images": "../Img" + }, + "optimization": { + "intra_op_num_threads": 4, + "inter_op_num_threads": 1, + "graph_optimization_level": "ORT_ENABLE_EXTENDED", + "execution_mode": "ORT_SEQUENTIAL", + "enable_cpu_mem_arena": true, + "enable_mem_pattern": true + } + }, + "raspberrypi4": { + "name": "Raspberry Pi 4", + "model": "BCM2711", + "system": "Linux", + "architecture": "aarch64", + "dependencies": { + "onnxruntime": { + "include_path": "/home/pi/onnxruntime-linux-aarch64-1.23.2/include", + "lib_path": "/home/pi/onnxruntime-linux-aarch64-1.23.2/lib", + "libs": ["onnxruntime"] + }, + "opencv": { + "include_path": "/usr/local/include/opencv4", + "lib_path": "/usr/local/lib", + "libs": ["opencv_calib3d", "opencv_core", "opencv_dnn", "opencv_features2d", "opencv_flann", "opencv_gapi", "opencv_highgui", "opencv_imgcodecs", "opencv_imgproc", "opencv_ml", "opencv_objdetect", "opencv_photo", "opencv_stitching", "opencv_video", "opencv_videoio"] + }, + "mvs": { + "include_path": "/opt/MVS/include", + "lib_path": "/opt/MVS/lib/aarch64", + "libs": ["MvCameraControl", "MvCameraControlWrapper", "MVGigEVisionSDK", "MvUsb3vTL"] + } + }, + "accelerators": { + "opencl": false, + "cuda": false, + "tensorrt": false + }, + "paths": { + "models": "../models", + "labels": "../Data/Labels", + "images": "../Img" + }, + "optimization": { + "intra_op_num_threads": 4, + "inter_op_num_threads": 1, + "graph_optimization_level": "ORT_ENABLE_BASIC", + "execution_mode": "ORT_SEQUENTIAL", + "enable_cpu_mem_arena": false, + "enable_mem_pattern": true + } + }, + "x86_64_pc": { + "name": "x86_64 PC", + "model": "Generic", + "system": "Linux", + "architecture": "x86_64", + "dependencies": { + "onnxruntime": { + "include_path": "/usr/local/include/onnxruntime", + "lib_path": "/usr/local/lib", + "libs": ["onnxruntime"] + }, + "opencv": { + "include_path": "/usr/local/include/opencv4", + "lib_path": "/usr/local/lib", + "libs": ["opencv_calib3d", "opencv_core", "opencv_dnn", "opencv_features2d", "opencv_flann", "opencv_gapi", "opencv_highgui", "opencv_imgcodecs", "opencv_imgproc", "opencv_ml", "opencv_objdetect", "opencv_photo", "opencv_stitching", "opencv_video", "opencv_videoio"] + }, + "mvs": { + "include_path": "/opt/MVS/include", + "lib_path": "/opt/MVS/lib/x86_64", + "libs": ["MvCameraControl", "MvCameraControlWrapper", "MVGigEVisionSDK", "MvUsb3vTL"] + }, + "opencl": { + "include_path": "/usr/include", + "lib_path": "/usr/lib/x86_64-linux-gnu", + "libs": ["OpenCL"] + } + }, + "accelerators": { + "opencl": true, + "cuda": true, + "tensorrt": true + }, + "paths": { + "models": "../models", + "labels": "../Data/Labels", + "images": "../Img" + }, + "optimization": { + "intra_op_num_threads": 8, + "inter_op_num_threads": 2, + "graph_optimization_level": "ORT_ENABLE_ALL", + "execution_mode": "ORT_PARALLEL", + "enable_cpu_mem_arena": true, + "enable_mem_pattern": true + } + } + }, + "default_config": "orangepi5_rk3588s" +} \ No newline at end of file diff --git a/VisualRobot/hardware_config.qrc b/VisualRobot/hardware_config.qrc new file mode 100644 index 0000000000000000000000000000000000000000..97eb1d5f5c0a73db2921f644a302b6126272ccd3 --- /dev/null +++ b/VisualRobot/hardware_config.qrc @@ -0,0 +1,6 @@ + + + + hardware_config.json + + \ No newline at end of file diff --git a/VisualRobot/main.cpp b/VisualRobot/main.cpp index 70e99c84ea75c53cebc944475e755cfb4e63c97d..67f35fdb7920e3fa011f020a2582ddf440f0e638 100644 --- a/VisualRobot/main.cpp +++ b/VisualRobot/main.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include "featureDetect.h" +#include "configmanager.h" #include #include #include @@ -24,6 +25,14 @@ int main(int argc, char *argv[]) a.installTranslator(&translator); } + // 初始化配置管理器 + if (!ConfigManager::instance()->init()) + { + qCritical() << "Failed to initialize config manager!"; + return -1; + } + qDebug() << "Config manager initialized successfully. Current config:" << ConfigManager::instance()->getCurrentConfigName(); + // 优先从资源加载样式表(打包情况),若资源不可用则回退到可执行目录下的 style.qss 文件 QString resourcePath = ":/style/style.qss"; bool loaded = false; diff --git a/VisualRobot_OpenCL_Optimization_Plan.md b/VisualRobot_OpenCL_Optimization_Plan.md deleted file mode 100644 index 75cf865d23f35a69d80e4372aacf52bfc01c3468..0000000000000000000000000000000000000000 --- a/VisualRobot_OpenCL_Optimization_Plan.md +++ /dev/null @@ -1,243 +0,0 @@ -# VisualRobot OpenCL加速优化计划 - -## 1. 项目概述 - -本计划针对VisualRobot项目中的计算密集型图像处理和计算机视觉算法,利用RK3588平台上的Mali-G610 GPU和OpenCL技术进行加速优化。通过将CPU密集型任务迁移到GPU执行,提高系统整体性能和实时性。 - -## 2. 优化目标 - -- 提高图像处理和特征检测的执行速度 -- 降低CPU使用率,释放CPU资源用于其他任务 -- 保持算法结果的准确性和稳定性 -- 实现GPU加速的透明化调用 - -## 3. 适合OpenCL加速的模块分析 - -### 3.1 DIP模块 - -**核心功能**:数字图像处理,包括图像预处理、形状检测、尺寸测量等 - -**优化点**: - -| 函数/操作 | 计算复杂度 | 加速潜力 | 优化策略 | -|-----------|------------|----------|----------| -| 图像灰度化 (cvtColor) | 低 | 中 | OpenCL内核实现并行像素转换 | -| 高斯模糊 (GaussianBlur) | 中 | 高 | 利用OpenCL并行计算每个像素的模糊值 | -| 双边滤波 (bilateralFilter) | 高 | 高 | OpenCL并行实现双边滤波算法 | -| 阈值处理 (threshold) | 低 | 中 | OpenCL并行像素阈值化 | -| 形态学操作 (morphologyEx) | 中 | 高 | OpenCL并行实现膨胀/腐蚀操作 | -| Canny边缘检测 | 高 | 高 | OpenCL实现完整的Canny边缘检测流水线 | -| Hough圆变换 (HoughCircles) | 很高 | 很高 | OpenCL并行实现Hough圆检测 | -| 轮廓提取 (findContours) | 高 | 中 | 部分步骤可并行化 | -| 亚像素角点优化 (cornerSubPix) | 中 | 中 | OpenCL并行优化角点坐标 | - -**预期加速比**:2-5倍 - -### 3.2 DataProcessor模块 - -**核心功能**:图像预处理、特征提取、数据增强 - -**优化点**: - -| 函数/操作 | 计算复杂度 | 加速潜力 | 优化策略 | -|-----------|------------|----------|----------| -| 图像标准化 (StandardizeImage) | 中 | 中 | OpenCL并行实现图像标准化 | -| 特征提取 (SIFT/ORB/AKAZE) | 很高 | 很高 | 利用OpenCL加速特征检测和描述符计算 | -| HOG特征提取 (ExtractHOGFeatures) | 高 | 高 | OpenCL并行实现HOG特征计算 | -| 图像旋转/翻转/裁剪 | 中 | 中 | OpenCL并行实现几何变换 | -| 高斯噪声添加 (AddNoise) | 中 | 中 | OpenCL并行生成和添加噪声 | - -**预期加速比**:3-8倍 - -### 3.3 featureDetect模块 - -**核心功能**:特征匹配、筛选和几何验证 - -**优化点**: - -| 函数/操作 | 计算复杂度 | 加速潜力 | 优化策略 | -|-----------|------------|----------|----------| -| 特征匹配 (knnMatch) | 高 | 中 | 部分匹配计算可并行化 | -| 匹配筛选 (FilterMatches) | 中 | 中 | OpenCL并行实现匹配点筛选 | -| RANSAC几何验证 | 高 | 中 | 并行RANSAC实现 | - -**预期加速比**:1.5-3倍 - -### 3.4 YOLOProcessorORT模块 - -**核心功能**:基于ONNX Runtime的YOLO目标检测,包括模型推理、图像预处理和后处理 - -**优化点**: - -| 函数/操作 | 计算复杂度 | 加速潜力 | 优化策略 | -|-----------|------------|----------|----------| -| 图像预处理 (letterbox缩放、颜色转换、归一化) | 中 | 高 | 使用OpenCV UMat实现透明OpenCL加速 | -| ONNX模型推理 | 很高 | 很高 | 启用ONNX Runtime的OpenCL执行提供者 | -| 置信度筛选 | 中 | 中 | OpenCL并行实现置信度过滤 | -| NMS (非极大值抑制) | 高 | 中高 | OpenCL加速NMS算法 | -| 坐标映射 (letterbox逆变换) | 中 | 中 | OpenCL并行计算坐标映射 | - -**预期加速比**:2-6倍 - -## 4. 优化实现方案 - -### 4.1 技术方案 - -- **OpenCL版本**:OpenCL 3.0 -- **开发模式**: - - 利用OpenCV内置的OpenCL加速(透明加速) - - 自定义OpenCL内核实现特定算法加速 - - 混合模式:结合OpenCV的OpenCL支持和自定义内核 - -### 4.2 实现步骤 - -#### 4.2.1 阶段1:OpenCV内置OpenCL加速启用 - -1. **编译配置**:确保OpenCV编译时启用了`WITH_OPENCL`选项 -2. **代码修改**: - ```cpp - // 在程序初始化时启用OpenCV的OpenCL支持 - cv::ocl::setUseOpenCL(true); - - // 使用UMat代替Mat进行图像处理 - cv::UMat src, dst; - cv::imread("image.jpg").copyTo(src); - cv::GaussianBlur(src, dst, cv::Size(5,5), 0); // 自动使用OpenCL加速 - ``` -3. **验证**:使用`cv::ocl::useOpenCL()`检查OpenCL是否启用成功 - -#### 4.2.2 阶段2:自定义OpenCL内核加速 - -对于OpenCV未优化或优化效果不佳的算法,实现自定义OpenCL内核: - -1. **内核编写**:为目标算法编写OpenCL内核代码 -2. **内存管理**:优化CPU-GPU内存传输 -3. **并行调度**:根据算法特点设计最优的工作组大小和网格大小 -4. **性能调优**:优化内存访问模式,减少全局内存访问 - -#### 4.2.3 阶段3:模块级优化实现 - -**DIP模块优化**: - -1. 修改`CalculateLength`和`CalculateLengthMultiTarget`函数: - - 将输入图像转换为`cv::UMat` - - 使用OpenCV的OpenCL加速版本函数 - - 对自定义算法实现OpenCL内核 - -2. 优化`GetCoordsOpenCV`函数: - - 使用OpenCL加速Hough圆变换 - - 并行实现圆心亚像素优化 - -3. 优化`DetectRectangleOpenCV`函数: - - 使用OpenCL加速Canny边缘检测 - - 并行实现轮廓提取和过滤 - -**DataProcessor模块优化**: - -1. 修改`DetectKeypoints`函数: - - 使用OpenCV的OpenCL加速版本特征提取器 - - 或实现自定义OpenCL特征提取内核 - -2. 优化`ExtractHOGFeatures`函数: - - 实现OpenCL并行HOG特征计算 - -3. 优化数据增强函数: - - 并行实现图像旋转、翻转、裁剪等操作 - -**featureDetect模块优化**: - -1. 修改特征匹配和筛选函数: - - 使用OpenCL加速匹配计算 - - 并行实现匹配点筛选 - -2. 优化RANSAC几何验证: - - 实现并行RANSAC算法 - -**YOLOProcessorORT模块优化**: - -1. 模型初始化优化: - - 启用ONNX Runtime的OpenCL执行提供者 - - 配置OpenCL设备和参数(设备ID、内存限制等) - -2. 图像预处理优化: - - 使用OpenCV的UMat实现透明OpenCL加速 - - 优化数据格式转换(HWC→CHW) - - 合并预处理步骤,减少内存访问 - -3. 后处理优化: - - OpenCL并行实现置信度过滤 - - OpenCL加速NMS算法 - - 并行化坐标映射计算 - -4. 内存管理优化: - - 减少CPU-GPU数据传输次数 - - 使用ONNX Runtime的内存池 - - 预分配内存,避免频繁内存分配 - -## 5. 性能评估方案 - -### 5.1 测试环境 - -- 硬件:RK3588开发板(4核Cortex-A76 + 4核Cortex-A55 + Mali-G610 GPU) -- 软件:Ubuntu 22.04,OpenCL 3.0,OpenCV 4.5+ -- 测试数据集:VisualRobot项目中的测试图像集 - -### 5.2 评估指标 - -- 执行时间:优化前后的函数执行时间对比 -- 加速比:优化前时间 / 优化后时间 -- CPU使用率:优化前后的CPU占用率对比 -- 内存占用:GPU内存使用情况 -- 结果准确性:优化前后算法结果的一致性 - -### 5.3 测试方法 - -1. 单函数性能测试:针对每个优化函数进行独立测试 -2. 端到端性能测试:测试完整的图像处理流水线 -3. 并发性能测试:测试多任务并发执行时的性能 -4. 稳定性测试:长时间运行测试,确保结果稳定 - -## 6. 实施计划 - -| 阶段 | 时间 | 任务 | 负责人 | -|------|------|------|--------| -| 阶段1 | 第1-2周 | 环境搭建,OpenCV OpenCL支持验证 | 开发人员 | -| 阶段2 | 第3-4周 | DIP模块OpenCV内置OpenCL加速实现 | 开发人员 | -| 阶段3 | 第5-6周 | DataProcessor模块OpenCL加速实现 | 开发人员 | -| 阶段4 | 第7-8周 | featureDetect模块OpenCL加速实现 | 开发人员 | -| 阶段4 | 第7-8周 | YOLOProcessorORT模块ONNX Runtime OpenCL加速 | 开发人员 | -| 阶段5 | 第9-10周 | 自定义OpenCL内核开发和优化 | 开发人员 | -| 阶段6 | 第11-12周 | 性能测试和调优 | 测试人员 | -| 阶段7 | 第13周 | 文档编写和项目总结 | 开发人员 | - -## 7. 风险评估 - -| 风险 | 影响 | 缓解措施 | -|------|------|----------| -| OpenCL驱动兼容性问题 | 加速效果不佳或无法运行 | 确保使用最新的Mali驱动,进行充分测试 | -| 内存传输开销过大 | 抵消GPU加速效果 | 优化内存管理,减少CPU-GPU数据传输次数 | -| 算法并行化难度高 | 部分算法难以并行化 | 针对不同算法采用不同优化策略,优先优化并行性好的算法 | -| 结果精度损失 | 算法结果不准确 | 确保GPU实现与CPU实现的结果一致性,进行严格验证 | - -## 8. 预期效果 - -通过本优化计划的实施,预计可以实现以下效果: - -- 图像处理速度提升2-5倍 -- 特征提取和匹配速度提升3-8倍 -- YOLO目标检测速度提升2-6倍 -- CPU使用率降低30%-50% -- 系统整体实时性显著提高 -- 为后续功能扩展提供更强的计算能力支持 - -## 9. 后续工作 - -- 持续优化现有算法的OpenCL实现 -- 为新增功能提供OpenCL加速支持 -- 研究更高效的GPU内存管理策略 -- 探索异构计算架构,结合CPU和GPU优势 -- 优化多GPU协同工作(如果硬件支持) - -## 10. 结论 - -OpenCL加速是提高VisualRobot系统性能的有效途径。通过合理的优化策略和实施计划,可以充分发挥RK3588平台上Mali-G610 GPU的计算能力,显著提高系统的图像处理和计算机视觉算法性能。本计划为VisualRobot项目的OpenCL加速提供了详细的指导和实施路径。 \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100644 index 0000000000000000000000000000000000000000..bad0eb9b13116a3c1ab866dcf0f9acda9d429f45 --- /dev/null +++ b/install.sh @@ -0,0 +1,275 @@ +#!/bin/bash + +# VisualRobot 安装脚本 +# 支持多种硬件平台部署 + +set -e + +# 默认配置 +DEFAULT_CONFIG="orangepi5_rk3588s" +INSTALL_DIR="/opt/VisualRobot" +CONFIG_FILE="hardware_config.json" + +# 显示帮助信息 +show_help() { + echo "VisualRobot 安装脚本" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " -h, --help 显示帮助信息" + echo " -c, --config CONFIG 指定硬件配置名称 (默认: $DEFAULT_CONFIG)" + echo " -d, --dir DIR 指定安装目录 (默认: $INSTALL_DIR)" + echo " -v, --verbose 显示详细安装过程" + echo "" + echo "可用的硬件配置:" + echo " orangepi5_rk3588s OrangePi 5 (RK3588S)" + echo " raspberrypi4 Raspberry Pi 4 (BCM2711)" + echo " x86_64_pc x86_64 PC" + echo "" +} + +# 解析命令行参数 +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -c|--config) + CONFIG_NAME="$2" + shift 2 + ;; + -d|--dir) + INSTALL_DIR="$2" + shift 2 + ;; + -v|--verbose) + VERBOSE=true + shift 1 + ;; + *) + echo "未知选项: $1" + show_help + exit 1 + ;; + esac + done + + # 设置默认值 + CONFIG_NAME=${CONFIG_NAME:-$DEFAULT_CONFIG} + VERBOSE=${VERBOSE:-false} +} + +# 检查依赖 +check_dependencies() { + echo "检查依赖..." + + # 检查Qt运行时 + if ! command -v qmake &> /dev/null; then + echo "错误: 未找到 qmake,请确保已安装Qt开发环境" + exit 1 + fi + + # 检查OpenCV + if ! pkg-config --libs opencv4 &> /dev/null; then + echo "警告: 未找到OpenCV 4,可能需要手动安装" + fi + + # 检查ONNX Runtime + if ! ldconfig -p | grep -q libonnxruntime; then + echo "警告: 未找到ONNX Runtime,可能需要手动安装" + fi +} + +# 安装应用程序 +install_app() { + echo "开始安装 VisualRobot 到 $INSTALL_DIR..." + + # 创建安装目录 + sudo mkdir -p $INSTALL_DIR + sudo mkdir -p $INSTALL_DIR/bin + sudo mkdir -p $INSTALL_DIR/models + sudo mkdir -p $INSTALL_DIR/labels + sudo mkdir -p $INSTALL_DIR/images + + # 复制可执行文件 + echo "复制可执行文件..." + if [ -f "VisualRobot/VisualRobot" ]; then + sudo cp VisualRobot/VisualRobot $INSTALL_DIR/bin/ + elif [ -f "VisualRobot/VisualRobot.exe" ]; then + sudo cp VisualRobot/VisualRobot.exe $INSTALL_DIR/bin/ + else + echo "错误: 未找到可执行文件,请先编译项目" + exit 1 + fi + + # 复制配置文件 + echo "复制配置文件..." + if [ -f "VisualRobot/$CONFIG_FILE" ]; then + sudo cp VisualRobot/$CONFIG_FILE $INSTALL_DIR/ + else + echo "错误: 未找到配置文件 $CONFIG_FILE" + exit 1 + fi + + # 复制模型文件 + echo "复制模型文件..." + if [ -d "Models" ]; then + sudo cp -r Models/* $INSTALL_DIR/models/ + else + echo "警告: 未找到模型目录,跳过模型复制" + fi + + # 复制标签文件 + echo "复制标签文件..." + if [ -d "Labels" ]; then + sudo cp -r Labels/* $INSTALL_DIR/labels/ + else + echo "警告: 未找到标签目录,跳过标签复制" + fi + + # 复制示例图像 + echo "复制示例图像..." + if [ -d "Img" ]; then + sudo cp -r Img/* $INSTALL_DIR/images/ + else + echo "警告: 未找到图像目录,跳过图像复制" + fi + + # 创建启动脚本 + create_start_script + + # 设置权限 + sudo chmod +x $INSTALL_DIR/bin/* + sudo chmod +x $INSTALL_DIR/start.sh + + echo "安装完成!" + echo "" + echo "使用以下命令启动应用程序:" + echo " $INSTALL_DIR/start.sh" + echo "" + echo "或使用指定配置启动:" + echo " $INSTALL_DIR/start.sh -c " +} + +# 创建启动脚本 +create_start_script() { + cat > start.sh << EOF +#!/bin/bash + +# VisualRobot 启动脚本 +# 支持多种硬件平台 + +set -e + +# 默认配置 +DEFAULT_CONFIG="$DEFAULT_CONFIG" +INSTALL_DIR="$INSTALL_DIR" +CONFIG_FILE="$CONFIG_FILE" + +# 显示帮助信息 +show_help() { + echo "VisualRobot 启动脚本" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " -h, --help 显示帮助信息" + echo " -c, --config CONFIG 指定硬件配置名称 (默认: $DEFAULT_CONFIG)" + echo " -v, --verbose 显示详细启动过程" + echo "" + echo "可用的硬件配置:" + echo " orangepi5_rk3588s OrangePi 5 (RK3588S)" + echo " raspberrypi4 Raspberry Pi 4 (BCM2711)" + echo " x86_64_pc x86_64 PC" + echo "" +} + +# 解析命令行参数 +parse_args() { + while [[ \$# -gt 0 ]]; do + case \$1 in + -h|--help) + show_help + exit 0 + ;; + -c|--config) + CONFIG_NAME="\$2" + shift 2 + ;; + -v|--verbose) + VERBOSE=true + shift 1 + ;; + *) + echo "未知选项: \$1" + show_help + exit 1 + ;; + esac + done + + # 设置默认值 + CONFIG_NAME=\${CONFIG_NAME:-$DEFAULT_CONFIG} + VERBOSE=\${VERBOSE:-false} +} + +# 主函数 +main() { + parse_args "\$@" + + echo "启动 VisualRobot,使用配置: \$CONFIG_NAME" + + # 切换到安装目录 + cd \$INSTALL_DIR + + # 设置环境变量 + export QT_QPA_PLATFORM=xcb + export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/lib:/opt/MVS/lib/\$(uname -m) + + # 启动应用程序 + if [ -f "bin/VisualRobot" ]; then + bin/VisualRobot + elif [ -f "bin/VisualRobot.exe" ]; then + wine bin/VisualRobot.exe + else + echo "错误: 未找到可执行文件" + exit 1 + fi +} + +# 执行主函数 +main "\$@" +EOF + + sudo mv start.sh $INSTALL_DIR/ +} + +# 主函数 +main() { + parse_args "$@" + + if [ "$VERBOSE" = true ]; then + set -x + fi + + check_dependencies + install_app + + if [ "$VERBOSE" = true ]; then + set +x + fi + + echo "" + echo "=============================================" + echo "VisualRobot 安装成功!" + echo "安装目录: $INSTALL_DIR" + echo "当前配置: $CONFIG_NAME" + echo "=============================================" + echo "" + echo "启动命令: $INSTALL_DIR/start.sh" + echo "" +} + +# 执行主函数 +main "$@" \ No newline at end of file