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;
}
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值