RGBA色彩空间和Alpha通道
RGBA是代表Red(红色)Green(绿色)Blue(蓝色)和Alpha的色彩空间,虽然它有的时候被描述为一个颜色空间,但是它其实仅仅是在RGB色彩空间上附加了额外的Alpha通道。在计算机图形学中,一个RGB色彩空间的图形,是由红、绿、蓝三个色彩信息通道合成的,每个通道用了8位色彩深度,共计24位,包含了所有彩色信息。为实现图形的透明效果,采取在图形文件的处理与存储中附加上另一个8位信息的方法,这个附加的代表图形中各个素点透明度的通道信息就被叫做Alpha通道。
Alpha通道使用8位二进制数,可以表示256级灰度,取值范围是0~255。值为255的Alpha像素用以定义不透明的彩色像素,而值为0的Alpha通道像素用以定义透明像素,介于黑白之间的灰度(值为30-255)的Alpha像素用以定义不同程度的半透明像素。
处理带Alpha通道的透明图片
在使用OpenCV的imread()读取带透明部分的.png图片时,相对于jpg图片的直接读取,需要处理其alpha通道。如果直接以imread("图片路径", -1)的方式来读取而不作任何处理,直接imshow()出来的图片的透明部分会被自动生成的噪点覆盖。
原图(马赛克为透明部分):
未处理Alpha通道直接加载出来,透明部分被覆盖:
因此要表现图片的透明情况,只能将其与其他图片叠时才能反映出来,通常是将一个抠过图的透明元素加载到背景中,这也是png格式透明图片在OpenCV中用到的最多的地方。
演示 :将一张背景透明的人物图叠加到背景图上
人物图(png格式,人物后面的马赛克为透明部分):
背景图:
代码示例:
#include <opencv2/opencv.hpp>
using namespace cv;
void imageOverlay(const Mat &srcImage, Mat &dstImage, int x, int y); // 图像叠加函数的定义
int main()
{
// 创建两个图像矩阵,分别是要融合的人物和背景
Mat people, background;
people = imread("/home/efort/Downloads/people.png", -1); // 此处要加上参数-1
background = imread("/home/efort/Downloads/background.jpg");
// 表示从背景的第(150, 267)开始设置对人物的叠加
imageOverlay(people, background, 150, 267);
imshow("富士山下", background);
waitKey(0);
return 0;
}
// 图像叠加函数的实现
void imageOverlay(const Mat &people, Mat &background, int x, int y)
{
int channelNum = 3; // rgb通道数为3
int alpha = 0; // alpha值表示图像透明度,0代表完全透明,1代表完全不透明
for (int i = 0; i < people.rows; i++)
{
for(int j = 0; j < people.cols * 3; j += 3)
{
alpha = people.ptr<uchar>(i)[j / 3*4 + 3];
if(alpha != 0)
{
for (int k = 0; k < 3; k++)
{
// jpg不存在alpha通道,所以给读取出来的数组增加一个alpha的维度
if( (i+y < background.rows) && (i+y>=0) &&
((j+x*3) / 3*3 + k < background.cols*3) && ((j+x*3) / 3*3 + k >= 0) &&
(i/channelNum*4 + k < background.cols*4) && (j/channelNum*4 + k >=0) )
{
background.ptr<uchar>(i+y)[(j+x*channelNum) / channelNum*channelNum + k] = people.ptr<uchar>(i)[(j) / channelNum*4 + k];
}
}
}
}
}
}
叠加后的运行结果如下: