20190830-ARM Compute Library的使用--图像存取和转换

彭洲
2023-12-01

下载linux版本的arm-compute-library,解压出来即可使用。compute library支持neon和opencl方式,neon方式时利用原生的ARM的neon硬件进行加速。而opencl是一个并行计算框架,同时支持neon硬件和GPU硬件。由于现在使用的ARM的GPU还不支持OpenCL方式,因此就使用预编译库中的linux-armv7a-neon目录中的库文件。编译一个程序的命令如下:

arm-linux-gnueabihf-g++ examples/neon_convolution.cpp utils/Utils.cpp -I. -Iinclude -std=c++11 -mfpu=neon -L. -larm_compute -larm_compute_core -o neon_convolution

在eclipse中进行开发时,只需要像上面命名行一样配置好头文件目录,库文件目录以及库文件即可。

注意
当使用预编译版本的compute library时,在后面使用impott_memory出现段错误问题。所以按照官方法自行编译了neon版本的compute library,将动态库替换后问题得到解决。

图像的存取与转换

在Compute Library中数据都是按照张量的形式存储和使用的。数组为一维张量,图像为二维张量,而像神经网络中使用的卷积核可用三维张量描述。因此在Tensor.h中可以看到如下的一句:

using Image= Tensor;

也就是说Image是Tensor的一个别名而已。

图像读取

Compute Library在ImageLoader.h中提供了两个图像格式的文件读取类:PPMLoader和JPEGLoader,分别读取PPM和JPEG文件。它们读取图像的操作都很简单,以PPMLoader为列给出读取的代码:

Image img;
PPMLoader ppm;
ppm.open(filename);
ppm.init_image(img, Format::U8);    //根据图像文件尺寸和最终使用的图像格式,配置好img
img.allocator()->allocate();        //分配实际的存储空间
if(ppm.is_open())
    ppm.fill_image(img);            //将图像数据写入到img

JPEGLoader的使用是一样的。注意其中Format必须是U8或者RGB888。但看了一些功能使用的都是U8的格式。所以最好转为U8的格式。

图形的存储

在Utils.h中提供了一个函数用于将图像数据保持到PPM文件:

template <typename T>
void save_to_ppm(T &Tensor, const std::string &ppm_filename);

使用也很简单:

save_to_ppm(img, filename);     //img为Image对象

从已有memory配置Image对象

当处理来自摄像头的数据时,可能不需要再分配存储空间,直接使用原有的空间即可。而Image(Tensor)是支持的。代码如下:

Image img;
img.allocator()->init(TensorInfo(640,480, Format::YUYV422));       //这里假设读取到的摄像头数据是YUYV422格式的。
img.allocator()->import_memory((void*)mem);           //mem是指向摄像头数据地址的指针

YUYV422到RGB888的转换

之所以需要将YUYV422转换为RGB888是因为有很多摄像头的输出格式要么为YUYV422,要么为Motion-JPEG。而在图像处理时通常都是使用的RGB格式,因此必须进行格式的转换。
查看https://arm-software.github.io/ComputeLibrary/v19.05/文档,在右边的查找框中输入color可以列出一系列颜色格式转换的函数,其中便可以看到有我们所需要的YUYV到RGB的转换函数colorconvert_yuyv_to_rgb。但最终使用的是NEColorConvert.h中提供的NEColorConvert类提供的功能。

首先,假设摄像头数据存放在buffer_ptr指向的地址,并且已知图像的尺寸和格式为YUYV422,那么可以通过如下代码进行格式转换:

Image src_img, dst_img;
src_img.allocator()->init(TensorInfo(640,480,Format::YUYV422));
src_img.allocator()->import_memory(buffer_ptr);     //使用指向原始数据的指针
dst_img.allocator()->init(TensorInfo(640,480,Format::RGB888));
dst_img.allocator()->allocate();                    //分配一块空间,存放转换后的图像
NEColorConvert convert;
convert.configure(&src_img, &dst_img);
convert.run;    //执行转换
save_to_ppm(dst_img, "test.ppm");
 类似资料: