参考链接
https://dev.t-firefly.com/thread-124629-1-1.html
【RK opencv CPU && GPU】: https://blog.csdn.net/qq_36784503/article/details/130306905
开启 Opencl 加速后,出现问题
当我使用下面代码进行测试时(其实就是使用了 GPU 版的 Opencv进行处理时,开启了 Opencl加速,开启加速后,就出现问题了)
#include <iostream> #include <opencv2/core.hpp> #include <opencv2/core/ocl.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #define IMAGE_PATHNAME "D:\\allike\\Image_20210707220543807.jpg" void calcEdgesCPU() { cv::ocl::setUseOpenCL(false); bool ret1 = cv::ocl::haveOpenCL(); bool ret2 = cv::ocl::useOpenCL(); std::cout << "haveOpenCL:" << ret1 << std::endl; std::cout << "useOpenCL:" << ret2 << std::endl; double start = cv::getTickCount(); cv::Mat cpuGray, cpuBlur, cpuEdges; cv::Mat cpuFrame = cv::imread(IMAGE_PATHNAME); cvtColor(cpuFrame, cpuGray, cv::COLOR_BGR2GRAY); cv::GaussianBlur(cpuGray, cpuBlur, cv::Size(3, 3), 15, 15); cv::Canny(cpuBlur, cpuEdges, 50, 100, 3); // std::vector<cv::Vec3f> cir; // cv::HoughCircles(cpuBlur, cir, cv::HOUGH_GRADIENT_ALT, 1.5, 15, 300, 0.8, 1, 100); std::cout << "CPU cost time:(s)" << ((cv::getTickCount() - start) / cv::getTickFrequency()) << std::endl; } void calcEdgesGPU() { cv::ocl::setUseOpenCL(true); bool ret1 = cv::ocl::haveOpenCL(); bool ret2 = cv::ocl::useOpenCL(); std::cout << "haveOpenCL:" << ret1 << std::endl; std::cout << "useOpenCL:" << ret2 << std::endl; //通过使用UMat对象,OpenCV会自动在支持OpenCL的设备上使用GPU运算,在不支持OpenCL的设备仍然使用CPU运算,这样就避免了程序运行失败,而且统一了接口。 double start = cv::getTickCount(); cv::UMat gpuFrame, gpuGray, gpuBlur, gpuEdges; cv::Mat cpuFrame = cv::imread(IMAGE_PATHNAME); cpuFrame.copyTo(gpuFrame); //Mat与UMat相互转换 cvtColor(gpuFrame, gpuGray, cv::COLOR_BGR2GRAY); cv::GaussianBlur(gpuGray, gpuBlur, cv::Size(3, 3), 15, 15); cv::Canny(gpuBlur, gpuEdges, 50, 100, 3); // std::vector<cv::Vec3f> cir; // cv::HoughCircles(gpuBlur, cir, cv::HOUGH_GRADIENT_ALT, 1.5, 15, 300, 0.8, 1, 100); std::cout << "GPU cost time:(s)" << ((cv::getTickCount() - start) / cv::getTickFrequency()) << std::endl; cv::Mat matResult = gpuEdges.getMat(cv::ACCESS_READ); //Mat与UMat相互转换 } int main(int argc, char *argv[]) { calcEdgesCPU(); calcEdgesGPU(); return 0; }
在函数 calcEdgesGPU 处, 报错了,错误内容如下:
OpenCL program build log: imgproc/color_rgb <u>Status -11: CL_BUILD_PROGRAM_FAILURE</u> -D depth=0 -D scn=3 -D PIX_PER_WI_Y=1 -D dcn=1 -D bidx=0 -D STRIPE_SIZE=1 <built-in>:167:9: error: expected member name or ';' after declaration specifiers int32_t depth; /**< The image depth. */ ~~~~~~~ ^ <built-in>:1:15: note: expanded from here #define depth 0 ^ <built-in>:167:8: error: expected ';' at end of declaration list int32_t depth; /**< The image depth. */ ^ error: Compiler frontend failed (error code 62)
解决方法
参考链接 : https://dev.t-firefly.com/thread-124629-1-1.html
链接中提到了,下面这句报错,其实是告诉我们,在编译Opencv 时, 有个地方编译不通过。
OpenCL program build log: imgproc/color_rgb <u>Status -11: CL_BUILD_PROGRAM_FAILURE</u>
同时有人提到这句话(如下图):
而后又看到了 这篇文章 【RK opencv CPU && GPU】: https://blog.csdn.net/qq_36784503/article/details/130306905
也提到了出现了 错误, 并使用上图的修改方式,但是更简化了一点:
找到 ./opencv/modules/imgproc/src/imgwarp.cpp 文件 的 ocl_remap 函数,找到
buildOptions += format(" -D T=%s -D T1=%s -D cn=%d -D ST=%s -D depth=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn, ocl::typeToStr(sctype), depth);
并修改成下面的样子
buildOptions += format(" -D T=%s -D T1=%s -D cn=%d -D ST=%s -D ocl_depth=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn, ocl::typeToStr(sctype), depth);
但问题在于,他们提到的问题都是有一个共同点
报错信息都是是 :
OpenCL program build log: imgproc/remap Status -11: CL_BUILD_PROGRAM_FAILURE
而我的报错信息:
OpenCL program build log: imgproc/color_rgb Status -11: CL_BUILD_PROGRAM_FAILURE
所以,这个方式自然不能解决我的问题
那么要如何解决 OpenCL program build log: imgproc/color_rgb 这个问题呢?
依葫芦画瓢
找到 ./opencv/modules/imgproc/src/color.hpp 文件的 createKernel 函数, 找到下面这句话
cv::String baseOptions = format("-D depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ", src.depth(), src.channels(), pxPerWIy);
改成下面这样:
cv::String baseOptions = format("-D ocl_m_depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ", src.depth(), src.channels(), pxPerWIy);
重新编译 Opencv ,将 编译好的 Opencv 动态链接库替换成正在使用的 Opencv 即可