背景

公司业务需要用到RK3588 的RGA进行图像处理加速,网上搜了下,这方面的资料很少,在此记录下自己从熟悉文档到应用的整个过程,给有相关需求的小伙伴做个参考。

一、什么是RGA

RGA (Raster Graphic Acceleration Unit)是一个独立的2D硬件加速器,可用于加速点/线绘制,执行图像缩放、旋转、格式转换等常见的2D图形操作。

二、RK3588 RGA及代码示例

2.1 从git拉取官方文档及sample示例

git clone https://github.com/airockchip/librga

cd librga

其中 include 是相关头文件,libs是运行库,samples是代码示例。注意:官方demo是有默认的验证源文件,开始前先看下图对应的md文件。

2.2 图像缩放或者放大

本示例代码是在官方resize_demo的基础上进行改动、验证。说明:因为是Debian系统,安装opencv会报错,缺少libjasper库。网上搜了下比较麻烦,本人使用的先在Ubuntu先编译好的opencv库。

代码功能:使用opencv读取本地 1.jpg 图片,调用RGA resize接口进行图片缩小和放大,再使用opencv保存为新的文件。BIG宏定义是用来执行控制放大还缩操作。

#include

#include

#include

#include

#include "im2d_version.h"

#include "im2d_type.h"

#include "im2d_single.h"

#include "im2d_common.h"

#include "im2d_buffer.h"

#include "RgaUtils.h"

#include "src/utils/utils.h"

#include "./opencv2/core/core.hpp"

#include "./opencv2/highgui/highgui.hpp"

using namespace std;

using namespace cv;

#define BIG

#ifdef BIG

#define RESIZE_WIDTH 1920

#define RESIZE_HEIGHT 1080

#define SCALE_NAME "./scale_1920_1080.jpg"

#else

#define RESIZE_WIDTH 640

#define RESIZE_HEIGHT 480

#define SCALE_NAME "./zoom_640_480.jpg"

#endif

int main(int argc, char **argv)

{

clock_t t1, t2;

t1 = clock();

int ret = 0;

int src_width, src_height, src_format;

int dst_width, dst_height, dst_format;

char *src_buf, *dst_buf;

int src_buf_size, dst_buf_size;

rga_buffer_t src_img, dst_img;

rga_buffer_handle_t src_handle, dst_handle;

memset(&src_img, 0, sizeof(src_img));

memset(&dst_img, 0, sizeof(dst_img));

Mat image, res;

image = imread("./1.jpg");

if (image.data == nullptr)

{

cout << "图片文件不存在" << endl;

}

cout << "图像宽为:" << image.cols << "\t高度为:" << image.rows << "\t通道数为:" << image.channels() << endl;

src_width = image.cols;

src_height = image.rows;

src_format = RK_FORMAT_BGR_888;

// src_format = RK_FORMAT_RGBA_8888; // RK_FORMAT_YCbCr_420_SP

dst_width = RESIZE_WIDTH;

dst_height = RESIZE_HEIGHT;

dst_format = RK_FORMAT_BGR_888;

src_buf_size = src_width * src_height * get_bpp_from_format(src_format);

dst_buf_size = dst_width * dst_height * get_bpp_from_format(dst_format);

cout << " src format: " << get_bpp_from_format(src_format) << endl;

cout << " dst format: " << get_bpp_from_format(dst_format) << endl;

src_buf = (char *)malloc(src_buf_size);

dst_buf = (char *)malloc(dst_buf_size);

memcpy(src_buf, image.data, src_width * src_height * get_bpp_from_format(src_format));

memset(dst_buf, 0x80, dst_buf_size);

src_handle = importbuffer_virtualaddr(src_buf, src_buf_size);

dst_handle = importbuffer_virtualaddr(dst_buf, dst_buf_size);

if (src_handle == 0 || dst_handle == 0) {

printf("importbuffer failed!\n");

// goto release_buffer;

return -1;

}

src_img = wrapbuffer_handle(src_handle, src_width, src_height, src_format);

dst_img = wrapbuffer_handle(dst_handle, dst_width, dst_height, dst_format);

ret = imcheck(src_img, dst_img, {}, {});

if (IM_STATUS_NOERROR != ret) {

printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));

return -1;

}

printf("%d, check success \n", __LINE__);

ret = imresize(src_img, dst_img);

if (ret == IM_STATUS_SUCCESS) {

printf("imresize running success!\n");

} else {

printf("running failed, %s\n", imStrError((IM_STATUS)ret));

// goto release_buffer;

return -1;

}

t2 = clock();

double time_use = (double)(t2 - t1) / CLOCKS_PER_SEC; // 微秒

printf("vptdt_init time_use is [%f] s\n", time_use);

res.create(RESIZE_HEIGHT, RESIZE_WIDTH, CV_8UC3);

