RK3588 RGA 图像操作

这篇具有很好参考价值的文章主要介绍了RK3588 RGA 图像操作。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

公司业务需要用到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

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

2.2 图像缩放或者放大

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

RK3588 RGA 图像操作

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

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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的基础上进行改动、验证。
RK3588 RGA 图像操作
代码功能:文章来源地址https://www.toymoban.com/news/detail-438743.html

  1. 打开宏定义BGR2NV12 ,使用opencv读取本地1.jpg图片,调用RGA imcvtcolor 接口实现BGR到YUV的转换;
  2. 关闭宏定义BGR2NV12,读取YUV文件,调用RGA imcvtcolor 接口实现YUV到BGR的转换;
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

到了这里,关于RK3588 RGA 图像操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RK3588开发板的入门指南:如何开始在RK3588开发板上进行安卓开发?

    RK3588是一款适用于Android系统的芯片,同时也是开发嵌入式系统的理想选择。本文将介绍如何开始在RK3588开发板上进行安卓开发,以及一些需要了解的基本知识和工具。 首先,需要准备一个RK3588开发板,一台运行Windows或Linux操作系统的计算机,以及一些必要的开发工具。这些

    2024年02月09日
    浏览(46)
  • RK3588-MIPI屏幕调试笔记:RK3588-MIPI-DSI之LCD上电初始化时序

    mipi屏调试一般都要在RK平台的dts中配置屏幕上电初始化时序 :panel-init-sequence和下电初始化时序:panel-exit-sequence。本文讲解如何配置屏幕的这些初始化时序。 注意:这里的parameter并不是指数据字节个数 0x05 命令类型:(DCS Short Write, no parameters) 0x15 命令类型:(DCS Short Write, 1 p

    2024年02月12日
    浏览(92)
  • RK3588电池以及充电

    目录 前言 一、硬件部分 二、软件部分 三、调试 四、问题 最近几天在rk3588平台上调试电池以及充电,记录下调试bq25703+cw2015的过程

    2024年02月11日
    浏览(44)
  • RK3588使用openCL

    一、opecnCL简介         OpenCL(全称Open Computing Language,开放运算语言)是第一个面向异构系统通用目的并行编程的开放式、免费标准,也是一个统一的编程环境,便于软件开发人员为高性能计算服务器、桌面计算系统、手持设备编写高效轻便的代码,而且广泛适用于多核

    2024年02月07日
    浏览(73)
  • rk3588使用gstreamer推流

    在https://launchpad.net/上搜索软件名+ppa 找到需要的包后下面命令安装 如果不需要了下面命令删除 查看支持的编码器 不支持rkmpp的硬编码 下面安装插件gstreamer1.0-rockchip 这时已经支持硬件编码了 播放本地视频mp4 查找设备 播放视频画面 rk3588 硬件编码mpph264enc,使用gstreamer udp 传输

    2024年02月16日
    浏览(67)
  • RK3588 CPU性能优化

    CPU负载的采样时间关系到CPU的变频和大小核调度的及时性,目前系统的默认配置是32ms,可以通过如下节点获取: 目前的采用时间可以设置为32ms和8ms,在8ms的情况下cpu的负载变频和大小核调度会更及时,但是同时功耗也会对应的增加; 可以通过如下命令进行设置: 如果要在

    2024年02月12日
    浏览(54)
  • RK3588适配Ubuntu系统

            RKsdk上支持buildroot以及Debian系统,但是Ubuntu需要自己移植,有很多公司都移植好了可以直接用,这里就总结记录一下我制作Ubuntu的过程。 http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.1-base-arm64.tar.gz 这里我选择的是Ubuntu20.04,直接下载至指定本地文件夹

    2024年02月09日
    浏览(56)
  • RK3588通用布线设计指南

    (1)走线长度应包含过孔和封装。 (2) 由于表贴器件的焊盘会导致阻抗降低,为减小阻抗突变的影响,建议在表贴焊盘的正下方按焊盘大小挖去一层参考层。 常用的表贴器件有:电容、 ESD、共模抑制电感、连接器等等。 (3)建议走线距离同层的地铜皮大等于 4 倍线宽。

    2023年04月08日
    浏览(33)
  • rk3588-云手机-docker

    拉取安卓镜像:docker pull suyunfei-docker.pkg.coding.net/docker/test/dobox12.0.0:rk3588-015 创建启动安卓:docker run -itd --name=syf1 --privileged -v /data/android_data/syf1:/data -p 5501:5555 suyunfei-docker.pkg.coding.net/docker/test/dobox12.0.0:rk3588-019 目前测试 8开安卓 同时使用 很好 3588 gpu性能还是偏弱 8开中大型游戏

    2024年02月14日
    浏览(90)
  • 启航RK3588边缘计算之旅:保定飞凌OK3588开发板

    一、飞凌嵌入式公司简介 飞凌嵌入式技术有限公司(Forlinx Embedded Technology Co., Ltd)是一家专注于嵌入式核心控制系统研发与制造的高新技术企业,创建于2006年。公司总部位于河北省保定市,并在北京和深圳分别设立了研发中心和华南技术服务中心。多年来,他们始终坚持技

    2024年02月15日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包