Opencv学习笔记 - 关于OpenCV的UMat 类

Posted 坐望云起

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opencv学习笔记 - 关于OpenCV的UMat 类相关的知识,希望对你有一定的参考价值。

         一个统一的抽象 cv::UMat 允许使用 CPU 或 OpenCL 代码实现相同的 API,而无需显式调用 OpenCL 加速版本。UMat类告诉 OpenCV 函数使用特定于 OpenCL 的代码处理图像,如果系统中存在启用 OpenCL 的 GPU(否则自动切换到 CPU)。

        根据 Khronos 小组的说法,  OpenCL™(开放计算语言)是:一种免版税标准,用于不同处理器的跨平台并行编程。OpenCL 极大地提高了众多市场类别中各种应用程序的速度和响应能力,包括游戏和娱乐标题、科学和医疗软件、专业创意工具、视觉处理以及神经网络训练和推理。

        OpenCL(开放计算语言)是一个框架,用于编写跨异构平台执行的程序,包括中央处理单元(CPU)、图形处理单元(GPU)、数字信号处理器(DSP)、现场可编程门阵列(FPGA)和其他处理器或硬件加速器。OpenCL 指定用于对这些设备和应用程序编程接口进行编程的编程语言(基于C99、C++14和C++17 )(API) 来控制平台并在计算设备上执行程序。OpenCL 为使用基于任务和数据的并行性的并行计算提供标准接口。

        OpenCL+C语言计算FFT示例

#include <stdio.h>
#include <time.h>
#include "CL/opencl.h"

#define NUM_ENTRIES 1024

int main() // (int argc, const char* argv[])

	// CONSTANTS
	// The source code of the kernel is represented as a string
	// located inside file: "fft1D_1024_kernel_src.cl". For the details see the next listing.
	const char *KernelSource =
		#include "fft1D_1024_kernel_src.cl"
			;

	// Looking up the available GPUs
	const cl_uint num = 1;
	clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 0, NULL, (cl_uint*)&num);

	cl_device_id devices[1];
	clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, num, devices, NULL);

	// create a compute context with GPU device
	cl_context context = clCreateContextFromType(NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, NULL);

	// create a command queue
	clGetDeviceIDs(NULL, CL_DEVICE_TYPE_DEFAULT, 1, devices, NULL);
	cl_command_queue queue = clCreateCommandQueue(context, devices[0], 0, NULL);

	// allocate the buffer memory objects
	cl_mem memobjs[] =  clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * 2 * NUM_ENTRIES, NULL, NULL),
						 clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * 2 * NUM_ENTRIES, NULL, NULL) ;

	// create the compute program
	// const char* fft1D_1024_kernel_src[1] =   ;
	cl_program program = clCreateProgramWithSource(context, 1, (const char **)& KernelSource, NULL, NULL);

	// build the compute program executable
	clBuildProgram(program, 0, NULL, NULL, NULL, NULL);

	// create the compute kernel
	cl_kernel kernel = clCreateKernel(program, "fft1D_1024", NULL);

	// set the args values

	size_t local_work_size[1] =  256 ;

	clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobjs[0]);
	clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&memobjs[1]);
	clSetKernelArg(kernel, 2, sizeof(float)*(local_work_size[0] + 1) * 16, NULL);
	clSetKernelArg(kernel, 3, sizeof(float)*(local_work_size[0] + 1) * 16, NULL);

	// create N-D range object with work-item dimensions and execute kernel
	size_t global_work_size[1] =  256 ;
	
	global_work_size[0] = NUM_ENTRIES;
	local_work_size[0] = 64; //Nvidia: 192 or 256
	clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_work_size, local_work_size, 0, NULL, NULL);

        OpenCV 从第二版开始就有 OpenCL 实现,但使用它们十分麻烦,需要对您的代码进行大量修改。从 3.0 版本开始,OpenCV 实现了 T-API(Transparent API),为很多“经典”功能增加了硬件加速。从那时起,它就能够自动检测、加载和利用 OpenCL 设备和加速代码。因此,您不需要实现任何 OpenCL 代码,它对用户是“透明的”。

        基于Mat的双边滤波。

void MatProcessing(const std::string& name)
	Mat img,dst;
	img = imread(name.c_str());
	cv::cvtColor(img,img,CV_BGR2GRAY);
	bilateralFilter(img, dst, 0, 10, 3);

        基于UMat的双边滤波。

void UMatProcessing(const std::string& name)
	UMat Uimg, Udst;
	Uimg = imread(name.c_str(), IMREAD_UNCHANGED).getUMat(ACCESS_READ);
	cv::cvtColor(Uimg,Uimg,CV_BGR2GRAY);
	bilateralFilter(Uimg, Udst, 0, 10, 3);

        下面图片转载自网络上,本人并没有进行严谨测试。不过创建了一张12000*12000的图片,也是进行了双边滤波,运行了两次,上面的结果是mat的,下面的结果是umat的,确实快一点,感觉应该是图片越大用Umat优势越明显,这个测试应该和下图的走势相符。 

第一次
DateTime costed for Shuffle function is: 1144.292ms
DateTime costed for Shuffle function is: 936.5605ms

第二次
DateTime costed for Shuffle function is: 1101.805ms
DateTime costed for Shuffle function is: 732.5992ms
Mat 和 UMat 的时间比较

         用英特尔的说法:不要所有地方都使用 cv::UMat 数据类型。可以将 cv::UMat 用于图像,并继续将 cv::Mat 用于其他较小的数据结构,例如卷积矩阵、转置矩阵等。

        也有说法是:仅当您对图像执行一些十分耗时的操作时,使用透明 API才有意义。否则,将图像copy到GPU的开销的时间也是不短的,这一点需要考虑。

以上是关于Opencv学习笔记 - 关于OpenCV的UMat 类的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 学习笔记(Watershed)

OpenCv关于灰度积分图的SSE代码学习和改进。

《OpenCV3编程入门》学习笔记三:HighGUI图形用户界面

OpenCV 学习笔记(mean shift 算法)

OpenCV 学习笔记(提取图像中特定颜色区域)

OpenCV的学习笔记