memcpy(res.data, dst_buf, RESIZE_HEIGHT*RESIZE_WIDTH*3);

cv::imwrite(SCALE_NAME, res);

printf("save picture: [ %s ] success\n", SCALE_NAME);

release_buffer:

if (src_handle)

releasebuffer_handle(src_handle);

if (dst_handle)

releasebuffer_handle(dst_handle);

if (src_buf)

free(src_buf);

if (dst_buf)

free(dst_buf);

return ret;

return 0;

}

2.2 图像格式转换

本示例代码是在官方cvtcolor_demo的基础上进行改动、验证。 代码功能:

打开宏定义BGR2NV12 ,使用opencv读取本地1.jpg图片,调用RGA imcvtcolor 接口实现BGR到YUV的转换;关闭宏定义BGR2NV12,读取YUV文件,调用RGA imcvtcolor 接口实现YUV到BGR的转换;

#include

#include

#include

#include

#include "im2d_version.h"

#include "im2d_type.h"

#include "im2d_single.h"

#include "im2d_common.h"

#include "im2d_buffer.h"

#include "RgaUtils.h"

#include "src/utils/utils.h"

#include "./opencv2/core/core.hpp"

#include "./opencv2/highgui/highgui.hpp"

#include "./opencv4/opencv2/opencv.hpp"

using namespace std;

using namespace cv;

#define TRANSFER_FILE "./transfer.YUV"

#define RGA_WRITE_FILE "./rga_res.jpg"

#define OPENCV_WRITE_FILE "./opecv_res.jpg"

#define BGR2NV12

// #define OPENCV_TRANSFER

int main(int argc, char **argv)

{

int ret = 0;

int src_width, src_height, src_format;

int dst_width, dst_height, dst_format;

char *src_buf, *dst_buf;

int src_buf_size, dst_buf_size;

rga_buffer_t src_img, dst_img;

rga_buffer_handle_t src_handle, dst_handle;

memset(&src_img, 0, sizeof(src_img));

memset(&dst_img, 0, sizeof(dst_img));

#ifdef BGR2NV12

clock_t t1, t2;

t1 = clock();

Mat image, res;

image = imread("./1.jpg");

if (image.data == nullptr)

{

cout << "图片文件不存在" << endl;

}

cout << "图像宽为:" << image.cols << "\t高度为:" << image.rows << "\t通道数为:" << image.channels() << endl;

src_width = image.cols;

src_height = image.rows;

src_format = RK_FORMAT_BGR_888;

dst_width = image.cols;

dst_height = image.rows;

dst_format = RK_FORMAT_YCbCr_420_SP; // NV12

cout << " src format: " << get_bpp_from_format(src_format) << endl;

cout << " dst format: " << get_bpp_from_format(dst_format) << endl;

src_buf_size = src_width * src_height * get_bpp_from_format(src_format);

dst_buf_size = dst_width * dst_height * get_bpp_from_format(dst_format);

src_buf = (char *)malloc(src_buf_size);

dst_buf = (char *)malloc(dst_buf_size);

memcpy(src_buf, image.data, src_width * src_height * get_bpp_from_format(src_format));

memset(dst_buf, 0x80, dst_buf_size);

src_handle = importbuffer_virtualaddr(src_buf, src_buf_size);

dst_handle = importbuffer_virtualaddr(dst_buf, dst_buf_size);

if (src_handle == 0 || dst_handle == 0)

{

printf("importbuffer failed!\n");

if (src_handle)

releasebuffer_handle(src_handle);

if (dst_handle)

releasebuffer_handle(dst_handle);

if (src_buf)

free(src_buf);

if (dst_buf)

free(dst_buf);

return ret;

}

src_img = wrapbuffer_handle(src_handle, src_width, src_height, src_format);

dst_img = wrapbuffer_handle(dst_handle, dst_width, dst_height, dst_format);

ret = imcheck(src_img, dst_img, {}, {});

if (IM_STATUS_NOERROR != ret)

{

printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));

return -1;

}

// ret = imcvtcolor(src_img, dst_img, src_format, dst_format, IM_RGB_TO_YUV_BT709_LIMIT);

ret = imcvtcolor(src_img, dst_img, src_format, dst_format, IM_RGB_TO_YUV_BT709_LIMIT);

if (ret == IM_STATUS_SUCCESS)

{

printf("imcvtcolor running success!\n");

}

else

{

printf("imcvtcolo rrunning failed, %s\n", imStrError((IM_STATUS)ret));

if (src_handle)

releasebuffer_handle(src_handle);

if (dst_handle)

releasebuffer_handle(dst_handle);

if (src_buf)

free(src_buf);

if (dst_buf)

free(dst_buf);

return ret;

}

t2 = clock();

