关键词:RK3588、RGA、 V4L2、 OPENCV、HTOP、MEN
前言
近期尝试降低在边缘端部署对芯片的资源消耗,合理应用各类子芯片功能时尝试将opencv逐渐进行替代。思考opencv在项目中主要承担读取usb摄像头、图像颜色通道更换和图像尺寸的修改功能点,经查阅搜索发现在RK3588中然后在对应的硬件中这些都有对应的独立硬件可以实现,故编辑此文以作记录。
V4L2
V4L2(Video for Linux 2) 是为了在Linux系统中操作视频设备而设计的一套API接口。它使得不同型号和厂商的视频设备,尤其是摄像头,在Linux系统中能被统一操作,从而降低了驱动程序开发的复杂性。使用V4L2可以很好了的对opencv函数中的VideoCapture函数进行替代获取图像数据指针uchar*。
使用V4L2读取摄像头数据的流程:打开设备、查询功能、设置视频格式、申请缓冲区、内存映射、采集启动、数据处理
使用jpeg解码核心代码如下:
int read_JPEG_file (const unsigned char *jpegData, unsigned char *rgbdata, int size)
{
struct jpeg_error_mgr jerr;
struct jpeg_decompress_struct cinfo;
cinfo.err = jpeg_std_error(&jerr);
//1创建解码对象并且初始化
jpeg_create_decompress(&cinfo);
//2.装备解码的数据
//jpeg_stdio_src(&cinfo, infile);
jpeg_mem_src(&cinfo,(const unsigned char*)jpegData, size);
//3.获取jpeg图片文件的参数
(void) jpeg_read_header(&cinfo, TRUE);
/* Step 4: set parameters for decompression */
//5.开始解码
(void) jpeg_start_decompress(&cinfo);
//6.申请存储一行数据的内存空间
int row_stride = cinfo.output_width * cinfo.output_components;
unsigned char *buffer = (unsigned char *)malloc(row_stride);
int i=0;
while (cinfo.output_scanline < cinfo.output_height) {
//printf("****%d\n",i);
(void) jpeg_read_scanlines(&cinfo, &buffer, 1);
memcpy(rgbdata+i*640*3, buffer, row_stride );
i++;
}
//7.解码完成
(void) jpeg_finish_decompress(&cinfo);
//8.释放解码对象
jpeg_destroy_decompress(&cinfo);
return 1;
}
在上述代码中使用的是系统驱动进行的软解码,在RK3588中是可以进行硬解码。在本文中未介绍硬解码,硬解码阶段在后续文章中将会提到,敬请期待。
RGA模块
上篇文章中提到了RGA模块可以实现对图像数据的缩放以及改变通道,这两个核心函数对应opencv的resize和cvtColor。由于需要比对实验,所以在RGA中使用了对应的模块实现了图像的缩放和通道转换(PS:V4L2读取的数据是BGR格式,显示时往往是RGB,所以需要BGR2RGB操作)。
不过在RGA模块的使用中需要注意的是RGA模块中封装的函数图像数据的输入是char* 格式输出也是char* 格式,然而无论是opencv或是v4l2读取的数据都是unsigned char* 这个时候就需要对unsigned char* 和 char* 之间进行转换。
unsigned char* 与 char* 互转
oup_unsigned_char = reinterpret_cast<char*>(inp_data); // uchar2char
inp_char = reinterpret_cast<unsigned char*>(inp_data); // char2uchar
测试记录
为了更严谨的比对OPENCV资源消耗与V4L2+RGA的比对,这里使用了一组空白对照组(Ps:重启设备后htop显示截图)
空白对照组
opencv
v4l2软解+rga
通过上述图像中的数据显示:
- 在重启后linux系统,系统不启动V4L2和opencv对应的二进制程序,此时消耗MEN=604M;
- 在重启后linux系统,使用opencv对应二进制程序,此时消耗MEN=718M,多核启动运行 ;
- 在重启后linux系统,使用v4l2软解+rga对应二进制程序,此时消耗MEN=663M,单核启动运行
查阅资料得知opencv的cpu消耗问题是由于opencv是采用多核运行,故而对cpu的占用较多,而v4l2是采用的cpu进行软解码,且在单一核中进行,对资源消耗在htop中查看并没有opencv消耗的那么多。
参考文章: