使用 RGBA 通道顺序的像素数据初始化 OpenCV Mat

分享于2022年07月17日 c++ opencv 问答
【问题标题】:使用 RGBA 通道顺序的像素数据初始化 OpenCV Mat(Initialize an OpenCV Mat with pixel data in RGBA channel order)
【发布时间】:2022-07-10 23:21:38
【问题描述】:

你好,

我正在用 C++ 为 Adob​​e After Effects 编写一个效果插件,我需要使用内存中已经存在的像素数据创建一个 cv::Mat 。但是,当我使用以下方法对其进行初始化时:

cv::Mat in_frame_mat(height, width, CV_8UC4, input->data);

(输入->数据是指向第一个字节的指针),输出全是蓝色。
我认为这是因为 AE 存储像素数据 RGBA 或 ARGB,而 OpenCV 假定为 BGRA 或 ABGR(不确定是哪个)。

我知道我可以遍历每个像素并在内存中创建一个新空间来存储图像的 BGRA 表示,然后使用 that 初始化 cv::Mat ,但这确实是性能受限而且我不想增加不必要的计算时间。

有没有办法使用存储 RGBA 的现有像素数据创建 cv::Mat

谢谢!

  • 好吧, cvtColor -- 你的处理可能不在乎, 在你用 imshow / imread 看图片时在乎。做你的事并保持频道秩序。在 AE 中它不会是蓝色的。
  • @ChristophRackwitz 我想到了这一点,但是我想在垫子上进行的处理需要它具有正确的色彩空间。我最终编写了自己的函数来转换色彩空间。

【解决方案1】:

OpenCV 假设通道顺序是 BGR (或 BGRA )。

您可以使用 cv::cvtColor 将您的输入更改为 BGRA。 第三个参数 code 应该是来自 cv::ColorConversionCodes 的值之一,例如: cv::COLOR_RGBA2BGRA (似乎是你需要的)。


更新:

根据 OP 在下面的评论,他的输入实际上是 ARGB(不是 RGBA):
cv::cvtColor 不支持 ARGB 转 BGRA。
但是您可以使用 cv:mixChannels 对通道进行任意重新排序( fromTo 参数指定重新排序)。

见下文如何使用它将 ARGB 转换为 BGRA

#include 
cv::Mat argb; // initialized from your input data
cv::Mat bgra(argb.size(), argb.type());
std::vector fromTo{ 0,3, 1,2, 2,1, 3,0 };  // ARGB->BGRA: 0->3, 1->2, 2->1, 3->0
cv::mixChannels(argb, bgra, fromTo);

如果您的 OpenCV 版本不支持这种风格的 cv::mixChannels (与 std::vector 等),您可以尝试:

cv::Mat argb; // initialized from your input data
cv::Mat bgra(argb.size(), argb.type());
int fromTo[] = { 0,3, 1,2, 2,1, 3,0 };    // ARGB->BGRA: 0->3, 1->2, 2->1, 3->0
cv::mixChannels(&argb, 1, &bgra, 1, fromTo, 4);

更新 2:

为了将 ARGB 转换为 BGR (即没有 alpha 通道),您可以通过以下方式使用 cv::mixChannels

#include 
cv::Mat argb; // initialized from your input data
cv::Mat bgr(argb.size(), CV_8UC3); // NOTE: the type is CV_8UC3, not argb.type()
std::vector fromTo{ 1,2, 2,1, 3,0 };  // ARGB->BGR: 1->2, 2->1, 3->0
cv::mixChannels(argb, bgr, fromTo);

  • 谢谢。不幸的是,事实证明 After Effects 确实使用 ARGB,因此似乎没有办法使用 cv::cvtColor 将其转换为 BGR。我可能最终会编写一个函数来手动完成。
  • @jonahclarsen - 原来您不必手动操作 - 请参阅我的答案的更新。
  • 太棒了 - 有效。非常感谢!这样可以减少 19 行代码。不幸的是,它比手动操作要慢一些。我认为这是因为我不需要透明度数据,所以当我手动复制它时,我不必触摸 alpha 通道(ARGB->BGR)。我尝试修改此解决方案以不触及 alpha 通道(通过将输入解释为 CV_8UC3 而不是 CV_8UC4 并删除“, 3, 0”)但我无法让它工作,它要么创建损坏的图像要么崩溃。
  • @jonahclarsen - 我在答案中添加了第二次更新,使用 cv::mixChannels 转换 ARGB -> BGR。