Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize an OpenCV Mat with pixel data in RGBA channel order

Tags:

c++

opencv

I am writing an effect plug-in for Adobe After Effects in C++, and I need to create a cv::Mat using pixel data that's already in memory. However, when I initialize it using:

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

(input->data is a pointer to the first byte), the output is all blue.
I think this is because AE stores pixel data RGBA or ARGB while OpenCV assumes BGRA or ABGR (not sure which).

I know that I could iterate through every pixel and create a new space in memory to store a BGRA representation of the image, then initialize a cv::Mat with that, but this is really performance constrained and I don't want to add unnecessary compute time.

Is there a way to create a cv::Mat using existing pixel data that is stored RGBA?

like image 509
jonahclarsen Avatar asked Sep 07 '25 08:09

jonahclarsen


1 Answers

OpenCV assumes the channel order is BGR (or BGRA).

You can use cv::cvtColor to change your input to BGRA. The 3rd parameter code should be one of the values from cv::ColorConversionCodes, e.g.: cv::COLOR_RGBA2BGRA (seems to be what you need).


Update:

Following the OP's comment below that his input is actually ARGB (not RGBA):
ARGB to BGRA is not supported by cv::cvtColor.
But you can use cv:mixChannels to do any arbitrary reordering of the channels (the fromTo parameter specifies the reordering).

See below how to use it to convert ARGB to 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);

If your OpenCV version does not support this flavor of cv::mixChannels (with std::vector etc.), you can try:

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);

Update 2:

In order to convert ARGB to BGR (i.e. without the alpha channel), you can use cv::mixChannels in the following way:

#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);
like image 95
wohlstad Avatar answered Sep 10 '25 02:09

wohlstad