OpenCV的加速

  • OpenCV基于OpenCL进行加速

在opencv2.x版本中,ocl作为一个专门的模块,里边重新构建了一系列可以加速的算子,包括:feature2d。调用方法是基于宏指令#ifdef HAVE_OPENCL来查看是否调用ocl中对应的算法分支,这种方法不是特别方便,造成了用户代码冗余。

在opencv3.x以后的版本中,ocl模块进行了重构,无需专门调用ocl模块中的算法,也无需定义HAVE_OPENCL,而只需要把mat输入改成Umat,即可自动内底层使用opencl的优化,而在opencv源码中看到的#ifdef HAVE_OPENCV则是为了兼容之前opencv2.x版本而存在的,实际上无需考虑。如下是在opencv3.x之下调用的方式:可见只需要把mat的声明变成Umat的声明,然后读取得到的mat转为Umat即可实现加速。

OpenCV的加速_第1张图片

opencv3.x的新接口API底层实现方式

- 首先定义了接口函数cvtColor()

- 在接口函数内部进行判断:是否启动ocl,数据是否为Umat,如果是则直接执行ocl_cvtColor()并返回,而如果不是,则继续往前执行cpu_cvtColor()

OpenCV的加速_第2张图片

 

使用Umat进行加速的流程

- mat转Umat:可以使用um = m.getUmat(),也可以m.copyTo(um)都可以

- Umat转mat:可以使用um.copyTo(m)

- 调用函数:通常无需区分函数是否支持Umat,因为opencv在函数内部都进行了判断,如果是Umat就会制动跳转使用带opencljiasu的函数。

实例:进行边缘检测

void test_ocl_edge()

{

            ocl::setUseOpenCL(true);

            UMat src, bw, blur, edge;

            src = imread("D:\\MyDatasets\\misc\\1.jpg").getUMat(ACCESS_RW);

            cvtColor(src, bw, COLOR_BGR2GRAY);

            GaussianBlur(bw, blur, Size(3, 3), 0);

            Canny(blur, edge, 50, 100, 3);

            imshow("res", edge);

            waitKey(0);

}

 

  • OpenCV基于CUDA进行加速

使用GpuMat进行cuda加速的流程

- mat转GpuMat:使用GpuMat的方法g.upload(host_img)

- GpuMat转mat:使用GpuMat的方法g.download(host_img)

- 使用cuda版本的函数接收GpuMat:cuda版本的函数一般在cuda命名空间,比如cuda::orb,常规版本函数传入GpuMat会报错。

 

注意:不是所有函数都支持GpuMat,只有特定支持GpuMat的函数能够接收GpuMat作为形参,否则就会报错,比如GaussianBlur()就不支持GpuMat,一般支持GpuMat的函数当前都还在cv::cuda命名空间中。从这点说,UmatGpuMat相对更方便,因为即使该函数不支持opencl加速,传入Umat也可以当成常规mat执行运行不会报错,但现阶段GpuMat貌似做不到

(猜测将来opencv有可能会统一用opencl做加速而不是cuda,因为opencl能够支持不同厂家的显卡和加速硬件,所以Umat在实施上更通用,跟mat结构更加深度绑定)

实例:进行高斯模糊

void test_gpu_mat()

{

    Mat img = imread("D:\\MyDatasets\\misc\\1.jpg", 0);

    GpuMat dev_img, dev_res;

    dev_img.upload(img);

    // 高斯柔化,只能用这个函数,不能用GaussianBlur

    auto filter = createGaussianFilter(CV_8UC1, CV_8UC1, Size(3,3), 5);

    filter->apply(dev_img, dev_res);

    Mat res;

    dev_res.download(res);

    imshow("res", res);

    waitKey(0);

}

 

你可能感兴趣的:(CV图像视觉算法)