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

4

你好,

我正在使用C++为Adobe After Effects编写一个效果插件,并且需要使用已经在内存中的像素数据创建cv::Mat。然而,当我使用以下方式进行初始化时:

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

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

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

有没有一种方法可以使用已存储RGBA的现有像素数据创建cv::Mat

谢谢!


好的,cvtColor -- 你的处理可能不在意,但 在调用 imshow/imread 来查看图片时会关心。只需按照自己的方式进行处理并保持通道顺序即可。在 AE 中它不会是蓝色的。 - Christoph Rackwitz
@ChristophRackwitz 我也考虑过这个问题,但是我需要对这个矩阵进行处理,所以必须确保它的颜色空间正确。最终我编写了自己的函数来转换颜色空间。 - jonahclarsen
1个回答

6

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 <vector>
cv::Mat argb; // initialized from your input data
cv::Mat bgra(argb.size(), argb.type());
std::vector<int> 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版本不支持这种带有std::vector等参数的cv::mixChannels函数,那么您可以尝试以下方法:

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 转换为没有 alpha 通道的 BGR,您可以使用以下方式的 cv::mixChannels

#include <vector>
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<int> 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
@jonahclarsen - 结果你不必手动操作 - 请查看我回答的更新。 - wohlstad
太棒了 - 这个方法可行。非常感谢!这样可以少写19行代码。不过,手动操作比这个方法稍微慢一些。我认为这是因为我不需要透明度数据,所以当我手动复制时,我不必触及Alpha通道(ARGB->BGR)。我尝试修改此解决方案以不触及Alpha通道(通过将输入解释为CV_8UC3而不是CV_8UC4并删除“,3,0”),但我无法使其正常工作,它要么创建损坏的图像,要么崩溃。 - jonahclarsen
@jonahclarsen - 我对我的答案进行了第二次更新,提供了使用 cv::mixChannels 将 ARGB 转换为 BGR 的方法。 - wohlstad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接