• 【失败经验分享】android下使用支持opencl的cv::dft()


    1.使用了UMat,但是并未使用GPU计算

    cv::dft()函数的定义是:

    void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows )
    

    dft()函数中这样调用opencl的版本:

    #ifdef HAVE_OPENCL
        CV_OCL_RUN(_dst.isUMat() && _src0.dims() <= 2,
                   ocl_dft(_src0, _dst, flags, nonzero_rows))
    #endif
    

    然后程序在ocl_dft()函数的如下位置返回false:

        // if is not a multiplication of prime numbers { 2, 3, 5 }
        if (ssize.area() != getOptimalDFTSize(ssize.area()))
            return false;
    

    于是突然领悟了:为什么opencl版本调用的时候比CPU版本还要更慢?因为程序并未返回内部的状态,如果opencl调用失败,就会转到CPU版本去计算。但是传入的数据是UMat,导致CPU版本还要从设备内存下载数据到主机内存,必然更慢。

    然后找到了这篇帖子解决了上面条件判断返回false的问题:
    OpenCV离散傅里叶变换
    核心代码如下:

    Mat padded;                            //expand input image to optimal size
    int m = getOptimalDFTSize( I.rows );
    int n = getOptimalDFTSize( I.cols ); // on the border add zero values
    copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));
    
    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexI;
    merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
    
    dft(complexI, complexI);            // this way the result may fit in the source matrix
    

    2.opencl核函数编译失败

    继续往后执行,debug版本opencv输出以下信息:

    [ INFO:0] Specify OPENCV_OPENCL_CACHE_DIR configuration parameter to enable OpenCL cache
    OpenCL program build log: core/fft
    Status -11: CL_BUILD_PROGRAM_FAILURE
    -D LOCAL_SIZE=36 -D kercn=12 -D FT=float -D CT=float2 -D RADIX_PROCESS=fft_radix4_B3(smem,twiddles+0,ind,1,9);fft_radix3_B4(smem,twiddles+3,ind,4,12);fft_radix3_B4(smem,twiddles+11,ind,12,12); -D COMPLEX_INPUT -D COMPLEX_OUTPUT
    BC-src-code:429:12: error: '__local' can only appear in __kernel functions at function scope
     __local CT smem[LOCAL_SIZE];
                ^
    BC-src-code:499:12: error: '__local' can only appear in __kernel functions at function scope
     __local CT smem[LOCAL_SIZE];
                ^
    BC-src-code:558:12: error: '__local' can only appear in __kernel functions at function scope
     __local CT smem[LOCAL_SIZE];
                ^
    BC-src-code:644:12: error: '__local' can only appear in __kernel functions at function scope
     __local CT smem[LOCAL_SIZE];
                ^
    4 diagnostic(s) generated.
    

    出错的代码是:
    bool enqueueTransform(InputArray _src, OutputArray _dst, int num_dfts, int flags, int fftType, bool rows = true) const

            ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, options);
            if (k.empty())
                return false;
    

    我的android手机是opencl 2.0版本,暂不清楚opencv开发者所用的fft.cl对应的opencl版本是什么。由此说明之前并没有人在android下去做opencl版本的dft()函数的兼容。

    下一步是认真分析fft.cl的语法,想办法在android下可以编译通过。

    ===================================
    2019-06-26 20:48补充:
    核函数这里解决了:
    '__local' can only appear in __kernel functions at function scope
    声明为__local的变量,只能定义在函数的顶级作用域,例如写在if()里面是不行的。
    因此,把所有if, for 等括号里面的__local变量定义放在函数开始处就解决了。
    opencv中的ocl_dft()终于跑起来了!

  • 相关阅读:
    从命令行运行postman脚本
    Postman简单的接口测试
    请写出正则表达式(regex),取得下列黄色部分的字符串 TEL: 02-236-9655/9659 FAX:02-236-9654 (黄色部分即02-236-9655/9659 ) ( 测试面试题)
    okhttp 的使用
    GridView的簡單使用
    Fragment 中 ListView绑定ContextMenu
    charles的使用
    selenium元素定位(Java)
    App间相互跳转及图片分享
    微信模板消息的使用
  • 原文地址:https://www.cnblogs.com/ahfuzhang/p/11090544.html
Copyright © 2020-2023  润新知