double time_use = (double)(t2 - t1) / CLOCKS_PER_SEC; // 微秒

printf("imcvtcolo to YUV time_use is [%f] s\n", time_use);

FILE *file = fopen(TRANSFER_FILE, "wb+");

if (!file)

{

fprintf(stderr, "Could not open %s\n", TRANSFER_FILE);

return false;

}

else

{

fprintf(stderr, "open %s and write ok\n", TRANSFER_FILE);

}

fwrite(dst_buf, image.cols * image.rows * get_bpp_from_format(dst_format), 1, file);

fclose(file);

#else

src_width = 1920;

src_height = 1080;

src_format = RK_FORMAT_YCbCr_420_SP; // NV12

#ifdef OPENCV_TRANSFER

cout << " src format: " << get_bpp_from_format(src_format) << endl;

src_buf_size = src_width * src_height * get_bpp_from_format(src_format);

src_buf = (char *)malloc(src_buf_size);

FILE *file = fopen(TRANSFER_FILE, "rb");

if (!file)

{

fprintf(stderr, "Could not open %s\n", TRANSFER_FILE);

return -EINVAL;

}

fread(src_buf, src_width * src_height * get_bpp_from_format(src_format), 1, file);

fclose(file);

cv::Mat yuvNV12, rgb24;

yuvNV12.create(src_height * 3 / 2, src_width, CV_8UC1);

memcpy(yuvNV12.data, src_buf, src_width*src_height * 3 / 2);

// trans to rgb24

cv::cvtColor(yuvNV12, rgb24, cv::COLOR_YUV2BGR_NV12);

cv::imwrite(OPENCV_WRITE_FILE, rgb24);

printf("[OPENCV] save picture: [ %s ] success\n", OPENCV_WRITE_FILE);

free(src_buf);

src_buf = NULL;

#else

clock_t t1, t2;

t1 = clock();

dst_width = 1920;

dst_height = 1080;

dst_format = RK_FORMAT_BGR_888;

cout << "src format: " << get_bpp_from_format(src_format) << endl;

cout << "dst format: " << get_bpp_from_format(dst_format) << endl;

src_buf_size = src_width * src_height * get_bpp_from_format(src_format);

dst_buf_size = dst_width * dst_height * get_bpp_from_format(dst_format);

src_buf = (char *)malloc(src_buf_size);

dst_buf = (char *)malloc(dst_buf_size);

FILE *file = fopen(TRANSFER_FILE, "rb");

if (!file)

{

fprintf(stderr, "Could not open %s\n", TRANSFER_FILE);

return -EINVAL;

}

fread(src_buf, src_width * src_height * get_bpp_from_format(src_format), 1, file);

fclose(file);

printf("read src file success!\n");

memset(dst_buf, 0x80, dst_buf_size);

src_handle = importbuffer_virtualaddr(src_buf, src_buf_size);

dst_handle = importbuffer_virtualaddr(dst_buf, dst_buf_size);

if (src_handle == 0 || dst_handle == 0)

{

printf("importbuffer failed!\n");

if (src_handle)

releasebuffer_handle(src_handle);

if (dst_handle)

releasebuffer_handle(dst_handle);

if (src_buf)

free(src_buf);

if (dst_buf)

free(dst_buf);

return ret;

}

src_img = wrapbuffer_handle(src_handle, src_width, src_height, src_format);

dst_img = wrapbuffer_handle(dst_handle, dst_width, dst_height, dst_format);

ret = imcheck(src_img, dst_img, {}, {});

if (IM_STATUS_NOERROR != ret)

{

printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));

return -1;

}

ret = imcvtcolor(src_img, dst_img, src_format, dst_format, IM_YUV_TO_RGB_BT709_LIMIT);

if (ret == IM_STATUS_SUCCESS)

{

printf("imcvtcolor running success!\n");

}

else

{

printf("imcvtcolo rrunning failed, %s\n", imStrError((IM_STATUS)ret));

if (src_handle)

releasebuffer_handle(src_handle);

if (dst_handle)

releasebuffer_handle(dst_handle);

if (src_buf)

free(src_buf);

if (dst_buf)

free(dst_buf);

return ret;

}

t2 = clock();

double time_use = (double)(t2 - t1) / CLOCKS_PER_SEC; // 微秒

printf("imcvtcolo YUV to BGR time_use is [%f] s\n", time_use);

Mat rgb24;

rgb24.create(src_height, src_width, CV_8UC3);

memcpy(rgb24.data, dst_buf, dst_width*dst_height*3);

cv::imwrite(RGA_WRITE_FILE, rgb24);

printf("[RGA] save picture: [ %s ] success\n", RGA_WRITE_FILE);

#endif // OPENCV_TRANSFER

#endif

return 0;

}

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: