Skip to main content

色彩转换

这里我们把从mipi摄像头读取到的NV12数据, 使用RGA转换成BGR格式。

首先, 确保DMA buffer能正常使用, 详细请查看RGA DMA.

1. RGA NV12转BGR

使用DMA buffer后, 直接传递其handle, 代码如下:

  • src_fd, 输入图片DMA句柄。
  • src_size, 输入DMA大小。
  • dst_fd, 转换后输出DMA句柄。
  • dst_size, 输出DMA大小。
  • width, 输入图片的宽。
  • height, 输入图片的高。
int rga_nv12_fd_to_bgr_fd(int src_fd, int src_size, int dst_fd, int dst_size, int width, int height) {
// 计算对齐后的 wstride(水平 stride)
int wstride = (width + 15) & ~15; // 对齐到 16 像素

rga_buffer_handle_t src_handle = importbuffer_fd(src_fd, src_size);
rga_buffer_handle_t dst_handle = importbuffer_fd(dst_fd, dst_size);
if (!src_handle || !dst_handle) {
if (src_handle) releasebuffer_handle(src_handle);
if (dst_handle) releasebuffer_handle(dst_handle);
cerr << "importbuffer_fd failed\n";
return -1;
}

// 使用 wrapbuffer_handle 初始化基本字段(width, height, fd, handle 等)
rga_buffer_t src = wrapbuffer_handle(src_handle, width, height, RK_FORMAT_YCbCr_420_SP);
rga_buffer_t dst = wrapbuffer_handle(dst_handle, width, height, RK_FORMAT_BGR_888);

src.wstride = wstride; // 水平行跨距(Y 和 UV 平面都用这个)
src.hstride = height; // 垂直 stride,通常等于 height(除非特殊对齐要求)

dst.wstride = wstride;
dst.hstride = height;

// 检查参数
int ret = imcheck(src, dst, {}, {});
if (IM_STATUS_NOERROR != ret) {
cerr << "imcheck error: " << imStrError((IM_STATUS)ret) << endl;
releasebuffer_handle(src_handle);
releasebuffer_handle(dst_handle);
return -1;
}

// 执行颜色转换
ret = imcvtcolor(src, dst, RK_FORMAT_YCbCr_420_SP, RK_FORMAT_BGR_888);
if (ret != IM_STATUS_SUCCESS) {
cerr << "imcvtcolor failed: " << imStrError((IM_STATUS)ret) << endl;
releasebuffer_handle(src_handle);
releasebuffer_handle(dst_handle);
return -1;
}

// 释放 handle(DMA-BUF 引用不受影响)
releasebuffer_handle(src_handle);
releasebuffer_handle(dst_handle);
return 0;
}

2. V4L2 + RGA demo

使用V4L2获取mipi摄像头的NV12数据, 再把NV12使用RGA转换成BGR, 最后使用OpenCV显示到屏幕, 完整的demo请查看V4L2-CAMERA

|-----------| RGA |----------|
| NV12 data | ----> | BGR data | ----> RKNN or X11...
|-----------| |----------|

也可以从此处下载完整的代码。