Opencv: Alpha融合
Alpha融合
Alpha融合是一种将前景通过透明度叠加到背景上的过程。透明度通常是图像的第四通道,当然也可以被分离出来成为一个单独的图像。这个透明的掩模通常被称为alpha掩模。
在上述图片中,左上是前景图片;右上是灰度alpha掩模;左下是背景图片,右下是融合结果。alpha融合背后的数学原理是相当直接的。在每一个像素位置,利用alpha模板(a)来融合前景图值和背景图像值。
以上的alpha模板的像素值实际计算的时候会从[0,255] 被归一化到[0,1]。从以上的等式我们知道:
1. 当a=0, 输出的像素值属于背景。
2. 当a=1, 输出的像素值属于前景。
3. 当0<a<1,输出像素值是前背景的混合 ,为何融合效果更自然,通常在alpha模板的边界上的像素值是位于0到1之间。
如何在Opencv中应用alpha融合
#include opencv2/opencv.hpp
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// 图像读取
Mat foreground = imread("puppets.png");
Mat background = imread("ocean.png");
Mat alpha = imread("puppets_alpha.png");
// 将数据转换成浮点型
foreground.convertTo(foreground, CV_32FC3);
background.convertTo(background, CV_32FC3);
// 将alpha掩模的灰度值归一化到[0,1]
alpha.convertTo(alpha, CV_32FC3, 1.0/255); //
// 存储输出图像
Mat ouImage = Mat::zeros(foreground.size(), foreground.type());
// 将前景像素与掩模相乘
multiply(alpha, foreground, foreground);
// 将背景与( 1 - alpha )相乘
multiply(Scalar::all(1.0)-alpha, background, background);
// 将上述两个操作的结果相加
add(foreground, background, ouImage);
//显示图像 imshow("alpha blended image", ouImage/255);
waitKey(0);
return 0;
}
上述代码简洁,但并不高效,可以采用以下方式来提高效率:
#include opencv2/opencv.hpp
using namespace cv;
using namespace std;
//先定义一个融合函数
void alphaBlend(Mat& foreground, Mat& background, Mat& alpha, Mat& outImage)
{
// 计算像素数量
int numberOfPixels = foreground.rows * foreground.cols * foreground.channels();
// Get floating point pointers to the data matrices
float* fptr = reinterpret_cast<float*>(foreground.data);
float* bptr = reinterpret_cast<float*>(background.data);
float* aptr = reinterpret_cast<float*>(alpha.data);
float* outImagePtr = reinterpret_cast<float*>(outImage.data);
// 一次性循环所有像素
for(
int i = 0;
i < numberOfPixels;
i++, outImagePtr++, fptr++, aptr++, bptr++
)
{
*outImagePtr = (*fptr)*(*aptr) + (*bptr)*(1 - *aptr);
}
}
int main(int argc, char** argv)
{
// 输入
Mat foreground = imread("puppets.png");
Mat background = imread("ocean.png");
Mat alpha = imread("puppets_alpha.png");
//定义输出
Mat ouImage = Mat::zeros(foreground.size(), foreground.type());
//融合操作
alphaBlend(foreground,background , alpha , ouImage)
// 显示图像
imshow("alpha blended image", ouImage/255);
waitKey(0);
return 0;
}