When the image file is read with the OpenCV function imread() , the order of colors is BGR (blue, green, red). On the other hand, in Pillow, the order of colors is assumed to be RGB (red, green, blue). Therefore, if you want to use both the Pillow function and the OpenCV function, you need to convert BGR and RGB.
OpenCV follows BGR order, while matplotlib likely follows RGB order. Therefore, when we display an image loaded in OpenCV using matplotlib functions, we may want to convert it into RGB mode. If we did not switch brg order, we get rgb inverted picture.
The reason the early developers at OpenCV chose BGR color format is that back then BGR color format was popular among camera manufacturers and software providers. E.g. in Windows, when specifying color value using COLORREF they use the BGR format 0x00bbggrr.
What's the Difference between RGB versus BGR? The main difference between RGB versus BGR is the arrangement of the subpixels for Red, Green, and Blue. RGB is arranged like that, but BGR is essentially in reverse with no adverse effect on color vibrancy and accuracy.
The required operation can be accomplished by swapping the image channels using cv::mixChannels
as follows:
cv::Mat bgr, bgra;
//bgr initialization code here...
//.
//.
//.
cv::cvtColor(bgr, bgra, cv::COLOR_BGR2BGRA);
cv::Mat abgr(bgra.size(), bgra.type());
int from_to[] = { 0,3, 1,1, 2,2, 3,0 };
cv::mixChannels(&bgra,1,&abgr,1,from_to,4);
from_to
array is the mapping function which specifies which channels from source will be copied to which channels of the destination image. The pairs indicate that channel number 0
of the input will be copied to channel number 3
of the output, 1
to 1
, 2
to 2
, and channel number 3
will be copied to channel number 0
of the output.
Alternatively, we can split the image channels, swap the required channels and merge again. It can be done as follows:
cv::cvtColor(bgr, bgra, cv::COLOR_BGR2BGRA);
std::vector<cv::Mat> channels_bgra;
cv::split(bgra, channels_bgra);
std::vector<cv::Mat> channels_abgr = { channels_bgra[3], channels_bgra[1], channels_bgra[2], channels_bgra[0] };
cv::merge(channels_abgr, abgr);
OpenCV doesn't support ARGB or ABGR formats, so you will not be able to display it or use some of the functions on it... However, it is possible to create them with split and merge functions of OpenCV. Here is some code to explain what I mean.
cv::Mat src, final_image;
// fill src as you prefer
std::vector<cv::Mat> channels;
cv::split(src, channels); // this will put each channel in a mat in the vector
// swap or add channels in the vector
cv::Mat alpha(src.rows, src.cols, CV_8U, cv::Scalar(255));
channels.push_back(alpha);
std::reverse(channels.begin(), channels.end()); //needs <algorithm>
// merge the channels in one new image
cv::merge(channels, final_image);
This can be done faster (maybe it will be just shorter) with the function mixChannels, but I will say that this one is a little bit more confusing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With